0

I am using Node.js and steam-node to write a couple of bots for steam (stored on an Array), each bot has their own account and stuff. So, to begin, here's a part of my code:

function onLogon(index){
    console.log('[STEAM] Logged in on bot ' + index);
    bots[index].setPersonaState(Steam.EPersonaState.Online);
    /*do other stuff*/
}

for (var i = 0; i < bots.length; i++){ /*Foreach of the bots, assign a loggedOn even listener */
    bots[i].on('loggedOn', onLogon(i));
}

And this code is giving me a 'listener must be a function'. Now, i know what this error means, i should set the event listener like this:

bots[i].on('loggedOn', onLogon);

but that doesnt work, because i need to pass a variable to the event.

I could do this:

for (var i = 0; i < accounts.length; i++){
    bots[i].on('loggedOn', function() {
        console.log('[STEAM] Logged in on bot ' + i);
        bots[i].setPersonaState(Steam.EPersonaState.Online);
        //...
    });
}

but it also doesnt work because i is passed by reference and it throws a TypeError: Cannot read property 'setPersonaState' of undefined that way.

bots[i].on('loggedOn', (function(index) {
        console.log('[STEAM] Logged in on bot ' + i);
        bots[index].setPersonaState(Steam.EPersonaState.Online);
        //...
    })(i));

And this ALSO doesn't work...

Is there ANY way to do what I want here? Or should I just dont use arrays?

Mark
  • 35
  • 4

2 Answers2

1

@Aaron's answer is probably the way to go, but as alternative, an enclosure might work.

function onLogon(bot, index){
    return function() {
        console.log('[STEAM] Logged in on bot ' + index);
        bot.setPersonaState(Steam.EPersonaState.Online);
        /*do other stuff*/
    };
}

for (var i = 0; i < bots.length; i++){ /*Foreach of the bots, assign a loggedOn even listener */
    bots[i].on('loggedOn', onLogon(bots[i], i));
}

Or to build on @Aaron's answer, pass the bot as the function context.

function onLogon(index){
    console.log('[STEAM] Logged in on bot ' + index);
    this.setPersonaState(Steam.EPersonaState.Online);
    /*do other stuff*/
}

for (var i = 0; i < bots.length; i++){ /*Foreach of the bots, assign a loggedOn even listener */
    bots[i].on('loggedOn', onLogon.bind(bots[i], i));
}
kim3er
  • 6,306
  • 4
  • 41
  • 69
0

When you run

bots[i].on('loggedOn', onLogon(i));

you are immediately calling onLogon, and passing the result to on. What you really want is to bind the first argument without calling it, which can be done as follows:

bots[i].on('loggedOn', onLogon.bind(null, i));

The null is because the first argument to bind is the context (or this value), which we don't care about.

Aaron Dufour
  • 17,288
  • 1
  • 47
  • 69