compass-3072376_1920

Source Maps in Screeps

Source Maps are great, they let you map your compiled (even minified) code to the original lines in the source files.

Part of the new typescript starter is a system for parsing and utilising these source maps in Screeps.

Creating the Map

Screeps can’t read .map files as such you need to modify the file and its file type. rollup-plugin-screeps does this for you (here). Basically, you need to take the source map and wrap turn it into an exported JSON string.

moudle.exports = “SOURCE_MAP”;

Save that as map.js in your screeps code folder so that it gets uploaded to Screeps.

Using the Source Map

apemanzilla wrote a class for the Typescript Starter that can utilise the source map and produce stack traces.

I run a modified version that slots into my OS as a process.

First off, I load the source map consumer into the global scope when the file is required. Depending on the size of your codebase this can cause quite a large spike in CPU usage. You need the source-map package installed which you can get from npm. You will need to use a bundler like webpack or rollup to bundle source-map in your package.

When an error is thrown it is passed to this process and it translates it back to the original positions.

You need to wrap your code in a try/catch block so that you can handle the error yourself. I’ve added a plain javascript version of the function below where error is the caught error.

// Where `error` is the error caught by yout try/catch block
const stack = error instanceof Error ? error.stack : error;
const re = /^\s+at\s+(.+?\s+)?\(?([0-z._\-\\\/]+):(\d+):(\d+)\)?$/gm
let match: RegExpExecArray | null
let outStack = error.toString()
while(match = re.exec(stack)){
if(match[2] === 'main'){
const pos = consumer.originalPositionFor({
line: parseInt(match[3], 10),
column: parseInt(match[4], 10)
})
if(pos.line != null){
if (pos.name) {
outStack += `\n at ${pos.name} (${pos.source}:${pos.line}:${pos.column})`
} else {
if (match[1]) {
// no original source file name known – use file name from given trace
outStack += `\n at ${match[1]} (${pos.source}:${pos.line}:${pos.column})`
} else {
// no original source file name known or in given trace – omit name
outStack += `\n at ${pos.source}:${pos.line}:${pos.column}`
}
}
} else {
// no known position
break;
}
} else {
// no more parseable lines
break;
}
}
console.log(outStack)

view raw
sourceMap.js
hosted with ❤ by GitHub

This has made my debugging a lot easier.

Catching the errors

Catching errors in your screeps AI is something that everyone should be doing. The Typescript starter recommends wrapping your whole loop function in a try/catch block which works but is a little broad. You will catch the error but your AI will halt at the error and nothing else will get processed.

I wrap my call to each process in my OS in a try/catch block allowing 1 process to fail without killing the whole AI. If you looped through each creep for actions you could try/catch each creeps code so that 1 creep can fail without killing the others.

Share this post

Share on facebook
Share on google
Share on twitter
Share on linkedin
Share on pinterest
Share on print
Share on email