[SOLVED] Events accumulation on stock

Game development with Board Game Arena Studio
Post Reply
User avatar
Woodruff
Posts: 423
Joined: 08 March 2014, 00:53

[SOLVED] Events accumulation on stock

Post by Woodruff »

Hi everybody !

I need to use the same event "onChangeSelection" on the same stock component (this.stock.hand[this.my_id]) for two different game states:

Code: Select all

        onEnteringState: function( stateName, args )
        {
            switch( stateName )
            {
            case 'turn0':
                console.log("turn0")
                this.stock.hand[this.my_id].setSelectionMode(1);
                dojo.connect(this.stock.hand[this.my_id], 'onChangeSelection', this, 'action_clicForInitialMeld' );
                break;
            case 'playerTurn':
                this.stock.hand[this.my_id].setSelectionMode(1);
                dojo.connect(this.stock.hand[this.my_id], 'onChangeSelection', this, 'action_clicForMeld' );
                break;
            }
        },
"turn0"is the first play state. When I reach it and the player triggers the event, all is OK.
"playerTurn" is the common play state, each player get active on their turn for this state. But then when the player choose his card, it triggers both events 'action_clicForInitialMeld' and 'action_clicForMeld', displaying an error message for the first one since the game state is wrong. The action resulting after the second event is proceeded correctly.

I assume the problem is that the first listener has not been disconnected. I found nothing in BGA doc about disconnexion so I decided to put in place my own connect/disconnect mechanism based on dojo.connect and dojo.disconnect. The ideas behind that were found on the last topic of this thread http://stackoverflow.com/questions/8707 ... rs-in-dojo:

Code: Select all

        ///////////////////////////////////////////////////
        //// Simple handler management system
        // this.on replace dojo.connect
        // this.off enables to disconnect all handlers on the object attached with this.on
        
        on: function (obj, event, context, method, dontFix) {
            if(obj._connectHandlers == undefined)
            {
                obj._connectHandlers = [];
            }
            var handler = dojo.connect(obj, event, context, method, dontFix);
            obj._connectHandlers.push(handler);
            return handler;
        },

        off: function (obj) {
            if(obj._connectHandlers == undefined) {
                return;
            }
            dojo.forEach(obj._connectHandlers, "dojo.disconnect(item)");  
        },
So I replace dojo.connect by this.on which calls it but getting track of all events being attached on the node:

Code: Select all

        onEnteringState: function( stateName, args )
        {
            switch( stateName )
            {
            case 'turn0':
                this.stock.hand[this.my_id].setSelectionMode(1);
                this.on(this.stock.hand[this.my_id], 'onChangeSelection', this, 'action_clicForInitialMeld' )
                break;
            case 'playerTurn':
                this.stock.hand[this.my_id].setSelectionMode(1);
                this.on(this.stock.hand[this.my_id], 'onChangeSelection', this, 'action_clicForMeld' )
                break
            }
        },

And I make the disconnection after the ajax call:

Code: Select all

        action_clicForInitialMeld : function(control_name) {
            console.log('initial_meld')
            if( !this.checkAction( 'initial_meld' ) ){
                console.log('cheat_initial_meld')
                return;
            }
            var card_id = this.stock.hand[this.my_id].getSelectedItems()[0].id;
            this.ajaxcall( "/innovation/innovation/initial_meld.html",
                            {
                                lock: true,
                                player_id: this.my_id,
                                card_id: card_id
                            },
                             this, function(result){}, function(is_error){}
                         );
            this.off(this.stock.hand[this.my_id]); //////////////////////// <- Here
            this.stock.hand[this.my_id].setSelectionMode(0);
        },
        
        action_clicForMeld : function(control_name) {
            console.log('meld')
            if( !this.checkAction( 'meld' ) ){
                console.log('cheat_meld')
                return;
            }
            
            var card_id = this.stock.hand[this.my_id].getSelectedItems()[0].id;
            this.ajaxcall( "/innovation/innovation/meld.html",
                            {
                                lock: true,
                                player_id: this.my_id,
                                card_id: card_id
                            },
                             this, function(result){}, function(is_error){}
                         );
            this.off(this.stock.hand[this.my_id]); //////////////////////// <- And here
            this.stock.hand[this.my_id].setSelectionMode(0);
        },
Still OK for turn0 state, but for playerTurn state I get this message when the event is triggered:
Javascript error:
During callback: onclick / onClickOnItem
_26c.advice is null
This error seems to be raised in the intern mechanism of 'onChangeSelection' on the stock component. But appart from that, the action is still resolved correctly.

What can I do to eliminate these error messages ?
Do you have a better way to manage event disconnection ?

Thanks :) !

Tchebychev
Last edited by Woodruff on 17 July 2016, 10:59, edited 1 time in total.
User avatar
Victoria_La
Posts: 665
Joined: 28 December 2015, 20:55

Re: Events accumulation on stock

Post by Victoria_La »

1) They do have connect/disconnect. You are right you need to disconnect or it will accumulate. The other option connect in setup and never disconnect, just ignore when in wrong state.
To use connect/disconnect from parent class (example)

Code: Select all

onEnteringState...
                   
 this.connect($('guard_slot'), 'onclick', 'onCityWatch');

onLeavingState...
                    
 this.disconnect($('guard_slot'), 'onclick');


2) I suggest not to do anything after ajaxcall, since you may have conflict with events triggered by the call. Better to put you code either in onLeavingState functions or both in
ajax callbacks

3) If you using dojo directly ajaxcall error handler has two arguments,
iserr:boolean and err:message so handler looks like

Code: Select all

                    var self = this;
                    err = function(iserr, message) {
                        if (iserr) {
                            console.log('on error '+message);
                        }
                    };
// now pass this "err" as error handler
User avatar
Woodruff
Posts: 423
Joined: 08 March 2014, 00:53

Re: Events accumulation on stock

Post by Woodruff »

Hi Victoria_la :)

Thanks for your answer. I'm going for solution 1, connecting/disconnecting onEnteringState/onLeavingState because it seems cleaner for me.

What do you mean by 'from parent class'? Your $ select an id, not a class?
On the base of what I understand, I tried to things:
-Connect from the parent div, that is the container of the stock:

Code: Select all

this.connect($('hand_' + this.my_id), 'onclick', this, 'action_clicForInitialMeld' )
That does not work because this expect a click on the div outside the cards.

-Connect using a CSS selector that match directly the cards in the stock:

Code: Select all

this.connect(dojo.query('#hand_' + this.my_id + ' > *'), 'onclick', this, 'action_clicForInitialMeld' )
That does nothing, when clicking on a card, nothing happens. The selector itself is right (tested on Firebug), so I bet I can't just replace the $ by dojo.query and this more complex selection.

Any luck?
User avatar
Victoria_La
Posts: 665
Joined: 28 December 2015, 20:55

Re: Events accumulation on stock

Post by Victoria_La »

Parent connect is one defined in parent from which your class inheriting (part of framework).
It has 3 arguments not 4. You don't pass 'this'. See my example.
User avatar
Woodruff
Posts: 423
Joined: 08 March 2014, 00:53

Re: Events accumulation on stock

Post by Woodruff »

OK thanks. I missed that the context argument this should not be provided. So I try this:

Code: Select all

this.connect(dojo.query('#hand_' + this.my_id + ' > *'), 'onclick', 'action_clicForMeld' )
Still does not work...
Anything I could do to pass my node without using this $ (I cannot access the id without getting dirty :twisted:)?
User avatar
Victoria_La
Posts: 665
Joined: 28 December 2015, 20:55

Re: Events accumulation on stock

Post by Victoria_La »

I don't understand what you mean by dirting it.
The first argument is a single object (or maybe id).
You cannot pass list into that. And you still passing an extra argument which won't work.
If you have to appy it to multiple object you can assign result of dojo query to array, then iterate over it and pass elements one by one to connect.

Code: Select all


var self = this;
dojo.query('#hand_' + this.my_id + ' > *').forEach(
   function(node, index, arr) {
      self.connect(node, 'onclick', 'action_clicForInitialMeld' );
   }
);
User avatar
Woodruff
Posts: 423
Joined: 08 March 2014, 00:53

Re: Events accumulation on stock

Post by Woodruff »

OK !
I meant by getting dirty that I should have done complicated things to get the id of the objects I wanted to handle. But as you say, the problem is not there.
I was got wrong by my JQuery experience ;)

All is OK now, thanks very much for your help :)
You helped me to gets things much clearer about this connexion mechanism.
Post Reply

Return to “Developers”