diff --git a/package.json b/package.json index 05f125d..d52a25e 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ }, "private": true, "scripts": { + "start": "node index.js", "test": "node test.js" }, "author": "Markus Scully ", @@ -17,9 +18,11 @@ "box2d-html5": "^0.1.230", "colors": "^1.1.2", "express": "^4.13.4", + "jade": "^1.11.0", "poly-decomp": "git://github.com/schteppe/poly-decomp.js.git", "recursive-readdir": "^1.3.0", "socket.io": "^1.4.5", + "socket.io-client": "^1.4.5", "uglify-js": "^2.6.2", "uuid": "^2.0.1" } diff --git a/public/index.html b/public/index.html deleted file mode 100644 index da12e01..0000000 --- a/public/index.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - Wingbase - - - - - - - - - - - Sorry, your browser does not currently support HTML5 Canvas. - - - diff --git a/public/css/FreePixel.ttf b/public/static/css/FreePixel.ttf similarity index 100% rename from public/css/FreePixel.ttf rename to public/static/css/FreePixel.ttf diff --git a/public/css/styles.css b/public/static/css/styles.css similarity index 100% rename from public/css/styles.css rename to public/static/css/styles.css diff --git a/public/img/favicon.png b/public/static/img/favicon.png similarity index 100% rename from public/img/favicon.png rename to public/static/img/favicon.png diff --git a/public/img/favicon_large.png b/public/static/img/favicon_large.png similarity index 100% rename from public/img/favicon_large.png rename to public/static/img/favicon_large.png diff --git a/public/img/main.png b/public/static/img/main.png similarity index 100% rename from public/img/main.png rename to public/static/img/main.png diff --git a/public/img/ships/01/hull.png b/public/static/img/ships/01/hull.png similarity index 100% rename from public/img/ships/01/hull.png rename to public/static/img/ships/01/hull.png diff --git a/public/img/ships/01/hull_old.png b/public/static/img/ships/01/hull_old.png similarity index 100% rename from public/img/ships/01/hull_old.png rename to public/static/img/ships/01/hull_old.png diff --git a/public/img/ships/01/teama.png b/public/static/img/ships/01/teama.png similarity index 100% rename from public/img/ships/01/teama.png rename to public/static/img/ships/01/teama.png diff --git a/public/img/ships/01/teamb.png b/public/static/img/ships/01/teamb.png similarity index 100% rename from public/img/ships/01/teamb.png rename to public/static/img/ships/01/teamb.png diff --git a/public/img/ships/01/thrust0.png b/public/static/img/ships/01/thrust0.png similarity index 100% rename from public/img/ships/01/thrust0.png rename to public/static/img/ships/01/thrust0.png diff --git a/public/img/ships/01/thrust1.png b/public/static/img/ships/01/thrust1.png similarity index 100% rename from public/img/ships/01/thrust1.png rename to public/static/img/ships/01/thrust1.png diff --git a/public/img/ships/01/thrust2.png b/public/static/img/ships/01/thrust2.png similarity index 100% rename from public/img/ships/01/thrust2.png rename to public/static/img/ships/01/thrust2.png diff --git a/public/img/ships/01/thrust3.png b/public/static/img/ships/01/thrust3.png similarity index 100% rename from public/img/ships/01/thrust3.png rename to public/static/img/ships/01/thrust3.png diff --git a/public/img/ships/01/thrust4.png b/public/static/img/ships/01/thrust4.png similarity index 100% rename from public/img/ships/01/thrust4.png rename to public/static/img/ships/01/thrust4.png diff --git a/public/img/ships/01/thrust5.png b/public/static/img/ships/01/thrust5.png similarity index 100% rename from public/img/ships/01/thrust5.png rename to public/static/img/ships/01/thrust5.png diff --git a/public/img/ships/01/thrust6.png b/public/static/img/ships/01/thrust6.png similarity index 100% rename from public/img/ships/01/thrust6.png rename to public/static/img/ships/01/thrust6.png diff --git a/public/img/ships/01/thrust7.png b/public/static/img/ships/01/thrust7.png similarity index 100% rename from public/img/ships/01/thrust7.png rename to public/static/img/ships/01/thrust7.png diff --git a/public/img/ships/01/thrust8.png b/public/static/img/ships/01/thrust8.png similarity index 100% rename from public/img/ships/01/thrust8.png rename to public/static/img/ships/01/thrust8.png diff --git a/public/img/ships/01/thrust9.png b/public/static/img/ships/01/thrust9.png similarity index 100% rename from public/img/ships/01/thrust9.png rename to public/static/img/ships/01/thrust9.png diff --git a/public/img/turrets/01/large.png b/public/static/img/turrets/01/large.png similarity index 100% rename from public/img/turrets/01/large.png rename to public/static/img/turrets/01/large.png diff --git a/public/img/turrets/01/medium.png b/public/static/img/turrets/01/medium.png similarity index 100% rename from public/img/turrets/01/medium.png rename to public/static/img/turrets/01/medium.png diff --git a/public/img/turrets/01/small.png b/public/static/img/turrets/01/small.png similarity index 100% rename from public/img/turrets/01/small.png rename to public/static/img/turrets/01/small.png diff --git a/public/js/lib/box2dweb.min.js b/public/static/js/lib/box2dweb.min.js similarity index 100% rename from public/js/lib/box2dweb.min.js rename to public/static/js/lib/box2dweb.min.js diff --git a/public/static/js/lib/dexie.min.js b/public/static/js/lib/dexie.min.js new file mode 100644 index 0000000..7a3646b --- /dev/null +++ b/public/static/js/lib/dexie.min.js @@ -0,0 +1,3 @@ +!function(n,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):n.Dexie=t()}(this,function(){"use strict";function n(n,t){return"object"!=typeof t&&(t=t()),tn(t).forEach(function(e){n[e]=t[e]}),n}function t(t){return{from:function(e){return t.prototype=Object.create(e.prototype),t.prototype.constructor=t,{extend:function(r){n(t.prototype,"object"!=typeof r?r(e.prototype):r)}}}}}function e(n,t,e){return on.call(n,t,e)}function r(n,t){return t(n)}function i(n){var t=setTimeout(n,1e3);clearTimeout(t)}function o(n){if(!n)throw new exceptions.Internal("Assertion failed")}function u(n){rn.setImmediate?setImmediate(n):setTimeout(n,0)}function c(n,t){try{n()}catch(e){t&&t(e)}}function a(n){try{throw n}catch(t){return K.reject(n)}}function s(n,t){if(n.hasOwnProperty(t))return n[t];if(!t)return n;if("string"!=typeof t){for(var e=[],r=0,i=t.length;i>r;++r){var o=s(n,t[r]);e.push(o)}return e}var u=t.indexOf(".");if(-1!==u){var c=n[t.substr(0,u)];return void 0===c?void 0:s(c,t.substr(u+1))}}function f(n,t,e){if(n&&void 0!==t&&!("isFrozen"in Object&&Object.isFrozen(n)))if("string"!=typeof t&&"length"in t){o("string"!=typeof e&&"length"in e);for(var r=0,i=t.length;i>r;++r)f(n,t[r],e[r])}else{var u=t.indexOf(".");if(-1!==u){var c=t.substr(0,u),a=t.substr(u+1);if(""===a)void 0===e?delete n[c]:n[c]=e;else{var s=n[c];s||(s=n[c]={}),f(s,a,e)}}else void 0===e?delete n[t]:n[t]=e}}function l(n,t){"string"==typeof t?f(n,t,void 0):"length"in t&&[].map.call(t,function(t){f(n,t,void 0)})}function h(n){var t={};for(var e in n)n.hasOwnProperty(e)&&(t[e]=n[e]);return t}function d(n){if(!n||"object"!=typeof n)return n;var t;if(en(n)){t=[];for(var e=0,r=n.length;r>e;++e)t.push(d(n[e]))}else if(n instanceof Date)t=new Date,t.setTime(n.getTime());else{t=n.constructor?Object.create(n.constructor.prototype):{};for(var i in n)n.hasOwnProperty(i)&&(t[i]=d(n[i]))}return t}function p(n,t){var e={};for(var r in n)n.hasOwnProperty(r)&&(t.hasOwnProperty(r)?n[r]!==t[r]&&JSON.stringify(n[r])!=JSON.stringify(t[r])&&(e[r]=t[r]):e[r]=void 0);for(var r in t)t.hasOwnProperty(r)&&!n.hasOwnProperty(r)&&(e[r]=t[r]);return e}function v(){}function y(n){return n}function m(n,t){return n===y?t:function(e){return t(n(e))}}function b(n,t){return function(){n.apply(this,arguments),t.apply(this,arguments)}}function g(n,t){return n===v?t:function(){var e=n.apply(this,arguments);void 0!==e&&(arguments[0]=e);var r=this.onsuccess,i=this.onerror;this.onsuccess=null,this.onerror=null;var o=t.apply(this,arguments);return r&&(this.onsuccess=this.onsuccess?b(r,this.onsuccess):r),i&&(this.onerror=this.onerror?b(i,this.onerror):i),void 0!==o?o:e}}function w(n,t){return n===v?t:function(){var e=n.apply(this,arguments);void 0!==e&&extend(arguments[0],e);var r=this.onsuccess,i=this.onerror;this.onsuccess=null,this.onerror=null;var o=t.apply(this,arguments);return r&&(this.onsuccess=this.onsuccess?b(r,this.onsuccess):r),i&&(this.onerror=this.onerror?b(i,this.onerror):i),void 0===e?void 0===o?void 0:o:void 0===o?e:extend(e,o)}}function _(n,t){return n===v?t:function(){return n.apply(this,arguments)===!1?!1:t.apply(this,arguments)}}function x(n,t){return n===v?t:function(){return t.apply(this,arguments)===!1?!1:n.apply(this,arguments)}}function P(n,t){return n===v?t:function(){n.apply(this,arguments),t.apply(this,arguments)}}function S(n,t){return n===v?t:function(){var e=n.apply(this,arguments);if(e&&"function"==typeof e.then){var r=this,i=arguments;return e.then(function(){return t.apply(r,i)})}return t.apply(this,arguments)}}function D(n,t){this.name=n,this.message=t}function k(n,t){return n+". Errors: "+t.map(function(n){return n.toString()}).filter(function(n,t,e){return e.indexOf(n)===t}).join("\n")}function O(n,t,e,r){this.name="ModifyError",this.failures=t,this.failedKeys=r,this.successCount=e,this.message=k(n,t)}function E(n,t){this.name="BulkError",this.failures=t,this.message=k(n,t)}function C(n,t){var e=n;return n instanceof D||!n.name||!dn[n.name]||(e=new dn[n.name](t||n.message,n),n.stack&&(e.stack=n.stack)),e}function T(n){if(n.stack)return n;try{throw new Error}catch(t){n.stack=t.stack}return n}function I(n,t){function r(n,t,e){if(en(n))return o(n);if("object"==typeof n)return i(n);t||(t=_),e||(e=v);var r={subscribers:[],fire:e,subscribe:function(n){r.subscribers.push(n),r.fire=t(r.fire,n)},unsubscribe:function(n){r.subscribers=r.subscribers.filter(function(t){return t!==n}),r.fire=r.subscribers.reduce(t,e)}};return a[n]=s[n]=r,r}function i(n){tn(n).forEach(function(t){var e=n[t];if(en(e))r(t,n[t][0],n[t][1]);else{if("asap"!==e)throw new hn.InvalidArgument("Invalid event config");var i=r(t,null,function(){var n=arguments;i.subscribers.forEach(function(t){u(function(){t.apply(rn,n)})})});i.subscribe=function(n){-1===i.subscribers.indexOf(n)&&i.subscribers.push(n)},i.unsubscribe=function(n){var t=i.subscribers.indexOf(n);-1!==t&&i.subscribers.splice(t,1)}}})}function o(n){function t(){return e?!1:void(e=!0)}var e=!1;n.forEach(function(n){r(n).subscribe(t)})}var c=arguments,a={},s=function(t,r){if(r){var i=e(arguments,1),o=a[t];return o.subscribe.apply(o,i),n}return"string"==typeof t?a[t]:void 0};s.addEventType=r;for(var f=1,l=c.length;l>f;++f)r(c[f]);return s}function j(n,t){bn.push([n,e(arguments,1)])}function A(){var n=bn;bn=[];for(var t=0,e=n.length;e>t;++t){var r=n[t];r[0].apply(rn,r[1])}}function K(n){if("object"!=typeof this)throw new TypeError("Promises must be constructed via new");if("function"!=typeof n)throw new TypeError("not a function");this._state=null,this._value=null,this._deferreds=[],this._catched=!1;var t=this,e=!0;this._PSD=K.PSD;try{W(this,n,function(n){e?yn(R,t,n):R(t,n)},function(n){return e?(yn(M,t,n),!1):M(t,n)})}finally{e=!1}}function B(n,t){if(null===n._state)return void n._deferreds.push(t);var e=n._state?t.onFulfilled:t.onRejected;if(null===e)return(n._state?t.resolve:t.reject)(n._value);var r,i=mn;mn=!1,yn=j;try{var o=K.PSD;K.PSD=n._PSD,r=e(n._value),n._state||r&&"function"==typeof r.then&&r._state===!1||F(n),t.resolve(r)}catch(u){var c=t.reject(u);if(!c&&n.onuncatched)try{n.onuncatched(u)}catch(u){}}finally{if(K.PSD=o,i){do{for(;bn.length>0;)A();var a=gn.pop();if(a)try{a()}catch(u){}}while(gn.length>0||bn.length>0);yn=vn,mn=!0}}}function N(n){var t=mn;mn=!1,yn=j;try{n()}finally{if(t){do{for(;bn.length>0;)A();var e=gn.pop();if(e)try{e()}catch(r){}}while(gn.length>0||bn.length>0);yn=vn,mn=!0}}}function F(n){n._catched=!0,n._parent&&F(n._parent)}function R(n,t){var e=K.PSD;K.PSD=n._PSD;try{if(t===n)throw new TypeError("A promise cannot be resolved with itself.");if(t&&("object"==typeof t||"function"==typeof t)&&"function"==typeof t.then)return void W(n,function(n,e){t.then(n,e)},function(t){R(n,t)},function(t){M(n,t)});n._state=!0,n._value=t,q.call(n)}catch(r){M(r)}finally{K.PSD=e}}function M(n,t){var e=K.PSD;if(K.PSD=n._PSD,n._state=!1,n._value=t,q.call(n),!n._catched)try{n.onuncatched&&n.onuncatched(n._value),K.on.error.fire(n._value)}catch(r){}return K.PSD=e,n._catched}function q(){for(var n=0,t=this._deferreds.length;t>n;n++)B(this,this._deferreds[n]);this._deferreds=[]}function U(n,t,e,r){this.onFulfilled="function"==typeof n?n:null,this.onRejected="function"==typeof t?t:null,this.resolve=e,this.reject=r}function W(n,t,e,r){var i=!1;try{t(function(n){i||(i=!0,e(n))},function(t){return i?n._catched:(i=!0,r(t))})}catch(o){if(i)return;return r(o)}}function V(i,o){function l(){Un.on("versionchange",function(n){Un.close(),Un.on("error").fire(new hn.VersionChange)})}function b(n){this._cfg={version:n,storesSource:null,dbschema:{},tables:{},contentUpgrade:null},this.stores({})}function _(n,t,i,o){if(0===n){tn(Tn).forEach(function(n){k(t,n,Tn[n].primKey,Tn[n].indexes)});var u=Un._createTransaction(qn,jn,Tn);u.idbtrans=t,u.idbtrans.onerror=H(i,["populating database"]),u.on("error").subscribe(i),K.newPSD(function(){K.PSD.trans=u;try{Un.on("populate").fire(u)}catch(n){o.onerror=t.onerror=function(n){n.preventDefault()};try{t.abort()}catch(e){}t.db.close(),i(n)}})}else{var c=[],a=In.filter(function(t){return t._cfg.version===n})[0];if(!a)throw new hn.Upgrade("Dexie specification of currently installed DB version is missing");Tn=Un._dbSchema=a._cfg.dbschema;var s=!1,f=In.filter(function(t){return t._cfg.version>n});f.forEach(function(n){var o=Tn,u=n._cfg.dbschema;gn(o,t),gn(u,t),Tn=Un._dbSchema=u;var a=D(o,u);a.add.forEach(function(n){c.push(function(t,e){k(t,n[0],n[1].primKey,n[1].indexes),e()})}),a.change.forEach(function(n){if(n.recreate)throw new hn.Upgrade("Not yet support for changing primary key");c.push(function(t,e){var r=t.objectStore(n.name);n.add.forEach(function(n){B(r,n)}),n.change.forEach(function(n){r.deleteIndex(n.name),B(r,n)}),n.del.forEach(function(n){r.deleteIndex(n)}),e()})}),n._cfg.contentUpgrade&&c.push(function(t,o){s=!0;var c=Un._createTransaction(qn,e(t.db.objectStoreNames),u);c.idbtrans=t;var a=0;c._promise=r(c._promise,function(n){return function(t,e,r){function i(n){return function(){n.apply(this,arguments),0===--a&&o()}}return++a,n.call(this,t,function(n,t,r){arguments[0]=i(n),arguments[1]=i(t),e.apply(this,arguments)},r)}}),t.onerror=H(i,["running upgrader function for version",n._cfg.version]),c.on("error").subscribe(i),n._cfg.contentUpgrade(c),0===a&&o()}),s&&mn()||c.push(function(n,t){A(u,n),t()})});var l=function(){try{c.length?c.shift()(t,l):j(Tn,t)}catch(n){o.onerror=t.onerror=function(n){n.preventDefault()};try{t.abort()}catch(e){}t.db.close(),i(n)}};l()}}function D(n,t){var e={del:[],add:[],change:[]};for(var r in n)t[r]||e.del.push(r);for(var r in t){var i=n[r],o=t[r];if(i){var u={name:r,def:t[r],recreate:!1,del:[],add:[],change:[]};if(i.primKey.src!==o.primKey.src)u.recreate=!0,e.change.push(u);else{var c=i.indexes.reduce(function(n,t){return n[t.name]=t,n},{}),a=o.indexes.reduce(function(n,t){return n[t.name]=t,n},{});for(var s in c)a[s]||u.del.push(s);for(var s in a){var f=c[s],l=a[s];f?f.src!==l.src&&u.change.push(l):u.add.push(l)}(u.recreate||u.del.length>0||u.add.length>0||u.change.length>0)&&e.change.push(u)}}else e.add.push([r,o])}return e}function k(n,t,e,r){var i=n.db.createObjectStore(t,e.keyPath?{keyPath:e.keyPath,autoIncrement:e.auto}:{autoIncrement:e.auto});return r.forEach(function(n){B(i,n)}),i}function j(n,t){tn(n).forEach(function(e){t.db.objectStoreNames.contains(e)||k(t,e,n[e].primKey,n[e].indexes)})}function A(n,t){for(var e=0;e0?n:t}function ln(n,t){return En.cmp(n,t)}function dn(n,t){return En.cmp(t,n)}function pn(n,t){return t>n?-1:n===t?0:1}function vn(n,t){return n>t?-1:n===t?0:1}function yn(n,t){return n?t?function(){return n.apply(this,arguments)&&t.apply(this,arguments)}:n:t}function mn(){return navigator.userAgent.indexOf("Trident")>=0||navigator.userAgent.indexOf("MSIE")>=0}function bn(){if(Un.verno=Bn.version/10,Un._dbSchema=Tn={},jn=e(Bn.objectStoreNames,0),0!==jn.length){var n=Bn.transaction($(jn),"readonly");jn.forEach(function(t){for(var e=n.objectStore(t),r=e.keyPath,i=r&&"string"==typeof r&&-1!==r.indexOf("."),o=new X(r,r||"",!1,!1,!!e.autoIncrement,r&&"string"!=typeof r,i),u=[],c=0;c0&&(Vn=!1),!En)throw new hn.MissingAPI("indexedDB API not found. If using IE10+, make sure to run your code on a server URL (not locally). If using Safari, make sure to include indexedDB polyfill.");if(r=Vn?En.open(i):En.open(i,Math.round(10*Un.verno)),!r)throw new hn.MissingAPI("IndexedDB API not available");r.onerror=H(e,["opening database",i]),r.onblocked=function(n){Un.on("blocked").fire(n)},r.onupgradeneeded=L(function(n){if(Vn&&!Un._allowEmptyDB){r.onerror=function(n){n.preventDefault()},r.transaction.abort(),r.result.close();var t=En.deleteDatabase(i);t.onsuccess=t.onerror=function(){e(new hn.NoSuchDatabase("Database "+i+" doesnt exist"))}}else{0===n.oldVersion&&(o=!0),r.transaction.onerror=H(e);var u=n.oldVersion>Math.pow(2,62)?0:n.oldVersion;_(u/10,r.transaction,e,r)}},e),r.onsuccess=L(function(t){if(Rn=!1,Bn=r.result,Vn)bn();else if(Bn.objectStoreNames.length>0)try{gn(Tn,Bn.transaction($(Bn.objectStoreNames),Mn))}catch(t){}Bn.onversionchange=Un.on("versionchange").fire,zn||Y(function(n){return-1===n.indexOf(i)?n.push(i):void 0}),K.newPSD(function(){function t(){Nn=!1,Wn.forEach(function(n){n.resume()}),Wn=[],n(Un)}K.PSD.letThrough=!0;try{var r=Un.on.ready.fire();r&&"function"==typeof r.then?r.then(t,function(n){Bn.close(),Bn=null,e(n)}):u(t)}catch(i){e(i)}})},e)}catch(c){e(c)}}))},this.close=function(){Bn?(Bn.close(),Bn=null,Ln=!1,Nn&&(Wn.forEach(function(n){n.resume()}),Wn=[]),Nn=!1,Fn=new hn.DatabaseClosed):Rn&&Un.on("ready",function(){return K.reject(new hn.DatabaseClosed)})},this["delete"]=function(){var n=arguments;return new K(function(t,e){function r(){Un.close();var n=En.deleteDatabase(i);n.onsuccess=function(){zn||Y(function(n){var t=n.indexOf(i);return t>=0?n.splice(t,1):void 0}),t()},n.onerror=H(e,["deleting",i]),n.onblocked=function(){Un.on("blocked").fire()}}if(n.length>0)throw new hn.InvalidArgument("Arguments not allowed in db.delete()");Rn?Wn.push({resume:r}):r()})},this.backendDB=function(){return Bn},this.isOpen=function(){return null!==Bn},this.hasFailed=function(){return null!==Fn},this.dynamicallyOpened=function(){return Vn},this.name=i,Object.defineProperty(this,"tables",{get:function(){return tn(An).map(function(n){return An[n]})}}),this.on=I(this,"error","populate","blocked",{ready:[S,v],versionchange:[x,v]}),this.on.ready.subscribe=r(this.on.ready.subscribe,function(n){return function(t,e){function r(){return e||Un.on.ready.unsubscribe(r),t.apply(this,arguments)}n.call(this,r),Un.isOpen()&&(Nn?Wn.push({resume:r}):r())}}),Sn(function(){Un.on("populate").fire(Un._createTransaction(qn,jn,Tn)),Un.on("error").fire(new Error)}),this.transaction=function(n,t,i){function o(t,e){var o=null;try{if(f)throw f;o=Un._createTransaction(n,l,Tn,c);var a=l.map(function(n){return o.tables[n]});a.push(o);var s,h=0;K.newPSD(function(){K.PSD.trans=o,o.scopeFunc=i,c&&(o.idbtrans=c.idbtrans,o._promise=r(o._promise,function(n){return function(t,e,r){function i(n){return function(t){var e;return K._rootExec(function(){e=n(t),K._tickFinalize(function(){0===--h&&o.active&&(o.active=!1,o.on.complete.fire())})}),e}}return++h,n.call(this,t,function(n,t,r){return e(i(n),i(t),r)},r)}})),o.complete(function(){t(s)}),o.error(function(n){o.idbtrans&&(o.idbtrans.onerror=G);try{o.abort()}catch(t){}c&&(c.active=!1,c.on.error.fire(n));var r=e(n);c||r||Un.on.error.fire(n)}),K._rootExec(function(){s=i.apply(o,a),s&&"function"==typeof s.next&&"function"==typeof s["throw"]&&(s=Q(s))})}),(!o.idbtrans||c&&0===h)&&o._nop()}catch(d){o&&o.idbtrans&&(o.idbtrans.onerror=G),o&&o.abort(),c&&c.on.error.fire(d),u(function(){e(d)||Un.on("error").fire(d)})}}t=e(arguments,1,arguments.length-1),i=arguments[arguments.length-1];var c=K.PSD&&K.PSD.trans;c&&c.db===Un&&-1===n.indexOf("!")||(c=null);var a=-1!==n.indexOf("?");n=n.replace("!","").replace("?","");var s=en(t[0])?t.reduce(function(n,t){return n.concat(t)}):t,f=null,l=s.map(function(n){return"string"==typeof n?n:(n instanceof F||(f=f||new TypeError("Invalid type. Arguments following mode must be instances of Table or String")),n.name)});return"r"==n||n==Mn?n=Mn:"rw"==n||n==qn?n=qn:f=new hn.InvalidArgument("Invalid transaction mode: "+n),c&&(f||(c&&c.mode===Mn&&n===qn&&(a?c=null:f=f||new hn.SubTransaction("Cannot enter a sub-transaction with READWRITE mode when parent transaction is READONLY")),c&&l.forEach(function(n){c.tables.hasOwnProperty(n)||(a?c=null:f=f||new hn.SubTransaction("Table "+n+" not included in parent transaction. Parent Transaction function: "+c.scopeFunc.toString()))}))),c?c._promise(n,o,"lock"):Un._whenReady(o)},this.table=function(n){if(Dn&&Vn)return new R(n);if(!An.hasOwnProperty(n))throw new hn.InvalidTable("Table "+n+" does not exist");return An[n]},n(F.prototype,function(){function n(){throw new hn.ReadOnly("Current Transaction is READONLY")}return{_trans:function(n,t,e){return this._tpf(n,[this.name],t,e)},_idbstore:function(n,t,e){if(Dn)return new K(t);var r=this;return this._tpf(n,[this.name],function(n,e,i){t(n,e,i.idbtrans.objectStore(r.name),i)},e)},get:function(n,t){var e=this;return this._idbstore(Mn,function(t,r,i){Dn&&t(e.schema.instanceTemplate);var o=i.get(n);o.onerror=H(r,["getting",n,"from",e.name]),o.onsuccess=function(){t(e.hook.reading.fire(o.result))}}).then(t)},where:function(n){return new q(this,n)},count:function(n){return this.toCollection().count(n)},offset:function(n){return this.toCollection().offset(n)},limit:function(n){return this.toCollection().limit(n)},reverse:function(){return this.toCollection().reverse()},filter:function(n){return this.toCollection().and(n)},each:function(n){var t=this;return Dn&&n(t.schema.instanceTemplate),this._idbstore(Mn,function(e,r,i){var o=i.openCursor();o.onerror=H(r,["calling","Table.each()","on",t.name]),un(o,null,n,e,r,t.hook.reading.fire)})},toArray:function(n){var t=this;return this._idbstore(Mn,function(n,e,r){Dn&&n([t.schema.instanceTemplate]);var i=[],o=r.openCursor();o.onerror=H(e,["calling","Table.toArray()","on",t.name]),un(o,null,function(n){i.push(n)},function(){n(i)},e,t.hook.reading.fire)}).then(n)},orderBy:function(n){return new this._collClass(new q(this,n))},toCollection:function(){return new this._collClass(new q(this))},mapToClass:function(n,t){this.schema.mappedClass=n;var e=Object.create(n.prototype);t&&J(e,t),this.schema.instanceTemplate=e;var r=function(t){if(!t)return t;var e=Object.create(n.prototype);for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);return e};return this.schema.readHook&&this.hook.reading.unsubscribe(this.schema.readHook),this.schema.readHook=r,this.hook("reading",r),n},defineClass:function(n){return this.mapToClass(V.defineClass(n),n)},add:n,put:n,"delete":n,clear:n,update:n}}),t(R).from(F).extend(function(){function n(n,t,e,r){return function(i){i.stopPropagation&&i.stopPropagation(),i.preventDefault&&i.preventDefault(),n.push(i.target.error),e&&e.onerror&&K.newPSD(function(){K.PSD.trans=r,e.onerror(i.target.error)}),t&&t()}}function t(n,t,e){return t?function(r){t.onsuccess&&K.newPSD(function(){K.PSD.trans=e,t.onsuccess(r.target.result)}),n&&n(r.target.result)}:function(t){n(t.target.result)}}return{bulkAdd:function(e){var r=this,i=this.hook.creating.fire;return this._idbstore(qn,function(o,u,c,a){function l(n){0===m.length?o(n):u(new E(r.name+".bulkAdd(): "+m.length+" of "+b+" operations failed",m))}if(!c.keyPath&&!r.schema.primKey.auto)throw new hn.Unsupported("bulkAdd() only support inbound keys");if(0===e.length)return o();var h,p,y,m=[],b=e.length;if(i!==v){var g=c.keyPath,w={onerror:null,onsuccess:null};p=n(m,null,w,a),y=t(null,w,a);for(var _=0,x=e.length;x>_;++_){var P=e[_],S=s(P,g),D=i.call(w,S,P,a);void 0===S&&void 0!==D&&(P=d(P),f(P,g,D)),h=c.add(P),x-1>_&&(h.onerror=p,w.onsuccess&&(h.onsuccess=y),w.onerror=null,w.onsuccess=null)}h.onerror=n(m,l,w,a),h.onsuccess=t(l,w,a)}else{p=n(m);for(var _=0,x=e.length;x>_;++_)h=c.add(e[_]),h.onerror=p;h.onerror=n(m,l),h.onsuccess=t(l)}})},add:function(n,t){var e=this,r=this.hook.creating.fire;return this._idbstore(qn,function(i,o,u,c){var a={onsuccess:null,onerror:null};if(r!==v){var l=void 0!==t?t:u.keyPath?s(n,u.keyPath):void 0,h=r.call(a,l,n,c);void 0===l&&void 0!==h&&(u.keyPath?f(n,u.keyPath,h):t=h)}var d=void 0!==t?u.add(n,t):u.add(n);d.onerror=H(function(n){return a.onerror&&K.newPSD(function(){K.PSD.trans=c,a.onerror(n)}),o(n)},["adding",n,"into",e.name]),d.onsuccess=function(t){var e=u.keyPath;e&&f(n,e,t.target.result),a.onsuccess&&K.newPSD(function(){K.PSD.trans=c,a.onsuccess(t.target.result)}),i(d.result)}})},put:function(n,t){var e=this,r=this.hook.creating.fire,i=this.hook.updating.fire;return r!==v||i!==v?this._trans(qn,function(r,i,o){var u=void 0!==t?t:e.schema.primKey.keyPath&&s(n,e.schema.primKey.keyPath);void 0===u?o.tables[e.name].add(n).then(r,i):(o._lock(),n=d(n),o.tables[e.name].where(":id").equals(u).modify(function(t){this.value=n}).then(function(r){return 0===r?o.tables[e.name].add(n,t):u})["finally"](function(){o._unlock()}).then(r,i))}):this._idbstore(qn,function(r,i,o){var u=void 0!==t?o.put(n,t):o.put(n);u.onerror=H(i,["putting",n,"into",e.name]),u.onsuccess=function(t){var e=o.keyPath;e&&f(n,e,t.target.result),r(u.result)}})},"delete":function(n){return this.hook.deleting.subscribers.length?this.where(":id").equals(n)["delete"]():this._idbstore(qn,function(t,e,r){var i=r["delete"](n);i.onerror=H(e,["deleting",n,"from",r.name]),i.onsuccess=function(n){t(i.result)}})},clear:function(){return this.hook.deleting.subscribers.length?this.toCollection()["delete"]():this._idbstore(qn,function(n,t,e){var r=e.clear();r.onerror=H(t,["clearing",e.name]),r.onsuccess=function(t){n(r.result)}})},update:function(n,t){if("object"!=typeof t||en(t))throw new hn.InvalidArgument("db.update(keyOrObject, modifications). modifications must be an object.");if("object"!=typeof n||en(n))return this.where(":id").equals(n).modify(t);tn(t).forEach(function(e){f(n,e,t[e])});var e=s(n,this.schema.primKey.keyPath);return void 0===e&&K.reject(new hn.InvalidArgument("Given object does not contain its primary key")),this.where(":id").equals(e).modify(t)}}}),n(M.prototype,{_lock:function(){return++this._reculock,1===this._reculock&&K.PSD&&(K.PSD.lockOwnerFor=this),this},_unlock:function(){if(0===--this._reculock)for(K.PSD&&(K.PSD.lockOwnerFor=null);this._blockedFuncs.length>0&&!this._locked();){var n=this._blockedFuncs.shift();try{n()}catch(t){}}return this},_locked:function(){return this._reculock&&(!K.PSD||K.PSD.lockOwnerFor!==this)},_nop:function(n){this.tables[this.storeNames[0]].get(0).then(n)},_promise:function(n,t,e){var r=this;return K.newPSD(function(){var i;return r._locked()?i=new K(function(i,o){r._blockedFuncs.push(function(){r._promise(n,t,e).then(i,o)})}):(i=r.active?new K(function(i,o){if(!r.idbtrans&&n){if(!Bn)throw Fn?Fn instanceof hn.DatabaseClosed?Fn:new hn.OpenFailed(Fn):new hn.DatabaseClosed;var c=r.idbtrans=Bn.transaction($(r.storeNames),r.mode);c.onerror=function(n){r.on("error").fire(n&&n.target.error),n.preventDefault(),r.abort()},c.onabort=function(n){u(function(){r.on("error").fire(new hn.Abort("Transaction aborted for unknown reason"))}),r.active=!1,r.on("abort").fire(n)},c.oncomplete=function(n){r.active=!1,r.on("complete").fire(n)}}e&&r._lock();try{t(i,o,r)}catch(a){!function(){var n=T(C(a));V.ignoreTransaction(function(){r.on("error").fire(n)}),r.abort(),o(n)}()}}):K.reject(T(new hn.TransactionInactive("Transaction is inactive. Original Scope Function Source: "+r.scopeFunc.toString()))),r.active&&e&&i["finally"](function(){r._unlock()})),i.onuncatched=function(n){V.ignoreTransaction(function(){r.on("error").fire(n)}),r.abort()},i})},complete:function(n){return this.on("complete",n)},error:function(n){return this.on("error",n)},abort:function(){if(this.idbtrans&&this.active)try{this.active=!1,this.idbtrans.abort(),this.on.error.fire(new hn.Abort("Transaction Aborted"))}catch(n){}},table:function(n){if(!this.tables.hasOwnProperty(n))throw new hn.InvalidTable("Table "+n+" not in transaction");return this.tables[n]}}),n(q.prototype,function(){function n(n,t,e){var r=n instanceof q?new n._ctx.collClass(n):n;try{throw e?new e(t):new TypeError(t)}catch(i){r._ctx.error=i}return r}function t(n){return new n._ctx.collClass(n,function(){return Cn.only("")}).limit(0)}function r(n){return e(1===n.length&&en(n[0])?n[0]:n)}function i(n){return"next"===n?function(n){return n.toUpperCase()}:function(n){return n.toLowerCase()}}function o(n){return"next"===n?function(n){return n.toLowerCase()}:function(n){return n.toUpperCase()}}function u(n,t,e,r,i,o){for(var u=Math.min(n.length,r.length),c=-1,a=0;u>a;++a){var s=t[a];if(s!==r[a])return i(n[a],e[a])<0?n.substr(0,a)+e[a]+e.substr(a+1):i(n[a],r[a])<0?n.substr(0,a)+r[a]+e.substr(a+1):c>=0?n.substr(0,c)+t[c]+e.substr(c+1):null;i(n[a],s)<0&&(c=a)}return uc?null:n.substr(0,c)+r[c]+e.substr(c+1)}function c(n,t,e,r){function c(n){a=i(n),s=o(n),f="next"===n?pn:vn;var t=e.map(function(n){return{lower:s(n),upper:a(n)}}).sort(function(n,t){return f(n.lower,t.lower)});l=t.map(function(n){return n.upper}),h=t.map(function(n){return n.lower}),d=n,p="next"===n?"":r}var a,s,f,l,h,d,p,v=e.length;c("next");var y=new n._ctx.collClass(n,function(){return Cn.bound(l[0],h[v-1]+r)});y._ondirectionchange=function(n){c(n)};var m=0;return y._addAlgorithm(function(n,e,r){var i=n.key;if("string"!=typeof i)return!1;var o=s(i);if(t(o,h,m))return!0;for(var c=null,a=m;v>a;++a){var y=u(i,o,l[a],h[a],f,d);null===y&&null===c?m=a+1:(null===c||f(c,y)>0)&&(c=y)}return e(null!==c?function(){n["continue"](c+p)}:r),!1}),y}return{between:function(e,r,i,o){i=i!==!1,o=o===!0;try{return an(e,r)>0||0===an(e,r)&&(i||o)&&(!i||!o)?t(this):new this._ctx.collClass(this,function(){return Cn.bound(e,r,!i,!o)})}catch(u){return n(this,xn)}},equals:function(n){return new this._ctx.collClass(this,function(){return Cn.only(n)})},above:function(n){return new this._ctx.collClass(this,function(){return Cn.lowerBound(n,!0)})},aboveOrEqual:function(n){return new this._ctx.collClass(this,function(){return Cn.lowerBound(n)})},below:function(n){return new this._ctx.collClass(this,function(){return Cn.upperBound(n,!0)})},belowOrEqual:function(n){return new this._ctx.collClass(this,function(){return Cn.upperBound(n)})},startsWith:function(t){return"string"!=typeof t?n(this,Pn):this.between(t,t+wn,!0,!0)},startsWithIgnoreCase:function(t){return"string"!=typeof t?n(this,Pn):""===t?this.startsWith(t):c(this,function(n,t){return 0===n.indexOf(t[0])},[t],wn)},equalsIgnoreCase:function(t){return"string"!=typeof t?n(this,Pn):c(this,function(n,t){return n===t[0]},[t],"")},anyOfIgnoreCase:function(e){var i=r(arguments);return 0===i.length?t(this):i.every(function(n){return"string"==typeof n})?c(this,function(n,t){return-1!==t.indexOf(n)},i,""):n(this,"anyOfIgnoreCase() only works with strings")},startsWithAnyOfIgnoreCase:function(e){var i=r(arguments);return 0===i.length?t(this):i.every(function(n){ +return"string"==typeof n})?c(this,function(n,t){return t.some(function(t){return 0===n.indexOf(t)})},i,wn):n(this,"startsWithAnyOfIgnoreCase() only works with strings")},anyOf:function(e){var i=r(arguments),o=ln;try{i.sort(o)}catch(u){return n(this,xn)}if(0===i.length)return t(this);var c=new this._ctx.collClass(this,function(){return Cn.bound(i[0],i[i.length-1])});c._ondirectionchange=function(n){o="next"===n?ln:dn,i.sort(o)};var a=0;return c._addAlgorithm(function(n,t,e){for(var r=n.key;o(r,i[a])>0;)if(++a,a===i.length)return t(e),!1;return 0===o(r,i[a])?!0:(t(function(){n["continue"](i[a])}),!1)}),c},notEqual:function(n){return this.inAnyRange([[-(1/0),n],[n,_n]],{includeLowers:!1,includeUppers:!1})},noneOf:function(t){var e=r(arguments);if(0===e.length)return new this._ctx.collClass(this);try{e.sort(ln)}catch(i){return n(this,xn)}var o=e.reduce(function(n,t){return n?n.concat([[n[n.length-1][1],t]]):[[-(1/0),t]]},null);return o.push([e[e.length-1],_n]),this.inAnyRange(o,{includeLowers:!1,includeUppers:!1})},inAnyRange:function(e,r){function i(n,t){for(var e=0,r=n.length;r>e;++e){var i=n[e];if(an(t[0],i[1])<0&&an(t[1],i[0])>0){i[0]=sn(i[0],t[0]),i[1]=fn(i[1],t[1]);break}}return e===r&&n.push(t),n}function o(n,t){return l(n[0],t[0])}function u(n){return!p(n)&&!v(n)}var c=this._ctx;if(0===e.length)return t(this);if(!e.every(function(n){return void 0!==n[0]&&void 0!==n[1]&&ln(n[0],n[1])<=0}))return n(this,"First argument to inAnyRange() must be an Array of two-value Arrays [lower,upper] where upper must not be lower than lower",hn.InvalidArgument);var a,s=!r||r.includeLowers!==!1,f=r&&r.includeUppers===!0,l=ln;try{a=e.reduce(i,[]),a.sort(o)}catch(h){return n(this,xn)}var d=0,p=f?function(n){return ln(n,a[d][1])>0}:function(n){return ln(n,a[d][1])>=0},v=s?function(n){return dn(n,a[d][0])>0}:function(n){return dn(n,a[d][0])>=0},y=p,m=new c.collClass(this,function(){return Cn.bound(a[0][0],a[a.length-1][1],!s,!f)});return m._ondirectionchange=function(n){"next"===n?(y=p,l=ln):(y=v,l=dn),a.sort(o)},m._addAlgorithm(function(n,t,e){for(var r=n.key;y(r);)if(++d,d===a.length)return t(e),!1;return u(r)?!0:0===an(r,a[d][1])||0===an(r,a[d][0])?!1:(t(function(){l===ln?n["continue"](a[d][0]):n["continue"](a[d][1])}),!1)}),m},startsWithAnyOf:function(e){var i=r(arguments);return i.every(function(n){return"string"==typeof n})?0===i.length?t(this):this.inAnyRange(i.map(function(n){return[n,n+wn]})):n(this,"startsWithAnyOf() only works with strings")}}}),n(U.prototype,function(){function n(n,t){n.filter=yn(n.filter,t)}function t(n,t){n.isMatch=yn(n.isMatch,t)}function e(n,t){if(n.isPrimKey)return t;var e=n.table.schema.idxByName[n.index];if(!e)throw new hn.Schema("KeyPath "+n.index+" on object store "+t.name+" is not indexed");return n.isPrimKey?t:t.index(e.name)}function r(n,t){return e(n,t)[n.op](n.range||null,n.dir+n.unique)}function i(n,t,e,i,o){n.or?!function(){function u(){2===++f&&e()}function c(n,e,r){if(!a||a(e,r,u,i)){var o=e.primaryKey.toString();s.hasOwnProperty(o)||(s[o]=!0,t(n,e,r))}}var a=n.filter,s={},f=0;n.or._iterate(c,u,i,o),un(r(n,o),n.algorithm,c,u,i,n.table.hook.reading.fire)}():un(r(n,o),yn(n.algorithm,n.filter),t,e,i,n.table.hook.reading.fire)}function o(n){return n.table.schema.instanceTemplate}return{_read:function(n,t){var e=this._ctx;return e.error?e.table._trans(null,function(n,t){t(e.error)}):e.table._idbstore(Mn,n).then(t)},_write:function(n){var t=this._ctx;return t.error?t.table._trans(null,function(n,e){e(t.error)}):t.table._idbstore(qn,n,"locked")},_addAlgorithm:function(n){var t=this._ctx;t.algorithm=yn(t.algorithm,n)},_iterate:function(n,t,e,r){return i(this._ctx,n,t,e,r)},each:function(n){var t=this._ctx;return Dn&&n(o(t)),this._read(function(e,r,o){i(t,n,e,r,o)})},count:function(n){if(Dn)return K.resolve(0).then(n);var t=this,r=this._ctx;if(r.filter||r.algorithm||r.or){var o=0;return this._read(function(n,t,e){i(r,function(){return++o,!1},function(){n(o)},t,e)},n)}return this._read(function(n,i,o){var u=e(r,o),c=r.range?u.count(r.range):u.count();c.onerror=H(i,["calling","count()","on",t.name]),c.onsuccess=function(t){n(Math.min(t.target.result,Math.max(0,r.limit-r.offset)))}},n)},sortBy:function(n,t){function e(n,t){return t?e(n[i[t]],t-1):n[o]}function r(n,t){var r=e(n,u),i=e(t,u);return i>r?-c:r>i?c:0}var i=n.split(".").reverse(),o=i[0],u=i.length-1,c="next"===this._ctx.dir?1:-1;return this.toArray(function(n){return n.sort(r)}).then(t)},toArray:function(n){var t=this._ctx;return this._read(function(n,e,r){Dn&&n([o(t)]);var u=[];i(t,function(n){u.push(n)},function(){n(u)},e,r)},n)},offset:function(t){var e=this._ctx;return 0>=t?this:(e.offset+=t,e.or||e.algorithm||e.filter?n(e,function(n,e,r){return--t<0}):n(e,function(n,e,r){return 0===t?!0:1===t?(--t,!1):(e(function(){n.advance(t),t=0}),!1)}),this)},limit:function(t){return this._ctx.limit=Math.min(this._ctx.limit,t),n(this._ctx,function(n,e,r){return--t<=0&&e(r),t>=0}),this},until:function(t,e){var r=this._ctx;return Dn&&t(o(r)),n(this._ctx,function(n,r,i){return t(n.value)?(r(i),e):!0}),this},first:function(n){return this.limit(1).toArray(function(n){return n[0]}).then(n)},last:function(n){return this.reverse().first(n)},and:function(e){return Dn&&e(o(this._ctx)),n(this._ctx,function(n){return e(n.value)}),t(this._ctx,e),this},or:function(n){return new q(this._ctx.table,n,this)},reverse:function(){return this._ctx.dir="prev"===this._ctx.dir?"next":"prev",this._ondirectionchange&&this._ondirectionchange(this._ctx.dir),this},desc:function(){return this.reverse()},eachKey:function(n){var t=this._ctx;return Dn&&n(s(o(this._ctx),this._ctx.index?this._ctx.table.schema.idxByName[this._ctx.index].keyPath:this._ctx.table.schema.primKey.keyPath)),t.isPrimKey||(t.op="openKeyCursor"),this.each(function(t,e){n(e.key,e)})},eachUniqueKey:function(n){return this._ctx.unique="unique",this.eachKey(n)},keys:function(n){var t=this._ctx;t.isPrimKey||(t.op="openKeyCursor");var e=[];return Dn?new K(this.eachKey.bind(this)).then(function(n){return[n]}).then(n):this.each(function(n,t){e.push(t.key)}).then(function(){return e}).then(n)},uniqueKeys:function(n){return this._ctx.unique="unique",this.keys(n)},firstKey:function(n){return this.limit(1).keys(function(n){return n[0]}).then(n)},lastKey:function(n){return this.reverse().firstKey(n)},distinct:function(){var t={};return n(this._ctx,function(n){var e=n.primaryKey.toString(),r=t.hasOwnProperty(e);return t[e]=!0,!r}),this}}}),t(W).from(U).extend({modify:function(t){var e=this,r=this._ctx,i=r.table.hook,o=i.updating.fire,u=i.deleting.fire;return Dn&&"function"==typeof t&&t.call({value:r.table.schema.instanceTemplate},r.table.schema.instanceTemplate),this._write(function(i,a,l,y){function m(n,t,e){function i(n){return E.push(n),C.push(o.primKey),o.onerror&&K.newPSD(function(){K.PSD.trans=y,o.onerror(n)}),g(),!0}T=t.primaryKey;var o={primKey:t.primaryKey,value:n,onsuccess:null,onerror:null};if(w.call(o,n,o)!==!1){var u=!o.hasOwnProperty("value");++S,c(function(){var e=u?t["delete"]():t.update(o.value);e.onerror=H(i,u?["deleting",n,"from",r.table.name]:["modifying",n,"on",r.table.name]),e.onsuccess=function(n){o.onsuccess&&K.newPSD(function(){K.PSD.trans=y,o.onsuccess(o.value)}),++D,g()}},i)}else o.onsuccess&&o.onsuccess(o.value)}function b(n){return n&&(E.push(n),C.push(T)),a(new O("Error modifying one or more objects",E,D,C))}function g(){k&&D+E.length===S&&(E.length>0?b():i(D))}var w;if("function"==typeof t)w=o===v&&u===v?t:function(n){var e=d(n);if(t.call(this,n,this)===!1)return!1;if(this.hasOwnProperty("value")){var r=p(e,this.value),i=o.call(this,r,this.primKey,e,y);i&&(n=this.value,tn(i).forEach(function(t){f(n,t,i[t])}))}else u.call(this,this.primKey,n,y)};else if(o===v){var _=tn(t),x=_.length;w=function(n){for(var e=!1,r=0;x>r;++r){var i=_[r],o=t[i];s(n,i)!==o&&(f(n,i,o),e=!0)}return e}}else{var P=t;t=h(P),w=function(e){var r=!1,i=o.call(this,t,this.primKey,d(e),y);return i&&n(t,i),tn(t).forEach(function(n){var i=t[n];s(e,n)!==i&&(f(e,n,i),r=!0)}),i&&(t=h(P)),r}}var S=0,D=0,k=!1,E=[],C=[],T=null;e._iterate(m,function(){k=!0,g()},b,l)})},"delete":function(){return this.modify(function(){delete this.value})}}),n(this,{Collection:U,Table:F,Transaction:M,Version:b,WhereClause:q,WriteableCollection:W,WriteableTable:R}),l(),kn.forEach(function(n){n(Un)})}function L(n,t,e){return function(){var r=K.PSD;K.PSD=e;try{n.apply(this,arguments)}catch(i){t(i)}finally{K.PSD=r}}}function z(n){if("function"==typeof n)return new n;if(en(n))return[z(n[0])];if(n&&"object"==typeof n){var t={};return J(t,n),t}return n}function J(n,t){return tn(t).forEach(function(e){var r=z(t[e]);n[e]=r}),n}function H(n,t){return function(e){var r=e&&e.target.error||new Error("");if(t){var i=" occurred when "+t.map(function(n){switch(typeof n){case"function":return n();case"string":return n;default:return JSON.stringify(n)}}).join(" ");r.message&&r.message!=r.name&&(i+=". "+r.message),r.name?r=C(r,r.name+i):r+=i}return n(r),e&&(e.stopPropagation&&e.stopPropagation(),e.preventDefault&&e.preventDefault()),!1}}function G(n){n.preventDefault()}function Y(n){var t,e=V.dependencies.localStorage;if(!e)return n([]);try{t=JSON.parse(e.getItem("Dexie.DatabaseNames")||"[]")}catch(r){t=[]}n(t)&&e.setItem("Dexie.DatabaseNames",JSON.stringify(t))}function Q(n){function t(n){return function(t){var r=n(t),i=r.value;return r.done?i:i&&"function"==typeof i.then?i.then(o,u):Array.isArray(i)?e(i,0):o(i)}}function e(n,t){if(t===n.length)return o(n);var r=n[t];return r.constructor&&"function"==typeof r.constructor.all?r.constructor.all(n).then(o,u):e(n,t+1)}var r=function(t){return n.next(t)},i=function(t){return n["throw"](t)},o=t(r),u=t(i);return t(r)()}function X(n,t,e,r,i,o,u){this.name=n,this.keyPath=t,this.unique=e,this.multi=r,this.auto=i,this.compound=o,this.dotted=u;var c="string"==typeof t?t:t&&"["+[].join.call(t,"+")+"]";this.src=(e?"&":"")+(r?"*":"")+(i?"++":"")+c}function Z(n,t,e,r){this.name=n,this.primKey=t||new X,this.indexes=e||[new X],this.instanceTemplate=r,this.mappedClass=null,this.idxByName=e.reduce(function(n,t){return n[t.name]=t,n},{})}function $(n){return 1===n.length?n[0]:n}function nn(){var n=V.dependencies.indexedDB,t=n&&(n.getDatabaseNames||n.webkitGetDatabaseNames);return t&&t.bind(n)}var tn=Object.keys,en=Array.isArray,rn="undefined"!=typeof self?self:"undefined"!=typeof window?window:global,on=[].slice,un=["Modify","Bulk","OpenFailed","VersionChange","Schema","Upgrade","InvalidTable","MissingAPI","NoSuchDatabase","InvalidArgument","SubTransaction","Unsupported","Internal","DatabaseClosed"],cn=["Unknown","Constraint","Data","TransactionInactive","ReadOnly","Version","NotFound","InvalidState","InvalidAccess","Abort","Timeout","QuotaExceeded","Syntax","DataClone"],an=un.concat(cn),sn={VersionChanged:"Database version changed by other database connection",DatabaseClosed:"Database has been closed"};t(D).from(Error),t(O).from(D),t(E).from(D);var fn=an.reduce(function(n,t){return n[t]=t+"Error",n},{}),ln=D,hn=an.reduce(function(n,e){function r(n,t){this.name=e+"Error","string"==typeof n?(this.message=n,this.inner=null):"object"==typeof n?(this.message=n.message,this.inner=t):(this.message=sn[e],this.inner=null)}return t(r).from(ln),n[e]=r,n},{});hn.Syntax=SyntaxError,hn.Type=TypeError,hn.Range=RangeError;var dn=cn.reduce(function(n,t){return n[t+"Error"]=hn[t],n},{}),pn=an.reduce(function(n,t){return-1===["Syntax","Type","Range"].indexOf(t)&&(n[t+"Error"]=hn[t]),n},{});pn.ModifyError=O,pn.DexieError=D,pn.BulkError=E;var vn=rn.setImmediate||function(n){var t=e(arguments,1);setTimeout(function(){n.apply(rn,t)},0)};i(function(){vn=yn=j=function(n){var t=arguments;setTimeout(function(){n.apply(rn,e(t,1))},0)}});var yn=vn,mn=!0,bn=[],gn=[];K.on=I(null,"error"),K.all=function(){var n=e(1===arguments.length&&en(arguments[0])?arguments[0]:arguments);return new K(function(t,e){function r(o,u){try{if(u&&("object"==typeof u||"function"==typeof u)){var c=u.then;if("function"==typeof c)return void c.call(u,function(n){r(o,n)},e)}n[o]=u,0===--i&&t(n)}catch(a){e(a)}}if(0===n.length)return t([]);for(var i=n.length,o=0;o { game.renderer.addEffect(data); }); + + this.socket.on('chat', data => console.log(data)); }; sendUpdate(inputs) { diff --git a/public/js/wingbase/player.js b/public/static/js/wingbase/player.js similarity index 100% rename from public/js/wingbase/player.js rename to public/static/js/wingbase/player.js diff --git a/public/js/wingbase/render/asteroids.js b/public/static/js/wingbase/render/asteroids.js similarity index 100% rename from public/js/wingbase/render/asteroids.js rename to public/static/js/wingbase/render/asteroids.js diff --git a/public/js/wingbase/render/body.js b/public/static/js/wingbase/render/body.js similarity index 100% rename from public/js/wingbase/render/body.js rename to public/static/js/wingbase/render/body.js diff --git a/public/js/wingbase/render/effect.js b/public/static/js/wingbase/render/effect.js similarity index 100% rename from public/js/wingbase/render/effect.js rename to public/static/js/wingbase/render/effect.js diff --git a/public/js/wingbase/render/particle.js b/public/static/js/wingbase/render/particle.js similarity index 100% rename from public/js/wingbase/render/particle.js rename to public/static/js/wingbase/render/particle.js diff --git a/public/js/wingbase/render/render.js b/public/static/js/wingbase/render/render.js similarity index 100% rename from public/js/wingbase/render/render.js rename to public/static/js/wingbase/render/render.js diff --git a/public/js/wingbase/render/ships.js b/public/static/js/wingbase/render/ships.js similarity index 100% rename from public/js/wingbase/render/ships.js rename to public/static/js/wingbase/render/ships.js diff --git a/public/js/wingbase/world/asteroid.js b/public/static/js/wingbase/world/asteroid.js similarity index 100% rename from public/js/wingbase/world/asteroid.js rename to public/static/js/wingbase/world/asteroid.js diff --git a/public/js/wingbase/world/body.js b/public/static/js/wingbase/world/body.js similarity index 100% rename from public/js/wingbase/world/body.js rename to public/static/js/wingbase/world/body.js diff --git a/public/js/wingbase/world/missile.js b/public/static/js/wingbase/world/missile.js similarity index 100% rename from public/js/wingbase/world/missile.js rename to public/static/js/wingbase/world/missile.js diff --git a/public/js/wingbase/world/physics.js b/public/static/js/wingbase/world/physics.js similarity index 100% rename from public/js/wingbase/world/physics.js rename to public/static/js/wingbase/world/physics.js diff --git a/public/js/wingbase/world/ship.js b/public/static/js/wingbase/world/ship.js similarity index 100% rename from public/js/wingbase/world/ship.js rename to public/static/js/wingbase/world/ship.js diff --git a/public/js/wingbase/world/world.js b/public/static/js/wingbase/world/world.js similarity index 100% rename from public/js/wingbase/world/world.js rename to public/static/js/wingbase/world/world.js diff --git a/public/views/game.jade b/public/views/game.jade new file mode 100644 index 0000000..cebafe4 --- /dev/null +++ b/public/views/game.jade @@ -0,0 +1,19 @@ +doctype html +html(lang='en') + head + meta(charset="UTF-8") + link(rel="icon", type="image/png", href="img/favicon.png") + link(rel="stylesheet", type="text/css", href="css/styles.css") + title + | Wingbase + script(src="js/lib/dexie.min.js") + script(src="socket.io/socket.io.js") + script(src="js/lib/box2dweb.min.js") + script(src="https://rawgit.com/Asraelite/pallet.js/master/pallet.js") + + script(src="wingbase.min.js") + body + canvas#wingbase_canvas + | Sorry, your browser does not currently support HTML5 Canvas. + #gui + include diff --git a/public/views/index.jade b/public/views/index.jade new file mode 100644 index 0000000..8b390bb --- /dev/null +++ b/public/views/index.jade @@ -0,0 +1 @@ +include game.jade diff --git a/server/game/room/index.js b/server/game/room/index.js index ee537f1..b75c279 100644 --- a/server/game/room/index.js +++ b/server/game/room/index.js @@ -2,6 +2,8 @@ const World = require('./world'); +const messages = require('./messages.json'); + class Room { constructor() { this.players = new Set(); @@ -14,13 +16,14 @@ class Room { } add(player) { - wingbase.log(`${player.name} joined ${this.name}.`); player.room = this; player.connection.room = this.name; this.players.add(player); this.setTeam(player, this.teamA.size > this.teamB.size ? 'b' : 'a'); this.world.addPlayer(player); this.sendWorld(player); + wingbase.log(`${player.name} joined ${this.name}.`); + this.message('roomEnter', player.name); } remove(player) { @@ -63,6 +66,22 @@ class Room { this.players.forEach(player => player.send(msg, data)); } + message(type, values) { + if (!(values instanceof Array)) values = [values]; + + let messageList = messages[type]; + let message = messageList[Math.random() * messageList.length | 0]; + + // TODO: format name to class. + + message = message.replace('@', values[0]); + + this.broadcast('chat', { + type: 'server', + message: message + }); + } + sendWorld(player) { let data = { playerShipId: player.ship.id, diff --git a/server/game/room/messages.json b/server/game/room/messages.json new file mode 100644 index 0000000..2bbb260 --- /dev/null +++ b/server/game/room/messages.json @@ -0,0 +1,54 @@ +{ + "roomEnter": [ + "@ has entered the room, the cunt.", + "Oh, looks like @ decided to show up.", + "Here comes @.", + "Guys, it's over, @ is here", + "What a great time we're having. Aw crap, here's @.", + "@ has entered the room.", + "Some guy by the name of @ decided to show up.", + "A wild @ appeared!", + "Oh no, @ just arrived.", + "Look out it's @!", + "@ has come for a visit.", + "Out of nowhere, @ arrives.", + "@ has penetrated the room.", + "@ showed up.", + "Good news, everyone, @ is here.", + "@ joined the room.", + "@ has arrived to play with y'all.", + "@ entered the room, the audacity.", + "Someone let @ in again.", + "@ has decided to participate.", + "@ joined the game.", + "You know @, the weird one? Yeah, he just joined.", + "Uh-oh spaghetti-o, it's @.", + "@ joined the room :/", + "May as well leave now, @ just joined.", + "@ decided to turn up.", + "@ has popped by for a visit.", + "And like that annoying friend who won't go away, @ arrives.", + "@ now arrives, run for your lives", + "@ joined the room. This is a \"good\" thing.", + "For fuck's sake, @ has joined again.", + "Well great, @ entered the room.", + "@ has entered the room, hopefully they'll leave soon.", + "@ didn't listen when we told them to go away and has joined.", + "@ has entered the game. They actually did it. Wow.", + "@ entered the room, but maybe it won't be as bad as last time.", + "Everybody clap for @, the shithead who has joined the room.", + "@ has come by for a visit. Joy of joys." + ], + "roomLeave": [ + "@ has left, finally.", + "@ has left the room.", + "@ finally decided to leave.", + "@ is now gone, good ridance.", + "@ disconnected. Good.", + "After much waiting, @ has finally left.", + "@ is gone. Hopefully it'll stay that way.", + "Thankfully @ has left the room.", + "@ has exited the game :)", + "@ left. Now hope they don't come back." + ] +} diff --git a/server/game/room/world/body/ship.js b/server/game/room/world/body/ship.js index b0fdcd1..e15fd73 100644 --- a/server/game/room/world/body/ship.js +++ b/server/game/room/world/body/ship.js @@ -30,8 +30,8 @@ class Ship extends Body { this.size = traits.size; // Mounts - traits.mounts.forEach((mount, i) => { - let mounts = new Mount(this, mount); + traits.mounts.forEach((data, i) => { + let mount = new Mount(this, data); this.mounts.push(mount); }); @@ -112,7 +112,7 @@ class Ship extends Body { name: this.player.name, frame: this.frame, power: this.power, - mounts: this.traits.mounts, + mounts: this.mounts.map(m => m.packFull()), turrets: this.turrets, size: this.size, delta: this.packDelta() diff --git a/server/game/room/world/body/turret/mount.js b/server/game/room/world/body/turret/mount.js index 5adb347..f56a7ca 100644 --- a/server/game/room/world/body/turret/mount.js +++ b/server/game/room/world/body/turret/mount.js @@ -19,6 +19,12 @@ class Mount { if (!this.fixture) return; this.fixture.destruct(); } + + packFull() { + return { + + } + } } module.exports = Mount; diff --git a/server/index.js b/server/index.js index fb074de..a8acb19 100644 --- a/server/index.js +++ b/server/index.js @@ -20,6 +20,11 @@ class WingbaseServer extends ServerInterface { this.log(`Wingbase version ${packageJson.version} running.`); } + + stop() { + this.log('Server stopping.'); + process.exit(); + } } function init() { diff --git a/server/web/index.js b/server/web/index.js index 1e21997..8f9ffab 100644 --- a/server/web/index.js +++ b/server/web/index.js @@ -12,18 +12,26 @@ class WebServer { } start() { - this.appServer.listen(8080); + this.appServer.listen(process.env.PORT || 8080); let app = this.app; - app.get('/starbugs.min.js', (req, res) => { + app.set('views', './public/views'); + app.set('view engine', 'jade'); + app.engine('jade', require('jade').__express); + + app.get('/wingbase.min.js', (req, res) => { minify(result => { - res.contentType('starbugs.min.js'); + res.contentType('wingbase.min.js'); res.end(result); }); }); - app.use(express.static('public')); + app.get('/', (req, res) => { + res.render('index', {}); + }); + + app.use(express.static('public/static')); } } diff --git a/server/web/minify.js b/server/web/minify.js index 5586a62..6d65302 100644 --- a/server/web/minify.js +++ b/server/web/minify.js @@ -9,7 +9,7 @@ const uglify = require('uglify-js'); function minifyJs(callback) { callback = callback || function() {}; - var dir = path.join(__dirname, '../../public/js/wingbase'); + var dir = path.join(__dirname, '../../public/static/js/wingbase'); var cache = ''; var scripts = []; diff --git a/test.js b/test.js index 7dd8537..af1e41e 100644 --- a/test.js +++ b/test.js @@ -1,3 +1,13 @@ #!bin/node -console.log('No tests to run'); +'use strict'; + +process.env.PORT = 28256; // Unused as far as I know. + +require('./server/')(); + +setTimeout(_ => { + wingbase.debug('Starting tests.'); + + require('./tests'); +}, 1000); diff --git a/tests/fuzz.js b/tests/fuzz.js new file mode 100644 index 0000000..fd9c609 --- /dev/null +++ b/tests/fuzz.js @@ -0,0 +1,26 @@ +'use strict'; + +const assert = require('assert'); + +function fuzz(socket) { + let types = ['setName', 'chat', 'inputs']; + + // Heh, they align. + let msg = Array(25).fill().map(v => { + let rndstr = Math.random().toString(36).substr(Math.random() * -5 - 1); + return Array(Math.random() * 20 | 0).fill().map(v => { + return Math.random() > 0.5 ? Math.random() * 10 : rndstr; + }); + }).concat(Array(75).fill().map(v => { + return Math.random() * 50; + })); + + for (var i = 0; i < 100; i++) { + let type = types[Math.random() * types.length | 0]; + socket.send(type, msg[i]); + } + + wingbase.debug('Sent 100 random messages.'); +} + +module.exports = fuzz; diff --git a/tests/index.js b/tests/index.js new file mode 100644 index 0000000..4ec1884 --- /dev/null +++ b/tests/index.js @@ -0,0 +1,17 @@ +'use strict'; + +const io = require('socket.io-client'); + +const fuzz = require('./fuzz.js'); + +let socket = io('http://localhost:' + process.env.PORT); +socket.on('connect', test); + +function test() { + wingbase.debug('Running fuzz test.'); + fuzz(socket); + + wingbase.debug('Ending tests.'); + + wingbase.stop(); +}