From 8f7a22134057e6c0a8102cc5638f061d041fc679 Mon Sep 17 00:00:00 2001 From: dsc Date: Thu, 10 Feb 2011 01:04:59 -0800 Subject: [PATCH] Adds init wrapper support to simplify mixin initialisation. --- src/evt.cjs | 86 +++++++++++++++++-------------- src/ezl/mixins/speciated.cjs | 1 + src/tanks/inventory/bag.cjs | 5 +- src/tanks/inventory/bagbag.cjs | 7 ++- src/tanks/inventory/container.cjs | 14 +++--- src/tanks/inventory/inventory.cjs | 8 ++-- src/tanks/map/wall.cjs | 2 +- src/tanks/mixins/inventoried.cjs | 6 +- src/tanks/mixins/quantified.cjs | 10 ++-- src/tanks/ui/inventory/containerui.cjs | 1 + 10 files changed, 75 insertions(+), 65 deletions(-) diff --git a/src/evt.cjs b/src/evt.cjs index d8c1880..5ed4e9e 100644 --- a/src/evt.cjs +++ b/src/evt.cjs @@ -43,7 +43,7 @@ var Y = require('Y').Y , classStatics = [ 'instantiate', 'fabricate', 'subclass' ] , classMagic = [ - '__bases__', '__initialise__', '__class__', 'constructor', 'className', + '__bases__', '__initialise__', '__inits__', '__class__', 'constructor', 'className', '__emitter__', '__static__', '__mixins__', '__id__' ] //.concat(classStatics) , mixinSkip = [ @@ -113,22 +113,26 @@ exports['createInitialise'] = function createInitialise(cls){ function initialise(){ var instance = this - , binds = cls.fn.__bind__ // list of names to bind + , proto = cls.fn + , binds = proto.__bind__ // list of names to bind + , init = proto.init + , inits = proto.__inits__ + , args = Y(arguments) ; if (binds) Y.bindAll(instance, binds); - var init = cls.fn.init; - if ( typeof init == 'function' ) { - var result = init.apply(instance, arguments); - if (result) instance = result; // XXX: I think this needs to go away - } + if ( typeof init == 'function' && init !== arguments.callee ) + init.apply(instance, args); + + if ( inits && inits.length ) + inits.invoke('apply', instance, args); instance.emit('init', instance, { 'instance' : instance, 'cls' : cls, - 'args' : Y(arguments) + 'args' : args }, instance); return instance; @@ -136,9 +140,6 @@ function createInitialise(cls){ return Y(initialise); }; -function notClassMagic(v, k){ - return classMagic.indexOf(k) === -1; -} @@ -206,36 +207,39 @@ function Class(className, Parent, members){ eval(constructor); // Copy parent methods, then add new instance methods - for (var k in parentMembers) + for (var k in parentMembers) { if ( hasOwn.call(parentMembers,k) ) setDesc(prototype, k, getDesc(parentMembers,k)); else prototype[k] = parentMembers[k]; + } - if ( prototype.toString === objToString ) + if ( prototype.toString === objToString ) // check SuperClass.fn.toString prototype.toString = classToString; NewClass.className = prototype.className = className; NewClass.prototype = NewClass.fn = prototype; + // Add class emitter + var ParentEmitter = (Parent.__emitter__ ? Parent : ClassFactory) + , ClassEmitter = NewClass.__emitter__ = new Emitter(NewClass, ParentEmitter) + , mixins = members.__mixins__ || [] + ; + // Fix Constructors NewClass.__super__ = SuperClass; // don't override NewClass.constructor -- it should be Function - NewClass.__bases__ = NewClass.fn.__bases__ = Y([SuperClass]).concat( SuperClass.__bases__ || [ Class, Object ] ); + NewClass.__bases__ = NewClass.fn.__bases__ = Y(mixins).concat( [SuperClass], SuperClass.__bases__ || [ Class, Object ] ); prototype.constructor = prototype.__class__ = NewClass; + prototype.__inits__ = new Y.YArray(); NewClass.init = prototype.__initialise__ = createInitialise(NewClass); - // Add class emitter - var ParentEmitter = (Parent.__emitter__ ? Parent : ClassFactory) - , ClassEmitter = NewClass.__emitter__ = new Emitter(NewClass, ParentEmitter) - ; // Record for metaprogramming KNOWN_CLASSES[className] = NewClass; NewClass.__bind__ = prototype.__bind__; - var mixins = NewClass.__mixins__ = Y([]).concat(members.__mixins__||[], SuperClass.__mixins__||[]).unique() - , statics = NewClass.__static__ = {} + var statics = NewClass.__static__ = {} , pstatics = SuperClass.__static__ , mstatics = members.__static__ ; @@ -270,7 +274,7 @@ function Class(className, Parent, members){ } NewClass.instantiate = instantiate.partial(NewClass); - NewClass.__bind__ = prototype.__bind__ = Y([]).concat(prototype.__bind__||[], SuperClass.__bind__||[]).unique(); + NewClass.__bind__ = prototype.__bind__ = Y(prototype.__bind__||[]).concat(SuperClass.__bind__||[]).unique(); // Notify mixins to let them finish up any customization if (mixins.length) @@ -283,8 +287,8 @@ function Class(className, Parent, members){ ParentEmitter.emit('subclass', NewClass, { 'className' : className, - 'parent' : Parent, - 'child' : NewClass, + 'super' : Parent, + 'cls' : NewClass, 'members' : members, 'prototype' : prototype }, NewClass); @@ -299,8 +303,8 @@ Class.__emitter__ = new Emitter(Class); Class.fn = Class.prototype; Class.fn.__class__ = Class.fn.constructor = Class; Class.fn.__bases__ = Class.__bases__ = Y([ Object ]); -Class.fn.__bind__ = Class.__bind__ = Y([]); -Class.className = Class.fn.className = "Class"; +Class.fn.__bind__ = Class.__bind__ = Y([]); +Class.fn.className = Class.className = "Class"; /* Class Methods */ @@ -373,9 +377,10 @@ function mixinFilter(v, k){ * Mixes a Mixin into another Class. */ function mixin(cls, _mxn){ - var proto = cls.fn - , bases = Y(cls.__bases__ || []) - , cbinds = Y(cls.__bind__ || []) + var proto = (typeof cls === "function") ? cls.prototype : cls + , bases = cls.__bases__ = Y(cls.__bases__ || []) + , cbinds = cls.__bind__ = proto.__bind__ = Y(cls.__bind__ || []) + , cinits = cls.__inits__ = proto.__inits__ = Y(cls.__inits__ || []) , cstatic = cls.__static__ , mxns = (Y.isArray(_mxn) ? _mxn.slice(0) : Y(arguments, 1)) ; @@ -386,8 +391,9 @@ function mixin(cls, _mxn){ throw new Error('Cannot mix in non-object! '+mxn); var mproto = (typeof mxn === "function") ? mxn.fn : mxn - , statics = mxn.__static__ + , statics = mxn.__static__ || {} , binds = mxn.__bind__ + , init = mproto.init , onCreate = mproto.onCreate , firstMix = (bases && bases.indexOf(mxn) === -1) ; @@ -395,14 +401,12 @@ function mixin(cls, _mxn){ core.extend(proto, core.filter(mproto, mixinFilter, mproto)); // Add mixin statics to class constructor - if (statics){ - for (var k in statics) - if ( hasOwn.call(statics,k) && classMagic.indexOf(k) === -1 ) { - var desc = getDesc(statics,k); - setDesc(cls, k, desc); - setDesc(cstatic, k, desc); - } - } + for (var k in statics) + if ( hasOwn.call(statics,k) && classMagic.indexOf(k) === -1 ) { + var desc = getDesc(statics,k); + setDesc(cls, k, desc); + setDesc(cstatic, k, desc); + } // Add/ensure the mixin is at the front of bases bases.remove(mxn).unshift(mxn); @@ -411,6 +415,10 @@ function mixin(cls, _mxn){ if (binds) cls.__bind__ = proto.__bind__ = cbinds.concat(binds).unique(); + // Wrap init call + if ( typeof init == 'function' ) + cinits.remove(init).unshift(init); + // Only perform these actions the first time we mix into this class if (!firstMix) return; @@ -444,7 +452,7 @@ function aggregate(cls, key){ Mixin.on('subclass', function onMixinSubclass(evt){ var d = evt.data - , mxn = d.child + , mxn = d.cls , members = d.members , onMixin = members.onMixin ; @@ -464,4 +472,4 @@ exports['instantiate'] = instantiate; exports['fabricate'] = Y.fabricate; exports['lookupClass'] = lookupClass; exports['mixin'] = mixin; -exports['aggregate'] = aggregate; +exports['aggregate'] = aggregate; \ No newline at end of file diff --git a/src/ezl/mixins/speciated.cjs b/src/ezl/mixins/speciated.cjs index dad1630..70195f0 100644 --- a/src/ezl/mixins/speciated.cjs +++ b/src/ezl/mixins/speciated.cjs @@ -126,6 +126,7 @@ Mixin.subclass('Speciated', { onMixin : function mixSpeciated(evt){ var cls = evt.data.cls; cls.__known__ = {}; + cls.on('subclass', arguments.callee); }, toString : function(){ diff --git a/src/tanks/inventory/bag.cjs b/src/tanks/inventory/bag.cjs index bafd675..d535721 100644 --- a/src/tanks/inventory/bag.cjs +++ b/src/tanks/inventory/bag.cjs @@ -15,15 +15,16 @@ Item.subclass('Bag', { /// Setup /// hasUI : true, - highlightIconOnOpen : true, // Whether to highlight the inventory icon when bag is open + uiOptions : null, reqs : null, + // highlightIconOnOpen : true, // Whether to highlight the inventory icon when bag is open /// Bookkeeping /// bagName : null, ui : null, // ContainerUI - init : function initBag(bagName, owner){ + init : function initBag(owner, bagName){ this.bagName = bagName; this.owner = owner; Item.init.call(this); diff --git a/src/tanks/inventory/bagbag.cjs b/src/tanks/inventory/bagbag.cjs index 609b163..bec16a8 100644 --- a/src/tanks/inventory/bagbag.cjs +++ b/src/tanks/inventory/bagbag.cjs @@ -15,8 +15,9 @@ Bag.subclass('BagBag', { /// Setup /// hasUI : true, - highlightIconOnOpen : true, // Whether to highlight the inventory icon when bag is open - reqs : 'bag', + uiOptions : null, + reqs : 'bag', // TODO: parse, enforce reqs + // highlightIconOnOpen : true, // Whether to highlight the inventory icon when bag is open /// Bookkeeping /// bagName : 'bagbag', @@ -25,7 +26,7 @@ Bag.subclass('BagBag', { init : function initBagBag(inventory, player){ this.inventory = inventory; - Bag.init.call(this, 'bagbag', player); + Bag.init.call(this, player, 'bagbag'); this.showUI(); if (this.ui) this.ui.layer.addClass('bagbag bag'); } diff --git a/src/tanks/inventory/container.cjs b/src/tanks/inventory/container.cjs index 775be14..25b005f 100644 --- a/src/tanks/inventory/container.cjs +++ b/src/tanks/inventory/container.cjs @@ -25,15 +25,15 @@ Mixin.subclass('Container', { children : null, // Nested containers: container id -> Container - onCreate : function initContainer(evt, self){ - self.items = {}; - self.children = {}; - self.slots = new Array(self.max); + init : function initContainer(){ + this.items = {}; + this.children = {}; + this.slots = new Array(this.max); - if ( typeof self.reqs == 'string' ) - self.reqs = Y([ self.reqs ]); + if ( typeof this.reqs == 'string' ) + this.reqs = Y([ this.reqs ]); else - self.reqs = Y(self.reqs); + this.reqs = Y(this.reqs); }, setup : function setup(owner, items){ diff --git a/src/tanks/inventory/inventory.cjs b/src/tanks/inventory/inventory.cjs index 10cd7a1..bd9e8ff 100644 --- a/src/tanks/inventory/inventory.cjs +++ b/src/tanks/inventory/inventory.cjs @@ -32,11 +32,11 @@ evt.subclass('Inventory', { belt : null, // {Belt} Size determined by beltSlots bagbag : null, // {BagBag} Size determined by bagSlots - items : {}, // id -> {Item} All items in all bags - equipment : {}, // name -> {Item} All equipped items - bags : {}, // id -> {Container} All bags in all bags + items : {}, // id -> {Item} All items in all bags + equipment : {}, // slot -> {Item} All equipped items + bags : {}, // id -> {Container} All bags in all bags namedBags : {}, // name -> {Container} All named bags in all bags - equipBags : {}, // name -> {EquipSlot} All EquipSlot containers + equipBags : {}, // slot -> {EquipSlot} All EquipSlot containers // Y-wrapped _items : null, diff --git a/src/tanks/map/wall.cjs b/src/tanks/map/wall.cjs index d55914c..fc35e99 100644 --- a/src/tanks/map/wall.cjs +++ b/src/tanks/map/wall.cjs @@ -107,7 +107,7 @@ Thing.subclass('Wall', { Wall.register('wall', Wall); Wall.on('subclass', function(evt){ - var subcls = evt.data.child; + var subcls = evt.data.cls; Wall.register(Y(subcls.className).camelToSnake(), subcls); }); diff --git a/src/tanks/mixins/inventoried.cjs b/src/tanks/mixins/inventoried.cjs index e027927..80f784c 100644 --- a/src/tanks/mixins/inventoried.cjs +++ b/src/tanks/mixins/inventoried.cjs @@ -29,9 +29,9 @@ Mixin.subclass('Inventoried', { }, - onCreate : function initInventoried(evt, self){ - var clsInv = self.__class__.aggregate('inventory') - , inv = self.inventory = deepcopy(clsInv) + init : function initInventoried(){ + var clsInv = this.__class__.aggregate('inventory') + , inv = this.inventory = deepcopy(clsInv) ; inv.items = {}; inv.backpack = new Array(inv.max); diff --git a/src/tanks/mixins/quantified.cjs b/src/tanks/mixins/quantified.cjs index b21ac8b..b65af5a 100644 --- a/src/tanks/mixins/quantified.cjs +++ b/src/tanks/mixins/quantified.cjs @@ -17,12 +17,10 @@ Mixin.subclass('Quantified', { buffs : [], - onCreate : function initQuantified(evt, self){ - self.buffs = Y([]); - self.on('buff.conjure', self.onBuffAcquired); - self.on('buff.die', self.onBuffLost); - // self.on('buff.conjure', self.onBuffAcquired.bind(self)); - // self.on('buff.die', self.onBuffLost.bind(self)); + init : function initQuantified(){ + this.buffs = Y([]); + this.on('buff.conjure', this.onBuffAcquired); + this.on('buff.die', this.onBuffLost); }, stat : function stat(k){ diff --git a/src/tanks/ui/inventory/containerui.cjs b/src/tanks/ui/inventory/containerui.cjs index 09cc579..39936ab 100644 --- a/src/tanks/ui/inventory/containerui.cjs +++ b/src/tanks/ui/inventory/containerui.cjs @@ -9,6 +9,7 @@ var Y = require('Y').Y ContainerUI = exports['ContainerUI'] = HtmlLayer.subclass('ContainerUI', { + __mixins__ : [], __bind__ : [ 'onItemUpdated', 'onDrop' ], _layerClasses : 'item-container hud', -- 1.7.0.4