What's wrong with reference storage.



  • Browser version.

    The following code:


    Memory.spa=Game.spawns.Spawn1
    module.exports.loop = function () {
    console.log(Memory.spa.name)
    console.log(Memory.spa.createCreep)
    }

    Genetates this output

    [8:26:37 PM]Spawn1
    [8:26:37 PM]undefined
    [8:26:38 PM]Spawn1
    [8:26:38 PM]undefined
    [8:26:39 PM]Spawn1
    [8:26:39 PM]function (b,c,e){var f=this;p.isObject(c)&&p.isUndefined(e)&&(e=c,c=void 0);var g=this.canCreateCreep(b,c);return g!=o.OK?g:(c||(c=a("./names").getUniqueName(function(a){return p.any(h.roomObjects,{type:"creep",user:d(f.id).user,name:a})||-1!=l.indexOf(a)})),l.push(c),p.isUndefined(k.Memory.creeps)&&(k.Memory.creeps={}),p.isObject(k.Memory.creeps)&&(p.isUndefined(e)?k.Memory.creeps[c]=k.Memory.creeps[c]||{}:k.Memory.creeps[c]=e),i.set(this.id,"createCreep",{name:c,body:b}),c)}
    [8:26:40 PM]Spawn1
    [8:26:40 PM]undefined

     

    Most of the time, class information about the object is lost.

    Can the script engine store references to functions and objects or not?

    (Also, this forum reacts strangely to ctrl+v)



  • You can't store objects' references into Memory, the result is "undefined behavior". The correct way is to store id's of objects and then use

    let obj = Game.getObjectById(Memory.someID); obj.doSmth(...);

    to get real object's reference at current tick. More information: http://support.screeps.com/hc/en-us/articles/203016642-Working-with-Memory



  • can't store objects' references into Memory, the result is "undefined behavior"

    Well, yes, that's what I reported as a bug.

    In certain other languages (can't say about other js execution environments) such reference juggling is a natural thing to do and helps performance.

    Maybe this limitation should be highlighted somewhere in tutorial. On that documentation page it slips by in the load of obvious or alternatively highly special technicalities.



  • In those other languages / js environments, you are likely not working with a sandbox that is destroyed and rebuilt every tick. What you need to understand is that the Game object and all it's children you are working with aren't live objects, but a static image of the game world in your current tick, an interface to the real, live game world.

    These game objects you are referencing are, simplified spoken, destroyed each tick after the actions you queued up in that tick are executed by the server, and then new game objects are created to reflect the new state of the game. Thus, referencing can't really work in the way you are expecting it to work. For the same reason, we can't really work with callbacks or promises either. it's sad, but that's how it is.



  • It's also worthwhile to note that the system uses a global reset flag. On some ticks, your entire environment is re-done and ALL your code is executed. On other ticks most of your code is cached and only the exports are executed.

    What that means is that, in your example, the top line is only executed on ticks where the global cache was reset (which will happen whenever you update your code, but also on other ticks... perhaps when anyone updates their code). When the top line executes your code temporarily has a live object in the Memory... for one tick. But Memory then serializes, and on the next tick you get a deserialized version of the object. Functions cannot be serialized, and so become undefined. Properties might appear, but they are snapshots of the property as it looked perhaps dozens of ticks ago rather than a live copy of the current object.

    The behavior is very clearly defined, and not a bug, nor is it inconsistent. A better way to phrase it is 'obscure' because if you don't realize what Memory is for and how it functions, and you don't understand that sometimes all your code is processed and sometimes only part of your code, then the behavior seems random.



  • "perhaps when anyone updates their code"

    I never thought of that... that'd explain so much though...