1
0
Fork 0
lasertank-js/scripts/ease.min.js

56 lines
24 KiB
JavaScript
Raw Normal View History

Initial commit illustrating LTG loading and masking This project -- creating a LaserTank clone in JavaScript -- deserves some discussion before diving into the implementation details (you may skip to the separator below for implementation details without the history). LaserTank is a game that has a special place in my heart. Not only is it a witty and enjoyable game, but it is in fact the reason I began programming as a young boy in the first place. While it is likely that I would have eventually picked up a programming book for some other reason, I owe that point in time entirely to this game. Allow me to explain. At the age of 10, I would spend much of my time on the Internet downloading various games and demos that may satisfy my interests (the old days of CNET's download.com showed me many of those, I believe). One of those games that immediately captivated me was LaserTank, but not purely for reasons of gameplay. It had this wonderful feature that added so much potential (and replayability) to the game -- a map editor. I found myself enthralled with the map editor to the point where I spent all my time creating maps rather than playing the game. What fascinated me was the ability to essentially create portions of the game -- to tell the game what to do and how to function. I was not able to create my own game using this editor, but I felt like I was creating portions of it. That said, I soon realized that it wasn't enough; I needed to do more. It was the limitations of the map editor and the enjoyment of creating the maps that caused me to convince my parents to take me to Barnes and Noble to purchase my first programming book - Learn to Program with Visual Basic 6 by John Smiley (N.B. Visual Basic is proprietary and I cannot recommend using it. I had no knowledge of the evils of proprietary software back at that point in time.) My parents had their doubts, but that only pushed me even harder to learn. Ironically, the book was about creating a business application. I found this process very enjoyable and began focusing more on conventional desktop software rather than gaming. I did create a couple games (bop-a-mole and breakout among others), but my focus was never game development. Eventually, I moved on from Visual Basic and got into web development. Following that, I discovered GNU/Linux and began getting more and more into lower-level systems and languages (such as C and ASM) and began adopting the hacker ethic. That brings us to where I am today -- nearly 13 years later. It would only seem fitting to bring my hobby-turned-career full circle by cloning the very game that started everything. When I say "clone", I mean nothing more; there will be no additional features or modifications to the original gameplay, menus, graphics, etc. It will support all original file formats (I will develop none of my own). The only differences between the clone and the original game will arise from the obvious issues introduced by cloning the game on a web platform. Specifically, the user will have the option to load files from either their local box or a remote resource, and I may provide pre-masked tile sets for browsers that do not support the canvas element (a fallback mode, if you will). No matter what the change, though, the gameplay will remain identical. That said, the library resulting from the clone will be built with extensibility in mind. If a user (or myself) wishes to create a derivative work by hooking or extending the library (for example, to support larger maps, add additional blocks/enemies, multiplayer support, etc), that should be fairly trivial to do. However, those works will be entirely separate from the clone and clearly distinguished. I think the original LaserTank is perfect the way it is. Remember, it has a special place in my heart (aww) and I would like to preserve the game as I remember it back then. --- Alright; now that we have a great deal of unnecessary history out of the way, let's get into the implementation details for this commit (if you're reading this as a blog entry, see the first commit). This commit represents a proof-of-concept showing that the LTG files (containing the LaserTank graphics) can be properly loaded and their masks properly applied. This was the first major concern for the project and, if a workaround were needed, would have prevented me from creating a full clone (as it would not support loading LTG files without having them first sent to the server, processed, and returned in a different format). The LTG file contains some metadata (including the name, author and description) as well as two bitmaps (BMPs) -- the game tileset and the associated mask. The game bitmap's position was static, but its length and the offset of the mask bitmap were provided by the four bytes immediately preceding the game bitmap (the TLTGREC struct in LTANK.H of the original sources represented this value as a DWORD, which represents a 32-bit integer). The only challenge with converting this value into an integer that we could use is its endianness -- is the most significant byte at the beginning or end? Windows programs (of which LaserTank is) generally write in little-endian format, but to be sure we can simply open up the LTG file in your favorite HEX editor (I simply use `xxd`). In the case of the original tileset, the four bytes immediately preceding the bitmap header (as identified by 'BM', or `424d`) were `7a f5 00 00`, which on its own clearly indicates little-endianness. We can verify by searching for 'BM' once again, and finding that it begins at location `f5 7a` (if your HEX editor displays in big-endian format). To convert into a number, we can simply add up each byte individually, left-shifting by 8N bits, where N is the 0-indexed byte position. Loading the BMP files was then fairly trivial; the file could be loaded into memory (read from disk using FileReader) and we could cut the relevant portions of the binary string out. The bitmaps could then be base64-encoded and the "src" attribute of an Image object set to 'data:image/bmp;base64,B', where B is the base64-encoded BMP. This could then be rendered however we please - CSS sprites or to a canvas. The problem with CSS sprites is that we need to apply the mask and there is no reliable way to do this without a canvas; transparency in the browser is normally handled using GIFs or PNGs. As it turns out, the canvas performs masking using the alpha channel as well, so I would have to create my own masking algorithm to manipulate the alpha channel of the tileset. To complicate matters even more, certain tiles had no mask, and they did not consistently represent the mask with all black (black is used in LT to indicate opacity), meaning that the algorithm would have to understand what tiles should be skipped entirely. The solution was to simply loop through each tile and set the alpha byte of each pixel relative to the respective pixel on the map. Because the images were created out of data in memory, the canvas is not tainted when the image is rendered before using getImageData(). To help speed up the process, since we know that the mask can only contain black and white, we need only check one of the channels; we do not need to calculate brightness. This process successfully returns each individual tile, properly masked, which can be rendered to the canvas using putImageData(). Crisis averted. With that major concern out of the way, the clone should no longer be a problem. I go into more detail in the comments within LtgLoader and TileMasker. This is going to be an exciting process, both because of the LT clone itself and because this is my first experience working with the canvas element. As aforementioned, I seldom create games and I have had no use for the canvas thus far. Hopefully this project will be well-received by both those who have played LaserTank in the past and the original developer of the game (Jim Kindley, JEK Software). LaserTank is a fairly old game and is not likely to be well known anymore, but the game itself is a blast (no pun intended) and bringing it to the browser, where it can be used on any platform (including mobile devices), should allow everyone to enjoy it. The source code is released under the GNU AGPL to ensure that the users' freedoms are preserved even if this game is rendered or in any way run server-side.
2012-03-11 21:38:06 -04:00
/**
* Combined, minified redistributable ease.js file.
* http://easejs.org/
* Licensed under the GNU LGPL v3+ <http://www.gnu.org/licenses>
* Copyright (C) 2010,2011 Mike Gerwitz
*/
var easejs={};
(function(x){var l={},j=function(b){var d=b.replace(/^\.?\/|[^/]*?\/\.\.\/|\.js$/,""),d=l[d];if(void 0===d)throw"[ease.js] Undefined module: "+b;return d.exports};(function(b){var d={"public":!0,"protected":!0,"private":!0,"static":!0,"abstract":!0,"const":!0,virtual:!0,override:!0};(b.exports={}).parseKeywords=function(a){var b=a,c=[],f={},a=""+a;if(/ /.test(a))for(var c=a.split(/\s+/),b=c.pop(),a=c.length,e="";a--;){e=c[a];if(!d[e])throw Error("Unexpected keyword for '"+b+"': "+e);f[e]=!0}return{name:b,
keywords:f}}})(l.prop_parser={},".");(function(b,d){function a(c,e){for(var a=e.length;a--;)if(null===e[a].match(/^[a-z_][a-z0-9_]*$/i))throw SyntaxError("Member "+c+" contains invalid parameter '"+e[a]+"'");}function g(){var a;return e?function(a,e,b){try{Object.defineProperty(a,e,{value:b,enumerable:!1,writable:!1,configurable:!1})}catch(f){c.definePropertyFallback(!0),a[e]=b}}:function(c,a,e){c[a]=e}}var c=b.exports={},f=j(d+"/prop_parser").parseKeywords,e;a:{if("function"===typeof Object.defineProperty)try{Object.defineProperty({},
"x",{});e=!0;break a}catch(h){}e=!1}c.freeze="function"===typeof Object.freeze?Object.freeze:function(){};c.definePropertyFallback=function(a){if(void 0===a)return!e;e=!a;c.defineSecureProp=g();return c};c.defineSecureProp=g();c.clone=function m(c,a){a=!!a;if(c instanceof Array){if(!a)return c.slice(0);for(var e=[],b=0,f=c.length;b<f;b++)e.push(m(c[b],a));return e}if("function"!==typeof c&&c instanceof Object){e={};b=Object.prototype.hasOwnProperty;for(f in c)b.call(c,f)&&(e[f]=a?m(c[f]):c[f]);return e}return c};
c.copyTo=function(a,b,f){var f=!!f,d;if(!(a instanceof Object)||!(b instanceof Object))throw TypeError("Must provide both source and destination objects");if(e)for(var i in b)d=Object.getOwnPropertyDescriptor(b,i),d.get||d.set?Object.defineProperty(a,i,d):a[i]=f?c.clone(b[i],!0):b[i];else for(i in b)a[i]=f?c.clone(b[i],!0):b[i];return a};c.propParse=function(b,d){var h=function(){},g=d.each||void 0,i=d.property||h,k=d.method||h,h=d.getset||h,j=d.keywordParser||f,l=Object.prototype.hasOwnProperty,
o={},n="",o={},s=null,A=!1,v=!1,w;for(w in b)if(l.call(b,w)){if(e)n=Object.getOwnPropertyDescriptor(b,w),A=n.get,v=n.set;s=b[w];o=j(w)||{};n=o.name||w;o=o.keywords||{};if(d.assumeAbstract||o["abstract"]){o["abstract"]=!0;if(!(s instanceof Array))throw TypeError("Missing parameter list for abstract method: "+n);a(n,s);s=c.createAbstractMethod.apply(this,s)}g&&g.call(g,n,s,o);A||v?h.call(h,n,A,v,o):"function"===typeof s?k.call(k,n,s,c.isAbstractMethod(s),o):i.call(i,n,s,o)}};c.createAbstractMethod=
function(a){var e=Array.prototype.slice.call(arguments),b=function(){throw Error("Cannot call abstract method");};c.defineSecureProp(b,"abstractFlag",!0);c.defineSecureProp(b,"definition",e);c.defineSecureProp(b,"__length",arguments.length);return b};c.isAbstractMethod=function(c){return"function"===typeof c&&!0===c.abstractFlag?!0:!1};c.arrayShrink=function(c){for(var a=[],e=0,b=c.length;e<b;e++){var f=c[e];void 0!==f&&a.push(f)}return a};c.getOwnPropertyDescriptor=e&&Object.getOwnPropertyDescriptor||
function(c,a){return!Object.prototype.hasOwnProperty.call(c,a)?void 0:{get:void 0,set:void 0,writable:!0,enumerable:!0,configurable:!0,value:c[a]}};c.getPrototypeOf=Object.getPrototypeOf||function(){};c.getPropertyDescriptor=function(a,e,b){var b=!!b,f=c.getOwnPropertyDescriptor(a,e),a=c.getPrototypeOf(a);return!f&&a&&(!b||c.getPrototypeOf(a))?c.getPropertyDescriptor(a,e,b):f};c.defineSecureProp(c.getPropertyDescriptor,"canTraverse",Object.getPrototypeOf?!0:!1)})(l.util={},".");(function(b,d){var a=
b.exports={},g=j(d+"/util");b.exports=a=function(){if(!(this instanceof a))return new b.exports};a.prototype.setup=function(c,a,e){var b=this._createPrivateLayer(c,a);this._doSetup(c,a["public"]);this._doSetup(c,a["protected"],e["protected"],"public");this._doSetup(b,a["private"],e["private"]);return b};a.prototype._createPrivateLayer=function(c,a){var b=function(){};b.prototype=c;b=new b;this.createPropProxy(c,b,a["protected"]);return b};a.prototype._doSetup=function(c,a,b,d){var u=Array.prototype.hasOwnProperty,
m=null;if(void 0!==b)for(var r in b)if(u.call(b,r)&&(m=c[r],!d||void 0===m||!m.___$$keywords$$[d]))c[r]=b[r];for(var p in a)u.call(a,p)&&(c[p]=g.clone(a[p][0]))};a.prototype.createPropProxy=function(a,b,e){var d=Object.prototype.hasOwnProperty,g;for(g in e)d.call(e,g)&&function(e){b[e]=void 0;Object.defineProperty(b,e,{set:function(b){a[e]=b},get:function(){return a[e]},enumerable:!0})}.call(null,g);return b}})(l.VisibilityObjectFactory={},".");(function(b,d){var a=b.exports={};b.exports=a=function(){if(!(this instanceof
a))return new b.exports};a.prototype=j(d+"/VisibilityObjectFactory")();a.prototype._createPrivateLayer=function(a){return a};a.prototype.createPropProxy=function(a){return a}})(l.FallbackVisibilityObjectFactory={},".");(function(b,d){var a=b.exports={},g=j(d+"/util"),c=j(d+"/VisibilityObjectFactory"),f=j(d+"/FallbackVisibilityObjectFactory");a.fromEnvironment=function(){return g.definePropertyFallback()?f():c()}})(l.VisibilityObjectFactoryFactory={},".");(function(b){var b=b.exports={},d=null,a="undefined"!==
typeof console?console:void 0,g=b.Warning=function(a){if(!(this instanceof g))return new g(a);if(!(a instanceof Error))throw TypeError("Must provide exception to wrap");Error.prototype.constructor.call(this,a.message);this.message=a.message;this.name="Warning";this._error=a;this.stack=a.stack&&a.stack.replace(/^.*?\n+/,this.name+": "+this.message+"\n")};g.prototype=Error();g.prototype.constructor=g;g.prototype.name="Warning";g.prototype.getError=function(){return this._error};b.handlers={log:function(b){var d;
a&&(d=a.warn||a.log)&&d("Warning: "+b.message)},throwError:function(a){throw a.getError();},dismiss:function(){}};b.setHandler=function(a){d=a};b.handle=function(a){d(a)};b.setConsole=function(b){a=b};d=b.handlers.log})(l.warn={},".");(function(b,d){function a(a,b,c){if(a.___$$abstract$$){if(0===c.__length)throw TypeError("Class "+(b||"(anonymous)")+" was declared as abstract, but contains no abstract members");}else if(0<c.__length)throw TypeError("Class "+(b||"(anonymous)")+" contains abstract members and must therefore be declared abstract");
}function g(a){return a["static"]||a["const"]?!0:!1}function c(a){var b=this,c=function(){};c.prototype=a;c=new c;a.___$$svis$$=c;c.$=function(){b._spropInternal=!0;var c=a.$.apply(a,arguments);b._spropInternal=!1;return c}}function f(a,b,c,e){var d=b.methods,f=b.props,g=this;(b=c.___$$sinit$$)&&b(a,!0);if(!e)a.___$$sprops$$=f,k.defineSecureProp(a,"$",function(b,e){var d=Object.prototype.hasOwnProperty,h=!1,v=this.___$$sprops$$?this:a,o=v!==a,h=d.call(f["public"],b)&&"public";!h&&g._spropInternal&&
(h=d.call(f["protected"],b)&&"protected"||!o&&d.call(f["private"],b)&&"private");if(!1===h)return(c.__cid&&c.$||i.ClassBase.$).apply(v,arguments);d=f[h][b];if(1<arguments.length){if(d[1]["const"])throw TypeError("Cannot modify constant property '"+b+"'");d[0]=e;return v}return d[0]});k.copyTo(a,d["public"],!0);k.copyTo(a.___$$svis$$,d["protected"],!0);e||k.copyTo(a.___$$svis$$,d["private"],!0)}function e(a,b){var c=b.__cid?i.getMeta(b):void 0;a.___$$meta$$=c?k.clone(c,!0):{implemented:[]};return a.prototype.___$$meta$$=
a.___$$meta$$}function h(a,b){k.defineSecureProp(a,"__iid",b)}function u(a){var b=function(){};b.prototype=a;a.___$$vis$$=new b}function m(a){var c=function(c){return b.exports.isInstanceOf(c,a)};k.defineSecureProp(a,"isInstanceOf",c);k.defineSecureProp(a,"isA",c)}function r(a,b){var c=0<b.__length?!0:!1;k.defineSecureProp(a,"isAbstract",function(){return c})}function p(a,b){k.defineSecureProp(a,"__cid",b);k.defineSecureProp(a.prototype,"__cid",b)}function q(a,b){a.___$$final$$=!!b.___$$final$$;a.___$$abstract$$=
!!b.___$$abstract$$;b.___$$final$$=b.___$$abstract$$=void 0}var i=b.exports={},k=j(d+"/util"),l=j(d+"/warn"),z=l.Warning,o=!1===Object.prototype.propertyIsEnumerable.call({toString:function(){}},"toString")?!0:!1,n={__initProps:!0},s={__construct:!0,toString:!0,__toString:!0};b.exports=i=function(a,c){if(!(this instanceof i))return new b.exports(a,c);this._memberBuilder=a;this._visFactory=c;this._instanceId=this._classId=0;this._spropInternal=this._extending=!1};i.ClassBase=function(){};i.ClassBase.$=
function(a,b){if(void 0!==b)throw ReferenceError("Cannot set value of undeclared static property '"+a+"'");};i.getReservedMembers=function(){return k.clone(n,!0)};i.getForcedPublicMethods=function(){return k.clone(s,!0)};i.getMeta=function(a){return a.___$$meta$$||{}};i.isInstanceOf=function(a,b){var c,e;if(!a||!b)return!1;try{if(b instanceof a)return!0}catch(d){}if(!b.__cid||!(c=i.getMeta(b)))return!1;c=c.implemented;for(e=c.length;e--;)if(c[e]===a)return!0;return!1};i.prototype.build=function(b,
d){this._extending=!0;var h=Array.prototype.slice.call(arguments),g=h.pop()||{},u=h.pop()||i.ClassBase,m=this._getBase(u),h="",n=this._memberBuilder.initMembers(),s=this._memberBuilder.initMembers(m),j={methods:this._memberBuilder.initMembers(),props:this._memberBuilder.initMembers()},y=k.clone(i.getMeta(u).abstractMethods)||{__length:0};if(!0===u.___$$final$$)throw Error("Cannot extend final class "+(u.___$$meta$$.name||"(anonymous)"));(h=g.__name)&&delete g.__name;if(o&&g.toString!==Object.prototype.toString)g.__toString=
g.toString;this._classId++;try{this.buildMembers(g,this._classId,u,n,y,s,j,function(){return t.___$$svis$$})}catch(B){if(B instanceof z)l.handle(B);else throw B;}m.___$$parent$$=u.prototype;var t=this.createCtor(h,y,s);c(t);var D=function(a,b){f(a,j,u,b)};D(t,!1);this._attachPropInit(m,n,s,t,this._classId);t.prototype=m;t.constructor=t;t.___$$props$$=n;t.___$$methods$$=s;t.___$$sinit$$=D;q(t,g);a(t,h,y);k.defineSecureProp(m,"__self",t.___$$svis$$);g=e(t,u);g.abstractMethods=y;g.name=h;r(t,y);p(t,
this._classId);this._extending=!1;return t};i.prototype._getBase=function(a){switch(typeof a){case "function":return new a;case "object":return a}throw TypeError("Must extend from Class, constructor or object");};i.prototype.buildMembers=function(a,b,c,e,d,f,h,u){var m=Array.prototype.hasOwnProperty,o={},r=h.methods,q=h.props,p=this;k.propParse(a,{each:function(a){if(!0===n[a])throw Error(a+" is reserved");if(m.call(o,a))throw Error("Cannot redefine method '"+a+"' in same declaration");o[a]=1},property:function(a,
b,d){var f=g(d)?q:e;p._memberBuilder.buildProp(f,null,a,b,d,c)},getset:function(a,b,e,d){var h=g(d)?r:f;p._memberBuilder.buildGetterSetter(h,null,a,b,e,d,c)},method:function(a,e,h,o){var k=g(o),n=k?r:f,k=k?u:i.getMethodInstance;if(!0===s[a]&&(o["protected"]||o["private"]))throw TypeError(a+" must be public");p._memberBuilder.buildMethod(n,null,a,e,o,k,b,c);h?(d[a]=!0,d.__length++):m.call(d,a)&&!1===h&&(delete d[a],d.__length--)}})};i.prototype.createCtor=function(a,b,c){return 0===b.__length?this.createConcreteCtor(a,
c):this.createAbstractCtor(a)};i.prototype.createConcreteCtor=function(a,b){function c(){if(!(this instanceof c))return e=arguments,new c;u(this);this.__initProps();if(!d._extending&&(h(this,++d._instanceId),"function"===typeof this.__construct&&(this.__construct.apply(this,e||arguments),e=null),m(this),!Object.prototype.hasOwnProperty.call(b["public"],"toString")))this.toString=b["public"].__toString||(a?function(){return"#<"+a+">"}:function(){return"#<anonymous>"})}var e=null,d=this;c.toString=
a?function(){return a}:function(){return"(Class)"};return c};i.prototype.createAbstractCtor=function(a){var b=this,c=function(){if(!b._extending)throw Error("Abstract class "+(a||"(anonymous)")+" cannot be instantiated");};c.toString=a?function(){return a}:function(){return"(AbstractClass)"};return c};i.prototype._attachPropInit=function(a,b,c,e,d){var f=this;k.defineSecureProp(a,"__initProps",function(e){var e=!!e,h=a.___$$parent$$,h=h&&h.__initProps;"function"===typeof h&&h.call(this,!0);h=f._visFactory.createPropProxy(this,
this.___$$vis$$,b["public"]);h=this.___$$vis$$[d]=f._visFactory.setup(h,b,c);e||k.defineSecureProp(h,"__inst",this)})};i.getMethodInstance=function(a,b){var c=a.___$$vis$$;return a.__iid&&c?c[b]:null}})(l.ClassBuilder={},".");(function(b){var d=b.exports={};b.exports=d=function(a){if(!(this instanceof d))return new b.exports(a);this._factory=a};d.prototype.wrapMethod=function(a,b,c,d){return this._factory(a,b,c,d)}})(l.MethodWrapperFactory={},".");(function(b){(b.exports={}).standard={wrapOverride:function(b,
a,g,c){return function(){var f=c(this,g)||this,e=void 0;f.__super=a;e=b.apply(f,arguments);f.__super=void 0;return e===f?this:e}},wrapNew:function(b,a,g,c){return function(){var a=c(this,g)||this,e=void 0,e=b.apply(a,arguments);return e===a?this:e}}}})(l.MethodWrappers={},".");(function(b,d){function a(a,b,c){var e=function(){throw TypeError("Only one access modifier may be used for definition of '"+c+"'");};if(b["private"])return(b["public"]||b["protected"])&&e(),a["private"];if(b["protected"])return(b["public"]||
b["private"])&&e(),a["protected"];(b["private"]||b["protected"])&&e();return a["public"]}function g(a,b,c){for(var d=e.length,p=null;d--;)if(p=f.getPropertyDescriptor(a[e[d]],b,!0))return{get:p.get,set:p.set,member:p.value};return void 0!==c?(a=c.___$$methods$$,c=c.___$$props$$,a&&g(a,b)||c&&g(c,b)||null):null}var c=b.exports={},f=j(d+"/util");j(d+"/warn");var e=["public","protected","private"];b.exports=function(a,c,e){if(!(this instanceof b.exports))return new b.exports(a,c,e);this._wrapMethod=
a;this._wrapOverride=c;this._validate=e};c=b.exports.prototype;c.initMembers=function(a,b,c){return{"public":a||{},"protected":b||{},"private":c||{}}};c.buildMethod=function(b,c,e,d,f,q,i,k){var j=(k=(c=g(b,e,k))?c.member:null)&&k.___$$keywords$$,b=a(b,f,e);this._validate.validateMethod(e,d,f,c,j);if(k)if(f.override||j["abstract"])d=this._overrideMethod(k,d,q,i);else throw Error("Method hiding not yet implemented (we should never get here; bug).");else d=f["abstract"]?d:this._overrideMethod(null,
d,q,i);b[e]=d;b[e].___$$keywords$$=f};c.buildProp=function(b,c,e,d,f,q){q=(c=g(b,e,q))?c.member:null;this._validate.validateProperty(e,d,f,c,q?q[1]:null);a(b,f,e)[e]=[d,f]};c.buildGetterSetter=function(b,c,e,d,f,q,i){c=g(b,e,i);this._validate.validateGetterSetter(e,{},q,c,c&&c.get?c.get.___$$keywords$$:null);d.___$$keywords$$=q;Object.defineProperty(a(b,q,e),e,{get:d,set:f,enumerable:!0,configurable:!1})};c._overrideMethod=function(a,b,c,e){var d=null,d=(a?this._wrapOverride:this._wrapMethod).wrapMethod(b,
a,e,c||function(){});f.defineSecureProp(d,"__length",b.__length||b.length);return d};c._getVisibilityValue=function(a){return a["protected"]?1:a["private"]?2:0}})(l.MemberBuilder={},".");(function(b){var d=b.exports={};b.exports=d=function(a){if(!(this instanceof b.exports))return new b.exports(a);this._warningHandler=a||function(){}};d.prototype.validateMethod=function(a,b,c,d,e){var h=d?d.member:null;if(c["abstract"]&&c["private"])throw TypeError("Method '"+a+"' cannot be both private and abstract");
if(c["const"])throw TypeError("Cannot declare method '"+a+"' as constant; keyword is redundant");if(c.virtual&&c["static"])throw TypeError("Cannot declare static method '"+a+"' as virtual");if(d&&(d.get||d.set))throw TypeError("Cannot override getter/setter '"+a+"' with method");if(h){if(e["private"])throw TypeError("Private member name '"+a+"' conflicts with supertype");if("function"!==typeof h)throw TypeError("Cannot override property '"+a+"' with method");if(c.override&&!e.virtual)throw TypeError("Cannot override non-virtual method '"+
a+"'");if(c["abstract"]&&!e["abstract"])throw TypeError("Cannot override concrete method '"+a+"' with abstract method");if((b.__length||b.length)<(h.__length||h.length))throw TypeError("Declaration of method '"+a+"' must be compatible with that of its supertype");if(this._getVisibilityValue(e)<this._getVisibilityValue(c))throw TypeError("Cannot de-escalate visibility of method '"+a+"'");if(!c.override&&!e["abstract"])throw TypeError("Attempting to override method '"+a+"' without 'override' keyword");
}else c.override&&this._warningHandler(Error("Method '"+a+"' using 'override' keyword without super method"))};d.prototype.validateProperty=function(a,b,c,d,e){if(b=d?d.member:null){if(e["private"])throw TypeError("Private member name '"+a+"' conflicts with supertype");if("function"===typeof b)throw new TypeError("Cannot override method '"+a+"' with property");if(this._getVisibilityValue(e)<this._getVisibilityValue(c))throw TypeError("Cannot de-escalate visibility of property '"+a+"'");}if(d&&(d.get||
d.set))throw TypeError("Cannot override getter/setter '"+a+"' with property");if(c["abstract"])throw TypeError("Property '"+a+"' cannot be declared as abstract");if(c["static"]&&c["const"])throw TypeError("Static keyword cannot be used with const for property '"+a+"'");if(c.virtual)throw TypeError("Cannot declare property '"+a+"' as virtual");};d.prototype.validateGetterSetter=function(a,b,c,d,e){b=d?d.member:null;d=d&&(d.get||d.set)?!0:!1;if(c["abstract"])throw TypeError("Cannot declare getter/setter '"+
a+"' as abstract");if(c["const"])throw TypeError("Cannot declare const getter/setter '"+a+"'");if(c.virtual&&c["static"])throw TypeError("Cannot declare static method '"+a+"' as virtual");if(b||d){if(e&&e["private"])throw TypeError("Private member name '"+a+"' conflicts with supertype");if(!d)throw TypeError("Cannot override method or property '"+a+"' with getter/setter");if(!e.virtual)throw TypeError("Cannot override non-virtual getter/setter '"+a+"'");if(!c.override)throw TypeError("Attempting to override getter/setter '"+
a+"' without 'override' keyword");if(this._getVisibilityValue(e||{})<this._getVisibilityValue(c))throw TypeError("Cannot de-escalate visibility of getter/setter '"+a+"'");}else c.override&&this._warningHandler(Error("Getter/setter '"+a+"' using 'override' keyword without super getter/setter"))};d.prototype._getVisibilityValue=function(a){return a["protected"]?1:a["private"]?2:0}})(l.MemberBuilderValidator={},".");(function(b,d){function a(a){if(1<arguments.length)throw Error("Expecting one argument for anonymous Class definition; "+
arguments.length+" given.");return e(a)}function g(a,b){if(2<arguments.length)throw Error("Expecting at most two arguments for definition of named Class '"+a+"'; "+arguments.length+" given.");if(void 0===b)return c(a);if("object"!==typeof b)throw TypeError("Unexpected value for definition of named Class '"+a+"'; object expected");b.__name=a;return e(b)}function c(a){return{extend:function(){var b=Array.prototype.slice.apply(arguments);b[b.length-1].__name=a;return e.apply(null,b)},implement:function(){return f(null,
Array.prototype.slice.call(arguments),a)}}}function f(a,b,c){return{extend:function(){var d=Array.prototype.slice.call(arguments),f=d.pop(),g=d.pop();if(0<d.length)throw Error("Expecting no more than two arguments for extend()");if(a&&g)throw Error("Cannot override parent "+a.toString()+" with "+g.toString()+" via extend()");if(c)f.__name=c;b.push(a||g||e({}));return e.call(null,z.apply(this,b),f)}}}function e(a,b){var c=C.build.apply(C,arguments),e=c;h(e);l(e);m.freeze(c);return c}function h(a){m.defineSecureProp(a,
"extend",function(a){return e(this,a)})}function l(a){m.defineSecureProp(a,"implement",function(){return f(a,Array.prototype.slice.call(arguments))})}b.exports={};var m=j(d+"/util"),r=j(d+"/ClassBuilder"),p=j(d+"/warn"),q=p.Warning,i=j(d+"/MethodWrapperFactory"),k=j(d+"/MethodWrappers").standard,C=r(j(d+"/MemberBuilder")(i(k.wrapNew),i(k.wrapOverride),j(d+"/MemberBuilderValidator")(function(a){p.handle(q(a))})),j(d+"/VisibilityObjectFactoryFactory").fromEnvironment());b.exports=function(b,c){var e=
null;switch(typeof b){case "object":e=a.apply(null,arguments);break;case "string":e=g.apply(null,arguments);break;default:throw TypeError("Expecting anonymous class definition or named class definition");}return e};b.exports.extend=function(a,b){return e.apply(this,arguments)};b.exports.implement=function(a){return f(null,Array.prototype.slice.call(arguments))};b.exports.isClass=function(a){a=a||{};return a.prototype instanceof r.ClassBase?!0:!1};b.exports.isClassInstance=function(a){a=a||{};return a instanceof
r.ClassBase?!0:!1};b.exports.isInstanceOf=r.isInstanceOf;b.exports.isA=b.exports.isInstanceOf;var z=function(a,c){for(var e=Array.prototype.slice.call(arguments),d={},f=e.pop(),g=e.length,h=null,i=[],k=!1,q=0;q<g;q++)h=e[q],m.propParse(h.prototype,{method:function(a,b){d["abstract "+a]=b.definition;k=!0}}),i.push(h);if(k)d.___$$abstract$$=!0;e=b.exports.extend(f,d);r.getMeta(e).implemented=i;return e}})(l["class"]={},".");(function(b,d){function a(a){a=a[a.length-1];if("object"===typeof a)a.___$$final$$=
!0}function g(b){var c=b.extend;b.extend=function(){a(arguments);return c.apply(this,arguments)}}var c=b.exports={},f=j(d+"/class"),c=b.exports=function(){a(arguments);var b=f.apply(this,arguments);f.isClass(b)||g(b);return b};c.extend=function(){a(arguments);return f.extend.apply(this,arguments)}})(l.class_final={},".");(function(b,d){var a=b.exports={},g=j(d+"/MemberBuilder");b.exports=a=function(a,d){if(!(this instanceof b.exports))return new b.exports(a,d);b.exports.prototype.constructor.call(this,
a,d)};b.exports.prototype=new g;b.exports.constructor=b.exports;a.prototype.buildGetterSetter=function(){throw Error("Getters/setters are unsupported in this environment");}})(l.FallbackMemberBuilder={},".");(function(b,d){function a(a){a=a[a.length-1];if("object"===typeof a)a.___$$abstract$$=!0}function g(b){var c=b.extend,d=b.implement;d&&(b.implement=function(){return g(d.apply(this,arguments))});b.extend=function(){a(arguments);return c.apply(this,arguments)};return b}var c=b.exports={},f=j(d+
"/class");b.exports=c=function(){a(arguments);var b=f.apply(this,arguments);f.isClass(b)||g(b);return b};c.extend=function(){a(arguments);return f.extend.apply(this,arguments)};c.implement=function(){var a=f.implement.apply(this,arguments);g(a);return a}})(l.class_abstract={},".");(function(b,d){function a(){}function g(a){if(1<arguments.length)throw Error("Expecting one argument for Interface definition; "+arguments.length+" given.");return p(a)}function c(a,b){if(2<arguments.length)throw Error("Expecting two arguments for definition of named Interface '"+
a+"'; "+arguments.length+" given.");if("object"!==typeof b)throw TypeError("Unexpected value for definition of named Interface '"+a+"'; object expected");b.__name=a;return p(b)}function f(a){h.defineSecureProp(a,"extend",function(a){return p(this,a)})}function e(a,b){a.toString=b?function(){return"[object Interface <"+b+">]"}:function(){return"[object Interface]"}}b.exports={};var h=j(d+"/util"),l=j(d+"/MethodWrapperFactory"),m=j(d+"/MethodWrappers").standard,r=j(d+"/MemberBuilder")(l(m.wrapNew),
l(m.wrapOverride),j(d+"/MemberBuilderValidator")());j(d+"/class");b.exports=function(a,b){var d=null;switch(typeof a){case "object":d=g.apply(null,arguments);break;case "string":d=c.apply(null,arguments);break;default:throw TypeError("Expecting anonymous interface definition or named interface definition");}return d};b.exports.extend=function(){return p.apply(this,arguments)};b.exports.isInterface=function(b){b=b||{};return b.prototype instanceof a?!0:!1};var p=function(b){function c(a){return function(){if(!b)throw Error("Interface"+
(a?a+" ":"")+" cannot be instantiated");}}return function(){b=!0;var d=Array.prototype.slice.call(arguments),g=d.pop()||{},d=new (d.pop()||a),j="",l=r.initMembers(d,d,d);(j=g.__name)&&delete g.__name;if(!(d instanceof a))throw new TypeError("Interfaces may only extend other interfaces");var n=c(j);try{h.propParse(g,{assumeAbstract:!0,property:function(){throw TypeError("Unexpected internal error");},getset:function(){throw TypeError("Unexpected internal error");},method:function(a,b,c,d){if(d["protected"]||
d["private"])throw TypeError(j+" member "+a+" must be public");r.buildMethod(l,null,a,b,d)}})}catch(m){throw m.message="Failed to define interface "+(j?j:"(anonymous)")+": "+m.message,m;}f(n);e(n,j);n.prototype=d;n.constructor=n;h.freeze(n);b=!1;return n}}(!1)})(l["interface"]={},".");(function(b){b.exports={};var d=[0,1,0];d.major=0;d.minor=1;d.rev=0;d.toString=function(){return this.join(".")};b.exports=d})(l.version={},".");x.Class=l["class"].exports;x.AbstractClass=l.class_abstract.exports;x.FinalClass=
l.class_final.exports;x.Interface=l["interface"].exports;x.version=l.version.exports})(easejs);