What are folks doing to integrate some OOP design into their Screeps code?
Background: I'm an experienced systems programmer but I'm brand new to Javascript, and it's not immediately clear to me how to integrate JS classes efficiently with the existing Screeps classes. I've been playing around in the console a bit and it seems like we can't just write class MyCreep extends Creep { ... }
sadly, which is exactly what I want to do.
I've been thinking about this in the back of my mind for a few days and I think a good construct would be class MyCreep { constructor(creep_id) { ... } }
where all the properties are just setters/getters to/from the creep's memory
, then wherever I deal with MyCreep
objects if I want to invoke a true Creep
method (moveTo
, etc...) I'll just have to go through a special method/property like MyCreep.creep
which would return the true Creep
. Kind of like this:
class MyCreep {
creep;
constructor(creep_id) { this.creep = Game.getObjectById(creep_id); }
get memory() { return this.creep.memory; }
get target() { return Game.getObjectById(this.memory.target_id); }
set target(target_object) { this.memory.target_id = target_object.id; }
myMoveTo(target_object) {
this.target = target_object;
// other state adjustments...
}
Then I could use them like this:
var john = new MyCreep(Game.creeps['John Galt'].id);
john.myMoveTo(john.creep.room.controller);
My biggest concern with this method is that MyCreep
objects require the apparently superfluous creep
member, and I have to actually allocate them with new
- I would have to resort to _.forEach(Game.creeps, (creep) => {new MyCreep(creep.id)})
each tick. The systems side of me is triggered by the dynamic allocations incurred by the calls to new MyCreep()
. At a high level there is no real extra state I need to capture that isn't already in the Creep
object itself to which I already have a reference. I find myself inclined to find a way to run MyCreep
methods directly on true Creep
objects, where this
can refer to the Creep
itself. I'd want to use something like in the following pseudocode in-place of new
:
new_MyCreep(creep_id) {
var creep = Game.getObjectById(creep_id);
return (MyCreep) creep; // indicates my desire for a "conversion" from Creep to MyCreep
}
In my naiivete, I see this as avoiding the extra allocation of a dedicated MyCreep
object, which now can just operate directly on the API-allocated Creep
object. I would then like to use _.forEach(Game.creeps, new_MyCreep)
(instead of new MyCreep()
) and then use instances of MyCreep
to invoke true Creep
methods as well as MyCreep
methods, like:
var john = new_MyCreep(Game.creeps['John Galt'].id);
john.myMoveTo(john.room.controller);
I've seen various people mess with .prototype
but I am unable refer to Creep.prototype
in the Screeps console and creep_instance.prototype
is undefined
, so I've given up on pursuing that lead.
I'm not well-versed enough in JS to know how dumb this all sounds, so please share your thoughts. Is my first method fine, and I'm just overestimating how expensive the extra new
calls are? Is the second method even possible? What do you do?
Cheers!
Fritz