Class instance in creep memory forgets his members



  • As a test, I created the following code:

    if (!MyClass) {
        console.log('define class');
        var MyClass = class {
            run() {
                console.log('AHAH');
            }
        }
    }
    
    module.exports.loop = function () {
        console.log('tick');
        let spawn = Game.spawns['Spawn1'];
        
        if(!spawn.spawning) {
            console.log('spawn');
            spawn.spawnCreep([MOVE], 'myCreep', { memory: { myObj: new MyClass() } });
        }
        
        for (let creep in Game.creeps) {
            console.log(creep, JSON.stringify(Game.creeps[creep].memory));
            Game.creeps[creep].memory.myObj.run();
        }
    }
    

    This is the output:

    [00:44:03]define class
    [00:44:03]tick
    [00:44:03]spawn
    [00:44:03]myCreep {"myObj":{}}
    [00:44:03]AHAH
    [00:44:04]tick
    [00:44:04]myCreep {"myObj":{}}
    [00:44:04]TypeError: Game.creeps[creep].memory.myObj.run is not a function
        at Object.module.exports.loop:25:41
        at __mainLoop:1:19079
        at eval:2:4
        at Object.r.run:2:143185
    [00:44:05]tick
    [00:44:05]myCreep {"myObj":{}}
    [00:44:06]TypeError: Game.creeps[creep].memory.myObj.run is not a function
        at Object.module.exports.loop:25:41
        at __mainLoop:1:19079
        at eval:2:4
        at Object.r.run:2:143185
    [00:44:15]define class
    [00:44:15]tick
    [00:44:15]spawn
    [00:44:15]myCreep {"myObj":{}}
    [00:44:15]TypeError: Game.creeps[creep].memory.myObj.run is not a function
        at Object.module.exports.loop:25:41
        at __mainLoop:1:19079
        at eval:2:4
        at Object.r.run:2:143185
    [00:44:30]define class
    [00:44:30]tick
    [00:44:30]spawn
    [00:44:30]myCreep {"myObj":{}}
    [00:44:30]TypeError: Game.creeps[creep].memory.myObj.run is not a function
        at Object.module.exports.loop:25:41
        at __mainLoop:1:19079
        at eval:2:4
        at Object.r.run:2:143185
    [00:44:32]define class
    [00:44:32]tick
    [00:44:32]spawn
    [00:44:32]myCreep {"myObj":{}}
    [00:44:32]TypeError: Game.creeps[creep].memory.myObj.run is not a function
        at Object.module.exports.loop:25:41
        at __mainLoop:1:19079
        at eval:2:4
        at Object.r.run:2:143185
    [00:44:33]tick
    [00:44:33]spawn
    [00:44:33]myCreep {"myObj":{}}
    [00:44:33]TypeError: Game.creeps[creep].memory.myObj.run is not a function
        at Object.module.exports.loop:25:41
        at __mainLoop:1:19079
        at eval:2:4
        at Object.r.run:2:143185
    [00:44:42]define class
    [00:44:42]tick
    [00:44:42]spawn
    [00:44:42]myCreep {"myObj":{}}
    [00:44:42]TypeError: Game.creeps[creep].memory.myObj.run is not a function
        at Object.module.exports.loop:25:41
        at __mainLoop:1:19079
        at eval:2:4
        at Object.r.run:2:143185
    [00:44:50]tick
    [00:44:50]spawn
    [00:44:50]myCreep {"myObj":{}}
    [00:44:50]TypeError: Game.creeps[creep].memory.myObj.run is not a function
        at Object.module.exports.loop:25:41
        at __mainLoop:1:19079
        at eval:2:4
        at Object.r.run:2:143185
    [00:44:51]tick
    [00:44:51]spawn
    [00:44:51]myCreep {"myObj":{}}
    [00:44:51]TypeError: Game.creeps[creep].memory.myObj.run is not a function
        at Object.module.exports.loop:25:41
        at __mainLoop:1:19079
        at eval:2:4
        at Object.r.run:2:143185
    

    I have several questions about the behaviour of this code.

    The first is that it seems that the object myObj forgets all his members the next tick after it started spawning. Why is that? Does this has something to do with the lifetime of the MyClass class object or something (I'm a JS newbie)? How do I deal with this? Storing classes themselves in memory?

    Secondly, and this question propably ties in with the first, why is MyClass defined just sometimes? Why not either just once or always?



  • So much wrong with this, but I understand why you think it could work.

    First, Screeps is not a system where your code is running all the time. It runs in slices, but unlike a Linux program with a select loop, your access to resources is not guaranteed in the time between slices.

    As such, you cannot attempt to insert a realized class into an object you place in a creep's memory. You can "do it"? But it will be a data only version... as such, you most certainly cannot execute something like:

    Game.creeps[creep].memory.myObj.run(); out of a creep's memory. Oh dear gosh no. Only pure data can go in memory in this context, certainly not functions.



  • Each tick, a creep's memory is serialised to JSON, stored in the server's database, and then at the start of the next tick it is loaded back from the database and an object is created.

    I'm not sure what the technical term is, but JSON can only serialise "basic objects". So while it can serialise basic data members (number, string, array, object) it can't serialise functions. This is why you get the error "myObj.run" is not a function.

    Another example, if you store a RoomPosition object in memory, what you get back the following tick is an object with a "roomName", "x", and "y" members, but the object is not "instanceof RoomPosition".

    If you want to use a class with the creep's memory, you would have to assign the class to each creep every tick. Or find a different way of organising the creep's memory.



  • Thank you both for your answers. That really cleared things up!