Skip to content

Latest commit

 

History

History
322 lines (200 loc) · 15.3 KB

README.md

File metadata and controls

322 lines (200 loc) · 15.3 KB

screeps-typescript-starter v2.0

Starter kit for TypeScript-based Screeps AI codes.


screeps-typescript-starter is a starter kit for building Screeps AIs in TypeScript. It is based on the original starter kit by Marko Sulamägi, but with extra tools for easy compiling/deploying of scripts to the Screeps server, as well as a base framework for running tests.

Download the latest zipped copy here.

Table of Contents

Features

  • Automated deploy to public and private Screeps servers
  • Live reload compiling of typescript code
  • Highly configurable environment with sane defaults
  • Pre-configured linting rules customized for screeps
  • Typescript Screeps typings
  • Logger which links with source code and git repo (TODO: pending documentation)
  • Screeps profiler
  • "Snippets" directory for code you want to save, but don't want compiled or linted
  • Modest starter code to get you started, but not hold your hand

Quick Start

Requirements

  • Node.js (latest LTS is recommended)
  • Typings
  • Yarn - Optional. You can use npm if you don't want to, but this is for your own sanity.

For testing NOTE Testing is currently a work-in-progress:

  • Mocha test runner and NYC for code coverage - yarn global add nyc mocha

Download

To get started, download a zipped copy of the starter kit and extract it somewhere, or clone this repo.

Install all required modules!

Run the following the command to install the required packages and TypeScript declaration files if you are using yarn:

$ yarn

or, for npm:

$ npm install

Configure Screeps credentials

Create a copy of config/credentials.example.json and rename it to config/credentials.json.

WARNING: DO NOT commit this file into your repository!

# config/credentials.json
$ cp config/credentials.example.json config/credentials.json

In the newly created credentials.json file, change the email and password properties with your Screeps credentials. The serverPassword, token, and gzip options are only for private servers that support them. If you are uploading to the public Screeps server, you should delete these fields from your credentials file.

See Configuration for more in-depth info on configuration options.

Run the compiler

# To compile and upload your TypeScript files on the fly in "watch mode":
$ npm start

# To compile and deploy once:
$ npm run deploy

Configuration

This project is configured in two places. config/ is for deployment configuration, and contains your screeps login credentials along with other options. src/config/ contains a file you can use to configure your runtime Screeps code.

Runtime config

You can use the configuration variables in src/config by importing the file:

import * as Config from "../path/to/config";

... and simply calling the config variables with Config.CONFIG_VARIABLE in your code.

This file mostly serves as an example for making configurable code. We've included some built-in config variables that you might want to take a look at:

// You can enable/disable the Screeps Profiler here. This will reduce your CPU usage.
export const USE_PROFILER: boolean = true;

// Set these to false to remove sourcemaps from the output logs, which will also reduce CPU usage.
export const LOG_PRINT_LINES: boolean = true;
export const LOG_LOAD_SOURCE_MAP: boolean = true;

NOTE: You may want to consider adding this file to .gitignore if you end up storing confidential information there.

Deployment / Compiling configuration

The files under config/, as well as webpack.config.ts are where deployment configuration options are set.

It's helpful to remember that the config is just a javascript object, and can be passed around and modifide using webpack-chain.

Environment:

webpack.config.ts is for setting environment variables defaults throughout the rest of the config. You can use these variables to pass options to the rest of the config through the command line. For example:

# (npm requires arguments be seperated by a double dash)
$ npm run build -- --env.TEST=true

Will set the member TEST to true on the options object.

Remember, the config code is just a typescript function that return a config object, so you can hypothetically configure it wherever and however is most convenient.

Build toggles / deployment-dependent variables

Inside config.common.ts is where the majority of the webpack configuration happens.

Of particular interest is the Plugins section where DefinePlugin is configured (look for the line about half-way down statring with config.plugin("define")).

Variables set in the object here will be replaced in the actual output JS code. When compiling your code, webpack will perform a search and replace, replacing the variable names with the output of the supplied expression or value.

Because these values are evaluated once as a string (for the find-and-replace), and once as an expression, they either need to be wrapped in JSON.stringify or double quoted (ex. VARIABLE: '"value-in-double-quotes"').

Webpack can do a lot with these variables and dead code elimination.

Caveats: you need to let typescript know about these variables by declaring them in a type definitions (.d.ts) file. Also be careful not to use too common of a name, because it will replace it throughout your code without warning. A good standard is to make the variables all caps, and surrounded by double underscores, so they stand out (ex: __REVISION__).

Additional Options

config.common.ts is for config options common to all environments. Other environments can inherit from this file, and add to, or override options on the config object.

config.dev.ts is a specific environment configuration. You can potentially have as many environments as you make files for. To specify which environment to use, append --env.ENV= and the environment name to any commands. An example is provided in package.json.

config.local.ts is an example configuration for local deploys. If you want to deploy to a local server for testing, just edit the path in the file and run with npm run local or npm run watch-local.

Common options you may wish to configure:

output.path: This is the output path for the compiled js. If you are running a local server, you may consider adding an environment that outputs directly to the screeps local folder. This is equivalent to the localPath setting in older versions of the screeps-typescript-starter.

watchOptions.ignored: This option is only to save computer resources, since watch-mode (npm start) can be CPU intensive. You can exclude directories you know don't need to be watched.

module.rules: These are the individual rules webpack uses to process your code. The defaults are generally all you will need. The most useful change you may want to make here is to explicity exclude files or directories from being compiled or linted (in case of 3rd party code, for example). These values, like all others can be passed around and modified before webpack acts on them.

Change the upload branch

You code is uploaded to the branch configured by the branch property on the object sent to new ScreepsWebpackPlugin (see config/config.dev.ts). You have three ways to customize this:

  1. Multiple config environment files, each with a seperate branch
  2. Use the special variables '$activeWorld' to upload to whatever brach is active in the Screeps world
  3. Configure a new environment variable in webpack.config.ts and use that in your code. For example:
// webpack.custom-env.ts
const ScreepsWebpackPlugin = require("screeps-webpack-plugin");
const git = require('git-rev-sync'); // make sure you require `git-rev-sync`

const credentials: Credentials = require("./credentials.json");
credentials.branch = git.branch();

config.plugin("screeps").use(ScreepsWebpackPlugin, [credentials]);

The above example will automatically set your upload branch to be the same as your active git branch. This is functionally equivalent to the option "autobranch": true in older versions.

You still have to create matching branch in screeps client by cloning an existing branch (API limitation). This is useful when setting up deployment pipelines that upload on commit after successful build (so a commit to major_refactoring branch doesn't overwrite your default branch in the middle of epic alliance action just because you forgot to update a pipeline configuration).

Testing

Running Tests

WARNING Testing functionality is currently not finished in the 2.0 build of the Starter.

To enable tests as part of the build and deploy process, flip the test flag in your config.json to true.

You can always run tests by running npm test. You can get a code coverage report by running npm test:coverage. Then opening coverage/index.html in your browser.

Writing Tests

All tests should go in the test/ directory and end in the extension .test.ts.

All constants are available globally as normal.

The game state is no simulated, so you must mock all game objects and state that your code requires. As part of this project, we hope to provide some helpers for generating game objects.

It is recommended to test the smallest pieces of your code at a time. That is, write tests that assert the behavior of single, small functions. The advantages of this are:

  1. less mocking to setup and maintain
  2. allows you to test behavior, not implementation

See test/components/creeps/creepActions.test.ts as an example on how to write a test, including the latest game object mocking support.

For writing assertions we provide chai. Check out their documentation to learn how to write assertions in your tests.

Important: In your tests, if you want to use lodash you must import it explicitly to avoid errors:

import * as _  from "lodash"

Notes

Sample code

This starter kit includes a bit of sample code, which uses some of the new TS2 features mentioned earlier. Feel free to build upon this as you please, but if you don't want to use them, you can remove everything from within the src/ directory and start from scratch.

When starting from scratch, make sure a main.ts file exists with a loop() function. This is necessary in order to run the game loop.

Source: http://support.screeps.com/hc/en-us/articles/204825672-New-main-loop-architecture

--strict mode

The --strict mode was introduced in TypeScript 2.3 which sets all strict type-checking options to true by default. The options affected under the --strict mode are as follows (and may in the future include more options):

  • --strictNullChecks
  • --noImplicitAny
  • --noImplicitThis
  • --alwaysStrict

Starting from version 2.0 of the starter kit, the tsconfig.json file will include a "strict": true setting in the "compilerOptions" section, to conform with the TS 2.3 defaults. If this gives you compile errors, you can try setting "strict" to false, or by overriding one or more of the options listed above.

For more info: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html#new---strict-master-option

TSLint

TSLint checks your TypeScript code for readability, maintainability, and functionality errors, and can also enforce coding style standards.

After each successful compiling of the project, TSLint will parse the TypeScript source files and display a warning for any issues it will find.

You can change the file paths checked automatically by editing the paths in the tslint section of config.json.

This project provides TSLint rules through a tslint.json file, which extends the recommended set of rules from TSLint github repository: https://github.com/palantir/tslint/blob/next/src/configs/recommended.ts

We made some changes to those rules, which we considered necessary and/or relevant to a proper Screeps project:

  • set the forin rule to false, it was forcing for ( ... in ...) loops to check if object members were not coming from the class prototype.
  • set the interface-name rule to false, in order to allow interfaces that are not prefixed with I.
  • set the no-console rule to false, in order to allow using console.
  • in the variable-name rule, added allow-leading-underscore.

If you believe that some rules should not apply to a part of your code, you can use flags to let TSLint know about it: https://palantir.github.io/tslint/usage/rule-flags/

More info about TSLint: https://palantir.github.io/tslint/

Source maps

TODO: Fix this readme info Works out of the box with "npm run deploy-prod" and default values from src/config/config.example.ts. Links back to source control when configured. Code has to be committed at build time and pushed to remote at run time for this to work correctly.

Doesn't work in sim, because they do lots of evals with scripts in sim.

Currently maps are generated, but "source-maps" module doesn't get uploaded for non-webpack builds.

Log level and output can be controlled from console by setting level, showSource and showTick properties on log object.

// print errors only, hide ticks and source locations
log.level = 1;
log.showSource = false;
log.showTick = false;

Console output example

TODO: Fix this readme info Note: As a side effect of changing the project to webpack, the built-in URL template is no longer automatically configured. GitHub and GitLab. If you use Bitbucket, replace LOG_VSC_URL_TEMPLATE on your config.ts with this:

export const LOG_VSC_URL_TEMPLATE = (path: string, line: string) => {
  const parts = path.split('/');
  const filename: string = parts[parts.length - 1];
  return `${LOG_VSC.repo}/src/${LOG_VSC.revision}/${path}?fileviewer=file-view-default#${filename}-${line}`;
};

(Thanks to crzytrane on Slack for this code sample!)

Contributing

  1. Fork it
  2. Create your feature branch: git checkout -b my-new-feature
  3. Commit your changes: git commit -am 'Add some feature'
  4. Push to the branch: git push origin my-new-feature
  5. Create a new Pull Request

Special thanks

Marko Sulamägi, for the original Screeps/TypeScript sample project.