Gettler‘s Screep World 笔记 Ⅰ

夏促时候刚刚入坑,写个笔记叭~

环境配置

参考 HoPGoldy 大佬的简书,先配置下开发环境

萌新去看大佬的详细教程,我这里比较简单,有前端基础的可以直接抄

VSCode 跳过

node 我配的是v18.18.2

换源

shell 复制代码
npm config set registry https://registry.npmmirror.com

安装依赖

shell 复制代码
npm install @types/screeps @types/lodash@3.10.1 # 代码提示
npm install -D rollup # 代码构建工具
npm install rollup-plugin-clear rollup-plugin-screeps rollup-plugin-copy -D # 代码上传工具
npm install source-map@0.6.1 # 异常信息映射
npm install -D @rollup/plugin-node-resolve @rollup/plugin-commonjs # 模块打包工具
# 下面的ts配不配就看心情了,建议配一下
npm install --save-dev typescript rollup-plugin-typescript2 # ts编译

根目录下创建代码构建工具的配置文件 rollup.config.js

js 复制代码
import clear from 'rollup-plugin-clear'
import screeps from 'rollup-plugin-screeps'
import copy from 'rollup-plugin-copy'
import resolve from '@rollup/plugin-node-resolve'
import commonjs from '@rollup/plugin-commonjs'

let config
// 根据指定的目标获取对应的配置项
if (!process.env.DEST) {
  console.log("未指定目标, 代码将被编译但不会上传")
} else if (!(config = require("./.secret.json")[process.env.DEST])) {
  throw new Error("无效目标,请检查 secret.json 中是否包含对应配置")
}

// 根据指定的配置决定是上传还是复制到文件夹
const pluginDeploy = config && config.copyPath ? // 复制到指定路径
                     copy({
                            targets: [{
                              src: 'dist/main.js', dest: config.copyPath
                            }, {
                              src: 'dist/main.js.map',
                              dest: config.copyPath,
                              rename: name => name + '.map.js',
                              transform: contents => `module.exports = ${contents.toString()};`
                            }], hook: 'writeBundle', verbose: true
                          }) : // 更新 .map 到 .map.js 并上传
                     screeps({config, dryRun: !config})

export default {
  input: 'src/main.js', output: {
    file: 'dist/main.js', format: 'cjs', sourcemap: true
  }, plugins: [// 清除上次编译成果
    clear({targets: ["dist"]}), // 执行上传或者复制
    // 打包依赖
    resolve(),
    // 模块化依赖
    commonjs(),
    pluginDeploy]
};

package.json 配置

json 复制代码
{
  "name": "sc",
  "version": "1.0.0",
  "description": "",
  "main": "rollup.config.js",
  "scripts": {
    "start": "rollup -cw --environment DEST:main",
    "local": "rollup -cw --environment DEST:local",
    "build": "rollup -cw"
  },
  "repository": {
    "type": "git",
    "url": "http://xxxxxxxx:xxxx/Gettler/screeps.git"
  },
  "keywords": [],
  "author": "Gettler",
  "license": "ISC",
  "devDependencies": {
    "@rollup/plugin-commonjs": "^14.0.0",
    "@rollup/plugin-node-resolve": "^8.4.0",
    "@types/lodash": "^3.10.1",
    "@types/node": "^14.0.24",
    "@types/screeps": "^3.3.8",
    "rollup": "^2.22.1",
    "rollup-plugin-clear": "^2.0.7",
    "rollup-plugin-copy": "^3.3.0",
    "rollup-plugin-screeps": "^1.0.1",
    "rollup-plugin-typescript2": "^0.27.1",
    "typescript": "^3.9.7"
  },
  "dependencies": {
    "source-map": "^0.6.1"
  }
}

项目根目录下配置 .secret.json 用于发布代码到游戏,token地址:https://screeps.com/a/#!/account/auth-tokens

json 复制代码
{
  "main": {
    "token": "你的token",
    "protocol": "https",
    "hostname": "screeps.com",
    "port": 443,
    "path": "/",
    "branch": "default"
  },
  "local": {
    "copyPath": "本地路径,如:C:\\Users\\Gettler\\AppData\\Local\\Screeps\\scripts\\screeps.com\\default"
  }
}

main.js

js 复制代码
import {errorMapper} from "./modules/errorMapper";

module.exports.loop = errorMapper(() => {
		// 代码在这里写即可
		console.log("Power!!!")
	}
)

errorMapper.js

js 复制代码
/**
 * 校正异常的堆栈信息
 *
 * 由于 rollup 会打包所有代码到一个文件,所以异常的调用栈定位和源码的位置是不同的
 * 本模块就是用来将异常的调用栈映射至源代码位置
 *
 * @see https://github.com/screepers/screeps-typescript-starter/blob/master/src/utils/ErrorMapper.ts
 */

import {SourceMapConsumer} from 'source-map'

// 缓存 SourceMap
let consumer = null

// 第一次报错时创建 sourceMap
const getConsumer = function () {
  if (consumer == null) consumer = new SourceMapConsumer(require("main.js.map"))
  return consumer
}

// 缓存映射关系以提高性能
const cache = {}

/**
 * 使用源映射生成堆栈跟踪,并生成原始标志位
 * 警告 - global 重置之后的首次调用会产生很高的 cpu 消耗 (> 30 CPU)
 * 之后的每次调用会产生较低的 cpu 消耗 (~ 0.1 CPU / 次)
 *
 * @param {Error | string} error 错误或原始追踪栈
 * @returns {string} 映射之后的源代码追踪栈
 */
const sourceMappedStackTrace = function (error) {
  const stack = error instanceof Error ? error.stack : error
  // 有缓存直接用
  if (cache.hasOwnProperty(stack)) return cache[stack]

  const re = /^\s+at\s+(.+?\s+)?\(?([0-z._\-\\\/]+):(\d+):(\d+)\)?$/gm
  let match
  let outStack = error.toString()
  console.log("ErrorMapper -> sourceMappedStackTrace -> outStack", outStack)

  while ((match = re.exec(stack))) {
    // 解析完成
    if (match[2] !== "main") break

    // 获取追踪定位
    const pos = getConsumer().originalPositionFor({
                                                    column: parseInt(match[4], 10),
                                                    line: parseInt(match[3], 10)
                                                  })

    // 无法定位
    if (!pos.line) break

    // 解析追踪栈
    if (pos.name) outStack += `\n    at ${pos.name} (${pos.source}:${pos.line}:${pos.column})`
    else {
      // 源文件没找到对应文件名,采用原始追踪名
      if (match[1]) outStack += `\n    at ${match[1]} (${pos.source}:${pos.line}:${pos.column})`
      // 源文件没找到对应文件名并且原始追踪栈里也没有,直接省略
      else outStack += `\n    at ${pos.source}:${pos.line}:${pos.column}`
    }
  }

  cache[stack] = outStack
  return outStack
}

/**
 * 错误追踪包装器
 * 用于把报错信息通过 source-map 解析成源代码的错误位置
 * 和原本 wrapLoop 的区别是,wrapLoop 会返回一个新函数,而这个会直接执行
 *
 * @param next 玩家代码
 */
export const errorMapper = function (next) {
  return () => {
    try {
      // 执行玩家代码
      next()
    } catch (e) {
      if (e instanceof Error) {
        // 渲染报错调用栈,沙盒模式用不了这个
        const errorMessage = Game.rooms.sim ?
                             `沙盒模式无法使用 source-map - 显示原始追踪栈<br>${_.escape(e.stack)}` :
                             `${_.escape(sourceMappedStackTrace(e))}`

        console.log(`<text style="color:#ef9a9a">${errorMessage}</text>`)
      }
      // 处理不了,直接抛出
      else throw e
    }
  }
}

tsconfig.json

json 复制代码
{
  "compilerOptions": {
    "target": "es2017",
    "moduleResolution": "Node",
    "outDir": "dist/",
    "baseUrl": "./",
    "sourceMap": true,
    "allowSyntheticDefaultImports": true,
    "paths": {
      "@/*": [
        "./src/*"
      ]
    }
  },
  "exclude": [
    "node_modules"
  ],
  "include": [
    "src/**/*.ts"
  ]
}

至此,环境配置完成(如有问题欢迎评论区指正)

我的项目结构(已经写了一部分代码了)

入门

新手先把官方教程的代码跑起来,在这个基础上优化,前期官方教程的代码也还够用,一定要看懂教程代码再来往下看

对照着

挖采分离

这个是我第一个想要实现的,因为我的矿可以让三个爬爬一起采,如果三个以上就会有一个爬爬闲着,等到有爬爬才玩矿运回去的时候才能有空间采矿,如果多个一起运回去好像又会损失空间,嗯。。。很浪费

实现挖采分离,就可以有三个爬爬一直挖矿,然后挖完矿扔到脚下,让别的爬爬来捡回去

思路:修改教程harvester代码,去掉运送能量到建筑的代码,去掉carry部件,编写mover

mover 的代码

js 复制代码
if (creep.memory.role === 'mover') {
  if ((creep.memory.moving !== undefined && creep.memory.moving === true) || creep.store.getFreeCapacity() === 0 || (sources.length === 0 && creep.store.getUsedCapacity() > 0)) {
    creep.say("I am moving!")
    creep.memory.moving = true
    var targets = creep.room.find(FIND_STRUCTURES, { //找出需要补充能量的建筑
      filter: (structure) => {
        return (structure.structureType === STRUCTURE_EXTENSION || structure.structureType === STRUCTURE_SPAWN || structure.structureType === STRUCTURE_EXTENSION ||  structure.structureType === STRUCTURE_TOWER) && structure.store.getFreeCapacity(RESOURCE_ENERGY) > 0;
      }
    });
    for (var tmp in Game.creeps) {
      var tmpCreep = Game.creeps[tmp];
      if (tmpCreep.memory.role === 'upgrader' && tmpCreep.store.getFreeCapacity() > 0) {
        targets.push(tmpCreep)
      } else if (tmpCreep.memory.role === 'builder' && tmpCreep.memory.building === true) {
        targets.push(tmpCreep)
      }
    }
    if (targets.length > 0) { // 需要维护的建筑数目 > 0
      var res = creep.transfer(targets[creep.memory.idx % targets.length], RESOURCE_ENERGY)
      if (res === ERR_NOT_IN_RANGE) {
        creep.moveTo(targets[creep.memory.idx % targets.length], {visualizePathStyle: {stroke: '#ffffff'}});
      } else if (res === OK) {

      }
    }
    if (creep.store.getUsedCapacity() === 0) {
      creep.memory.moving = false
    }

  } else if (creep.store.getFreeCapacity() > 0) {
    creep.say("I am carrying!")
    creep.memory.moving = false
    let res = creep.pickup(sources[creep.memory.idx % sources.length])
    if (res === ERR_NOT_IN_RANGE) {
      creep.moveTo(sources[creep.memory.idx % sources.length], {visualizePathStyle: {stroke: '#ffaa00'}});
    } else {
    }
  }
}
相关推荐
冷眼看人间恩怨2 小时前
【Qt笔记】QDockWidget控件详解
c++·笔记·qt·qdockwidget
Hejjon8 小时前
SpringBoot 整合 SQLite 数据库
笔记
西洼工作室10 小时前
【java 正则表达式 笔记】
java·笔记·正则表达式
初学者7.11 小时前
Webpack学习笔记(2)
笔记·学习·webpack
新手上路狂踩坑12 小时前
Android Studio的笔记--BusyBox相关
android·linux·笔记·android studio·busybox
stm 学习ing13 小时前
HDLBits训练3
c语言·经验分享·笔记·算法·fpga·eda·verilog hdl
尘觉13 小时前
算法的学习笔记—扑克牌顺子(牛客JZ61)
数据结构·笔记·学习·算法
bohu8314 小时前
sentinel学习笔记1-为什么需要服务降级
笔记·学习·sentinel·滑动窗口
初学者7.15 小时前
Webpack学习笔记(3)
笔记·学习·webpack
bohu8316 小时前
sentinel学习笔记5-资源指标数据统计
笔记·sentinel·statisticslot