最近,我变得无可救药地迷上了Screeps,并且我重构了一些代码以实现基于任务的实现。任务是诸如“步行然后收获直到满负荷工作”之类的事情,并且基于以ES6样式类编写的单个基本任务模板为基础。可以通过包装器(tasks.js)向蠕变分配任务,该包装器加载相关任务文件并返回新的任务实例。

今天,我遇到了一个奇怪的错误,使我觉得我不完全了解Javascript的继承模型。下面是相关代码:

Task.js :(基本任务类)

class Task {
    constructor(taskName) {
        // Parameters for the task
        this.name = taskName; // name of task
        this.quiet = false; // suppress console logging if true
        this.creep = [creep assigned to this task]
        this.target = [thing task operates on, e.g. "repair this wall"]
        ...
    }
    ...
    // Execute this task each tick. Returns nothing unless work is done.
    step() {
        ...
        if (creep.pos.inRangeTo(target, this.targetRange)) {
            var workResult = this.work();
            console.log(this.quiet) // < returns false, should be true?
            if (workResult != OK && this.quiet == false) {
                creep.log("Error: " + workResult); // < is printed when run
            }
            return workResult;
        } [else move to target]
    }
    ...
    // Task to perform when at the target
    work() {
        // overwrite this in child class
    }
}

module.exports = Task;


task_harvest.js :(收获任务)

var Task = require('Task');

class taskHarvest extends Task {
    constructor() {
        super('harvest');
        // no mention of this.quiet here
    }
    ...
    work() {
        console.log("harvest:" + this.quiet);
        return this.creep.harvest(this.target);
    }
}
module.exports = taskHarvest;


task.js :(包装器通过函数调用生成新的任务实例)

module.exports = function (taskName) {
    var TaskClass = require('task_' + taskName); // all tasks follow this naming pattern
    var taskInstance = new TaskClass;
    return taskInstance;
};


Harvester.js :(收割机蠕变的行为模型)

var tasks = require('tasks');
var roleHarvester = {
    ...
    harvest: function (creep) {
        var target = Game.getObjectById(creep.memory.assignment);
        var taskHarvest = tasks('harvest');
        taskHarvest.quiet = true;  // < this task shouldn't print anything
        creep.assign(taskHarvest, target); // assigns to creep.task
        return OK;
    },
    ...
    run: function (creep) { // executed every tick
        // execute the task
        creep.task.step();
    },
   ...
}


当我指定要从源中获取的蠕变时,我从task_harvest.js创建一个新任务,将其quiet属性设置为true,并将其及其目标绑定到该蠕变。一旦蠕变执行了任务,系统将指示其运行直到失效为止(上面未包含代码)。蠕变可以很好地执行任务,但仍将所有内容记录到控制台。

我认为在Harvester.js中,当我设置taskHarvest.quiet = true;时,从Task.js导入的行为会将this.quiet视为true。但是,似乎并非如此。在roleHarvester中,运行console.log(creep.task.quiet)返回true,但在Task中,当蠕变正在执行分配的任务时运行console.log(this.quiet)给出false

我可以将quiet作为可选参数添加到构造函数中,但这令人费解,我想知道为什么我在做什么不起作用。

最佳答案

没关系,实际上这不是继承问题;这是由游戏机制引起的问题:taskHarvest.quiet不会在每个滴答声中都被删除。 Screeps仅允许您将JSON可序列化的对象存储在内存中,因此我将任务设置存储在内存中,并在每次打勾时重新构造任务对象:

Object.defineProperty(Creep.prototype, 'task', {
    get: function () { // provide new task object recreated from literals stored in creep.memory.task
        if (this.memory.task != null) {
            var task = tasks(this.memory.task.name);
            task.creepName = this.memory.task.creepName;
            task.targetID = this.memory.task.targetID;
            task.data = this.memory.task.data; // < task.quiet is now task.data.quiet
            return task;
        } else {
            return null;
        }
    },
    set: function(newTask) {
        if (newTask != null) {
            this.log("use Creep.assign() to assign tasks. Creep.task = ___ should only be used to null a task.");
        } else {
            this.memory.task = newTask;
        }
    }
});


taskHarvest.quiet不会存储在内存中,因此它不会在任务的第一滴答声之后持续存在。现在,我将所有实例级可调参数存储在task.data对象中,因此task.quiet现在是task.data.quiet。这解决了问题。对不起,造成任何混乱!

09-08 08:08