Error message since introduction of new architecture



  • I have the following setup in my Creep prototype definition:

    _.assign(Creep.prototype,{
        /* ... */,
        getAttackType : getAttackType,
        meleeAttack : Creep.prototype.attack,
        attack : attack_new,
        /* ... */
    }
    

    which basically maps the old attack to a new name meleeAttack and overwrites the existing name with a new attack method like seen below.

    function attack_new(target){
        var attack = this.getAttackType();
        if (attack){
            return this[attack](target);
        } else {
            l.warn(this.name + "cannot attack - no suitable attack type found", l.info(this));
            return ERR_NO_BODYPART;
        }
    }
    

    This has been working like a charm for several months now. However, since the change to the architecture was introduced, I get a stack overflow error instead - however not in 100% of the time!

    RangeError: Maximum call stack size exceeded
        at data (/opt/engine/dist/game/creeps.js:20:23)
        at Creep.Object.defineProperty.get (/opt/engine/dist/game/creeps.js:53:28)
        at Creep.getAttackType (Prototype_Creep:360:26)
        at Creep.attack_new [as meleeAttack] (Prototype_Creep:369:23)
        at Creep.attack_new [as meleeAttack] (Prototype_Creep:371:28)
        at Creep.attack_new [as meleeAttack] (Prototype_Creep:371:28)
        ...
    

    Basically, attack_new instead of the "old" attack method is now mapped to meleeAttack which causes the infinite loop. My guess is, that the occasional times it's working are the ticks when the global object is newly built, and the ticks afterwards it fails?



  • The only scenario I have in my head, where this could happen is when the global object is preserved for several ticks, but the code actually is executed more then once.
    In that case, in the first tick after the initialization of the global object, the original attack method has been mapped to meleeAttack and after that, attack_new is correctly mapped to attack. In this tick, everything runs fine.
    On the next tick however, attack ( which now effectively is attack_new) is again mapped to meleeAttack, overwriting the original attack method, and thus creating an infinite loop until the global object is reset.



  • I experienced the same issues. Looks like the global object is indeed preserved, but not every tick. You may try to add some checks if you prototype is already extended, and please tell if it works.

    Like that:

    if(!Creep.prototype.meleeAttack) {
        _.assign(Creep.prototype,{
            /* ... */,
            getAttackType : getAttackType,
            meleeAttack : Creep.prototype.attack,
            attack : attack_new,
            /* ... */
        }
    }
    


  • @Rumatah this surely works, but it is not fixing the initial problem...