Giter Club home page Giter Club logo

engine's Introduction

npm version

logo

Screeps is a MMO RTS sandbox game for programmers, wherein the core mechanic is programming your units AI. You control your colony by writing JavaScript which operate 24/7 in the single persistent world filled by other players on par with you.

This project is a distributed, standalone game server that allows you to launch your own game world on a local computer or dedicated server on the Internet.

Server launch

The server consists of multiple parallel processes linked to each other. There is a separate launcher process to launch them correctly, and these launchers have various versions for different purposes.

GUI launcher. This is the easiest way to launch the server. It comes with the standard package of the Steam version of the game. You launch the game via the server's executable file that shows the GUI with logs of all started processes and the CLI interface to control the server.

Console launcher. You can also launch the server without the GUI using the command line:

npm install screeps
npx screeps init
npx screeps start

Prerequisites:

You will be prompted for your Steam Web API key, you can obtain it on this page.

Your own launcher. The launchers are intended to launch other server's processes and give them correct environment variables. You can launch those processes your own way (for example, via upstart/systemd, for distributing them across different machines, or setting up an automated testing framework). Please refer to the file launcher/lib/start.js for the list of environment variables that each process needs.

Storage

The default built-in storage is based on LokiJS library which allows to embed it in pure JavaScript environments like the Steam game client. It stores all data in the db.json file. However, you can manually replace the storage engine with another community solution to improve performance.

See this step-by-step guide which explains how to install a standalone private server on Ubuntu using MongoDB and Redis as a storage.

Connect to server

You can connect to your private server using the Steam game client. Click "Change server" and enter your server credentials:

client

Launch options

If you use a stock launcher (either desktop or console), the file .screepsrc in the current catalog stores launch configuration options. You can specify them directly when you launch the server using the console command start.

> npx screeps start --help	
Usage: start [options]	
Start all processes. Launch options can be configured from command line or using the .screepsrc file in the same folder.	
Options:

    -h, --help               output usage information
    --db <path>              The path to the database file.
    --logdir <path>          The path to directory where logs will be created.
    --modfile <path>          The path to JSON file with the list of custom mods to load. Defaults to mods.json.
    --assetdir <path>        The path to directory where static assets are located.
    --port <port>            The port number on which the game server should listen. Defaults to 21025.
    --host <host>            The hostname on which the game server should listen. Defaults to 0.0.0.0.
    --password <password>    The server password which should be provided on user sign in. Default is empty.
    --cli_port <port>        The port number on which the CLI server should listen. Defaults to port+1.
    --cli_host <host>        The hostname on which the CLI server should listen. Defaults to 127.0.0.1.
    --runners_cnt <num>      The number of parallel runner worker processes to launch. Don't set this option greater than the number of your physical CPU cores. Default is 2.
    --processors_cnt <num>   The number of parallel processor worker processes to launch. Don't set this option greater than the number of your physical CPU cores. Default is 2.
    --steam_api_key <key>    If you launch the server without running the local Steam client, then the Steam Web API key is required for authenticating users. It can be obtained on this page: http://steamcommunity.com/dev/apikey

Modules

The server consists of 6 separate modules: launcher, storage, backend, engine, driver,common. They may be in the node_modules of any catalog according to the npm rules. Each module has its own code base and GitHub repository, while the engine module is shared between the official and standalone servers and other modules are developed specifically for the standalone server.

Each module is intended for its own strict purpose:

  • launcher launches the rest of the processes, and it includes the server control GUI.

  • storage contains a LokiJS-based database, a key-value storage, and a Pub/Sub mechanism. The rest of the processes connect to storage to exchange data.

  • backend contains an HTTP server accessed by clients and a CLI server for administration.

  • engine is the game core. It executes game scripts and interacts with game world objects.

  • driver is a link between the environment-independent engine (that is shared for the official server, standalone server, and in-browser simulation) and the immediate environment that hosts the game engine. You can replace this module with your own one, if you wish to use another method of storing and handling data.

  • common is a shared code base with useful utilities.

modules

Authentication

The server does not have any user authentication mechanism of its own. Instead, Steam is employed for this purpose, and the server has two mechanisms that work in parallel to achieve this:

  • Native authentication via the local Steam client on your machine. This is the easiest and handiest method that does not require any setting up and works automatically when launched via Steam.

  • If you want to launch your server on a machine without a Steam client installed, you will have to set up authentication via the Steam Web API. To do this, register a new Steam API Key on this page and set it as the steam_api_key option at the server launch.

Command Line Interface (CLI)

The running server process provides administrative access using a separate port (21026 by default) which allows executing inner server commands using batch commands. It is accessible through the Steam GUI or using this console command:

npx screeps cli

The CLI server contains a JavaScript virtual machine allowing to run any valid JS code and work with inner server functions. They allow changing game objects and call procedures, including those added by you. Some examples of such commands:

// Add an NPC bot to the map
bots.spawn('simplebot', 'W3N1');

// Send a server message to all connected users
system.sendServerMessage("OHAI");

// Generate a new room and add it to the world
map.generateRoom("E0N3", {sources: 4, terrainType: 2});

// View user's data by his username
storage.db['users'].findOne({username: "User"});

// Show all creeps in a room
storage.db['rooms.objects'].find({$and: [{room: 'W1N1'}, {type: 'creep'}]});

// Remove an object by its id
storage.db['rooms.objects'].removeWhere({_id: "abcdef"});

Type help() to get a detailed help for all available objects.

Mods

The game server is written in such a way that you can redefine and configure many aspects of its work. Do not modify server code directly! This will block you from updating with new releases, and the official Steam client of other players will stop connecting to your server. Rather than editing the server's source, create mods.

Mods are simple js files listed in the mods.json (the default folder can be changed through the modfile launch option). Each file must be a Node.js module that exports a single function that receives as an argument a config object:

module.exports = function (config) {

}

Each server process will automatically include all the mods at launch and pass the object config to them with properties corresponding to the type of the launched process. If the server consists of 10 processes, then each mod file will be requested 10 times, each time with a different type of config.

All config child objects are EventEmitter instances that you can listen for game engine events. They also contain some properties that can be simple numeral or string configuration parameters as well as functions that you can redefine thus changing server behavior. Their number will increase with time. We have not prepared documentation for all the available properties yet, but the folder example-mods offers a few simple examples of what you can change by mods. We also recommend to investigate the config object of various processes on your own to find out what is possible.

Installing mods

There are three methods to install a mod to your server:

  • Edit mods.json manually and add a new entry to the array in it.
  • If the mod is published to the NPM repository, you can run npm install my-screeps-mod in your server folder, and it will be added automatically. (CAUTION: There is a bug in some npm 5.x versions which prevents auto install hooks from running.) The mod's package.json should contain "screeps_mod":true parameter in this case:
{
  "name": "my-screeps-mod",
  "version": "1.0.0",
  "main": "my-screeps-mod.js",
  "screeps_mod": true
}
  • Using the Steam Workshop.

NPC bots

You can create autonomous NPC bot players on your private server. They work as regular players, but you can specify their AI scripts in bots option at your mods.json file. Initially there is one AI loaded into your server, called simplebot, but you can always add more, and share with other players.

Use the following CLI commands to control bot players on your server:

> help(bots);
Available methods:
 - bots.spawn(botAiName, roomName, [opts]) - Create a new NPC player with bot AI scripts, and spawn it to the specified room. 'opts' is an object with the following optional pr
operties:
    * name - the name of a bot player, default is randomly generated
    * cpu - the CPU limit of a bot user, default is 100
    * gcl - the Global Control Level of a bot user, default is 1
    * x - the X position of the spawn in the room, default is random
    * y - the Y position of the spawn in the room, default is random
 - bots.reload(botAiName) - Reload scripts for the specified bot AI.
 - bots.removeUser(username) - Delete the specified bot player and all its game objects.
Bot AIs:
 - simplebot [D:\SteamLibrary\steamapps\common\Screeps\server\@screeps\simplebot\src]

If you want to publish your bot AI to the NPM repository, set main.js as the main entry in your package.json, and add screeps_bot:true parameter:

{
  "name": "my-screeps-bot",
  "version": "1.0.0",
  "main": "src/main.js",  
  "screeps_bot": true
}

engine's People

Contributors

alinanova21 avatar artch avatar bastianh avatar carst3n avatar cgamesplay avatar chobobobo avatar creosteanu avatar daboross avatar deft-code avatar edhaase avatar esryok avatar laverdet avatar magnostherobot avatar mattfindley avatar mototroller avatar o4kapuk avatar rbryson74 avatar riftlurker avatar sheeo avatar sparr avatar tedivm avatar wolfwings avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

engine's Issues

NPM version broken [2.9.0]

It looks like the NPM version did not get built before publishing, this results in the bin files not being symlinked and dist folder not existing.

[Optimization] processor/roads/tick

Why does road during decay iterates 2 times through all room objects searching for objects of type "swamp" and "wall". Shouldn't it be enough to just check the terrain mask?

if(_.any(roomObjects, (i) => i.x == object.x && i.y == object.y && i.type == 'swamp') ||

if(_.any(roomObjects, (i) => i.x == object.x && i.y == object.y && i.type == 'wall') ||

Removing the _.any(...) check would change complexity from O(n) to O(1).
I don't have any server to check impacts of this optimizations.

Engine uses a *slightly* older version of lodash than the rest of Screeps

  • screeps/engine is using lodash ^3.10.0.
  • screeps/driver is using lodash ^3.10.1.
  • screeps/common is using lodash ^3.10.1.
  • screeps/backend-local is using lodash ^3.10.1.
  • screeps/launcher is using lodash ^3.10.1.
    As is clear from the above, screeps/engine is 1 bugfix release behind the rest of the Screeps project. I've created a pull request for this.

inactive orders (amount = 0) have wrong price

First spotted by Taki on slack:

When an order is inactive (amount: 0), the order's .price property when returned via Game.market.getOrderById is incorrect. It is smaller than the actual by a factor of 1000.

I've confirmed this and narrowed it down to the following code block:

getOrderById: register.wrapFn(function(id) {
const order = runtimeData.market.orders.all[id] || this.orders[id];
if(!order) {
return null;
}
const result = JSON.parse(JSON.stringify(order));
result.price /= 1000;
return result;

It attempts to fetch order from all orders, but inactive orders don't show up there, so instead it pulls it from your own orders (Game.market.orders), and then divides the order's price by 1000, however, in Game.market.orders the price is already processed, so the end result is price being dividied by 1000 twice, and inaccurate.

Construction sites for roads on swamps are inconsistent

http://screeps.com/s/hqxDDh

Note the road at 24,35, which was most recently placed and placed manually, requires 300 energy. However, the road at 23,24, which was placed via script, requires 1500 energy.

I'm not sure exactly what's going on, but I was able to catch the inconsistency on replay.

Also, I wasn't sure which project to place this in, this one seemed most logical since the code to calculate it appears to be here.

Destroying structure by invoking `Structure#destroy` is not logged by `Room#getEventLog`

The API showed that EVENT_OBJECT_DESTROYED can return the any object in rooms is destroyed. But in engine code the structure destroy can only be logged when it is destroyed by creep or nuke attack (in

eventLog.push({event: C.EVENT_OBJECT_DESTROYED, objectId: target._id, data: { type: target.type }});
). I wonder if i need to spend a lot CPU to check if structure is changed or overwrite the prototype of Structure? Or it is just missing in the structure destroy code?

created/owned structures missing from API in private server with broken patch

I have just init'd a brand new server, connected and created a player, then placed a spawn. Immediately I check and find that Game.spawns.Spawn is undefined, Game.rooms.W8N3.find(FIND_MY_STRUCTURES) finds only the room controller, Game.getObjectById(idofthespawn) returns null.

I have no idea how to further troubleshoot this. I encountered this problem first while using the cli to create some buildings to run some experiments, but later boiled it down to just a spawn on a fresh server.

creep.moveTo doesn't return ERR_NO_PATH when all paths are blocked by creeps

I've been using creep.moveTo with ignoreCreeps: false, and I've noticed that if all paths are blocked by creeps, my creep will just walk to those creeps and then not do anything. The API says that ERR_NO_PATH should be returned when no path is found, but creep.moveTo is instead returning 0 in this case, even though all paths are blocked.

TypeScript?

Wouldn't it make sense to convert this project into TypeScript? If so, I can help out with a PR.

Automatically Attacking Obstacles. Bug or Intended?

Hi,

I don't know whether it is intended, an oversight, or simply a bug but if anything blocks an attack unit, it seems to automatically attack.

I've traced it down to this section of code (with help from a friend/ally):
https://github.com/screeps/engine/blob/master/src/processor/intents/creeps/move.js#L39

It seems to run the attack intent if any obstacles are detected before moving.

While I can see the appeal of such a thing, it does make it tricky to handle ally creeps that are working together in the same room, without them smacking each other over the head when they get too close.

Instead of removing it, may I suggest an optional arg/parameter for the move functions to allow us to disable this behaviour. That way players get to choose whether or not moving will auto-attack. :)

Example:
creep.moveTo(target, {autoAttack: false});
or
creep.moveTo(target, {attackObstacles: false});

Request: Remove minimum resource amount for StructureTerminal.send()

While its not a huge problem, being unable to send a resources in amounts of less than 100 can be a hassle. With multiple rooms producing multiple resources, its easy to accumulate small amounts of intermediary products. The same is true for minerals used to boost creeps; its easy to exhaust your supply of a certain boost, but still have around 10-20 minerals remaining.

While a single room experiencing this issue can be easily rectified, as the number of owned rooms increases, it becomes less manageable. Small resource pockets of a specific type scattered across enough rooms can add up to the hundreds, if not thousands. As it stands, the only way to transfer resources in amounts of less than 100 through a terminal is by creating a buy order and having the target room purchase it (or just outright selling the resource to get rid of it).

.send() already incurs the standard energy cost and cooldown, so I don't feel the 100 unit threshold should be added to that. While not restricting market transactions to this threshold makes sense, its still worth pointing out you can buy and sell in 1 unit increments.

While I don't foresee something like this being useful continuously, managing logistics would be more manageable if you didn't have to factor in resource counts when trying to consolidate a single resource type across multiple rooms.

Node 7 Degradation

Looking into that it seems the biggest cause for performance degradation in node 7 is instanceof being updated in recent V8 builds. nodejs/node#11923
The consensus seems to be to not go with backporting the upstream fix since developement on node 8 is going to be active soon and 7 is not an LTS.
I suspect that node 8 will most likely have the fix since it will probably have a newer V8 build.

Spawning not being set to null after spawning

The spawning property of a StructureSpawn is not set to null after spawning (using spawnCreep) has been completed as the documentation says it should.

Documentation: https://docs.screeps.com/api/#StructureSpawn.spawning

If the spawn is in process of spawning a new creep, this object will contain a StructureSpawn.Spawning object, or null otherwise.

The value is in fact null initially but after spawning a creep it does not get reset properly.

RoomPosition.findClosestByPath ignores range option - always uses range 1

The documentation for RoomPosition.findClosestByPath clearly states that any options from Room.findPath are accepted, one of which is range.

However, RoomPositition.findClosestByPath appears to ignore the range option entirely.

See https://github.com/screeps/engine/blob/master/src/game/rooms.js#L328. The range argument is always set to 1. It should be opts.range || 1.

This bug caused my creeps to not bother repairing structures which they couldn't get adjacent to, which is often the case with thick walls, blocking the observer behind other structures, etc.

How to debug VMs

I've been looking into #121 yesterday and tried to set up some tests to verify wrong/right behavior.

Therefore I had to create a few mocks in roomsSpec.js, but couldn't find out what these values should be.

My idea was to debug the script when its running to get some useful mocks, but I can't get my IDE (VSCode) to debug those...

I've seen there is a config option editor.enableInspector so I figured you have set this up once.
Can you help me set up debugging?


PS: That's where I'm currently at in terms of mocking values

let globals = {};

beforeEach(() => {
  const runtimeData = {
    staticTerrainData: require("../../helpers/mocks/rooms").terrain,
  };
  const register = {
    wrapFn: fn => fn,
    rooms: { E2S7: {} },
    _useNewPathFinder: true,
  };

  rooms.make(runtimeData, {}, register, globals);
  rooms.makePos(register);

  for (var i in runtimeData.rooms) {
    register.rooms[i] = new globals.Room(i);
  }
});

But calling RoomPosition.findClosestByPath still results in the following issue, since globals.PathFinder is not set.

Message:
    TypeError: Cannot read property 'search' of undefined
  Stack:
        at <Jasmine>
        at _findClosestByPath2 (/Users/josef/screeps/screeps-modules/engine/src/game/rooms.js:360:34)
        at RoomPosition.findClosestByPath (/Users/josef/screeps/screeps-modules/engine/src/game/rooms.js:1446:20)
        at UserContext.fit (/Users/josef/screeps/screeps-modules/engine/spec/engine/game/roomsSpec.js:70:28)
        at <Jasmine>
        at runCallback (timers.js:705:18)

Spawn.spawning.setDirections() unable to change number of directions

I'm having an issue with the setDirections API call. It won't let me decrease the number of directions supplied. For instance if I create a creep via: spawn.spawnCreep(body, name, { directions: [ TOP, BOTTOM ] }); and then later I perform spawn.spawning.setDirections([ LEFT ]); then the directions that actually get set are: [ LEFT, BOTTOM ]. It seems like it's merging the old directions and the new ones instead of just overwriting as I would expect.

This is happening on a local server, I'm not sure if it happens on MMO as well.

cc: @sparr because you worked on this in #61

Refactor recommendation for Structure.isActive

Why?

The existing isActive function has two main problems. Firstly, it is incredibly inefficient for its goal, sorting structures by range to controller simply to determine which structures a player can use while the controller is downgraded. Secondly, and far more notably, the code has a chance to return false information to a bot! This seems to happen because there are multiple calls to isActive - a function with pseudo-random return order - for two different situations. First is when the engine runs this to determine which structures it will allow interaction with, and second is when the user runs it to determine which structures they can interact with. So, for example, when two extensions have the same range to the controller, the engine vs user calls to isActive can determine a different extension to be not active.

image
image (12)

Here you can see a non-parallel determination of isActive states between the user and engine calls. (compare the energyAvail to energyCapacity in the console to the 800 energy in what are supposed to be active extensions + spawn)

Nikolay and I agreed there needs to be a fully deterministic solution to address this issue, so enough selling, what can be done?

Solution

Both the Room.structureOfType and Structure.buildOrder properties do not need to be exposed to users for this logic to function. Only the game engine needs access to them.

  • An ideally persistent Room.structuresOfType: {[key: StructureTypes]: number} is used to record the number of structures each structureType in the room. So a count for extensions, spawns, etc.
  • Each structure has a persistent buildOrder: number, a record of what order the structure is in relative to other structures of the same structureType
  • When a structure is destroyed
    • If the buildOrder is not equal to the structure's structureType, splice the buildOrder: loop through each structure of the same structureType and, if their buildOrder is more than that of the structure that is being deleted, decrement their buildOrder by 1
    • decrease the count for the structureType by 1
  • When a structure is built
    • increase the structuresOfType for the new structure's structureType
    • the new structure is assigned the lowest unique build order possible (should just be the current Room.structuresOfType[newStructure.structureType]
  • For existing structures not yet integrated with this new system
    • Simply loop through each structure and apply the "When a structure is built" logic to them
  • When isActive is called
    • As a guard clause to avoid running the entire algorithm, check if the number of structures of the structureType in question is more than the max structures the current RCL can support. If it is not, the structure is definitively active.
    • Loop through each structure of the structureType in question. Record inActive for every structure with a buildOrder less or equal to the max structures the current RCL can support.
    • It can now be a linear search, and is entirely deterministic! This should speed up the algorithm by at least 10x, at the cost of some extra Room and Structure properties. It also fixes the energyAvail/energyCapacity discrepancy bug, which should be a big priority considering it affects many users.

NPM Outdated

Can we get a fresh npm publish to include the latest hotfixes? Market on PS is buggy without the f67f8ff hotfix.

creep.moveTo calculates new Path when creep fatigued and reusePath and visualizePathStyle is used

I don't know if this is intended or not, but if a creep uses moveTo over multiple Ticks while using the Options reusePath and visualizePathStyle, then every Tick the creep is fatigued when calling moveTo, a new Path is generated instead of using the one already saved in memory.

Example call over multiple Ticks: creep.moveTo(target, {reusePath: 50, visualizePathStyle: {})

I think the issue lies here:

engine/src/game/creeps.js

Lines 173 to 175 in 92a3fff

if(data(this.id).fatigue > 0 && (!opts || !opts.visualizePathStyle)) {
return C.ERR_TIRED;
}

This gets skipped when visualizePathStyle is in use, regardless of the .fatigue value.
Then when getting to this Point, at the end of the reusePath Block:

engine/src/game/creeps.js

Lines 271 to 283 in 92a3fff

var result = this.moveByPath(path);
if(result == C.OK) {
return C.OK;
}
}
}
if(opts.noPathFinding) {
return C.ERR_NOT_FOUND;
}
var path = this.pos.findPathTo(targetPos, opts);

var result = this.moveByPath(path); results, down the line in creep.move(), with C.ERR_TIRED, but creep.moveTo only returns on OK, thus continuing further down and generating a new Path at this.pos.findPathTo(targetPos, opts);

Creep.moveTo tries to path through walls where there is no room exit

Take a hypothetical scenario of two rooms, say Shard 2 W39N23 and W38N23.

Using moveTo to go from one to the other will cause the creep to try to move up against the wall and stay there, even though JSON.stringify(Game.map.describeExits("W38N23") returns {"1":"W38N24","3":"W37N23","5":"W38N22"} (i.e. no exit connecting both rooms.

This applies to all edges where the most extreme coordinate (x or y is 0 or 49) is a wall but it is adjacent to moveable tiles.

Unable to build any constructionSite of a type, if structures + sites of that type are higher than RCL allows

var structuresCnt = _(roomObjects).filter((i) => i.type == type || i.type == 'constructionSite' && i.structureType == type).size();

For example, if a room had previously been RCL 3, and somehow ends up being RCL 2 with no extensions currently built, and 6 constructionSites for extensions placed (before the downgrade of controller happened), then it is not possible to perform the last build action on any of the sites.

Update lodash

Can we have a lodash update?

I can of course import my own, which works fine in the world, but in simulation (on the latest copy of chrome, at least, it does not work.

_.js contains a copy of 4.17.2

main.js:

var _ = require('_')
console.log(_.VERSION);

module.exports.loop = function () {
   console.log(_.VERSION);
}

output in world:

4.17.2
4.17.2

output in simulation:

4.17.2
3.10.1

costCallback with pathfinder (findClosestByPath)

In the function _findClosestByPath2 in rooms.js the roomCallback property is not set to the correct costMatrix. The function to generate the costMatrix is there, but it does not get stored in the variable costMatrix.

            if(register.objectsByRoom[roomName]) {
                var costMatrix = getPathfindingGrid2(roomName, opts);
                if(typeof opts.costCallback == 'function') {
                    costMatrix = costMatrix.clone();
                    opts.costCallback(roomName, costMatrix);
                }
                return costMatrix;
            }
        },

roomPosition.findPathTo ignoring options when using findExitTo

I've had problems recently where my creeps fail to path between rooms correctly using creep.moveTo(), no matter how high I set maxOps. They walk to a solid room wall.

On investigating the code, I think the problem is that in RoomPosition.prototype.findPathTo , the exit direction is chosen using:
var exitDir = room.findExitTo(roomName);
rather than something like
var exitDir = room.findExitTo(roomName, opts);
(which would also require a small edit to room.findExitTo, to make it pass opts through to findExit).

So right now, no matter how you set options in creep.moveTo, if the destination is in another room, only 2000 operations are spent trying to decide which exit to path to.

Construction site removal broken, completely locking up rooms on IVM private servers.

Error and stacktrace below, this is on ScreepsPlus with the latest of the isolated-vm branch.
I've also adjusted package.json to point at src rather than dist to allow for easier testing of various patches, however, I also get this error on a completely stock engine too.

Error processing room E14S15: Error: Cannot find module './construction-sites/remove'
    at Function.Module._resolveFilename (module.js:547:15)
    at Function.Module._load (module.js:474:25)
    at Module.require (module.js:596:17)
    at require (internal/module.js:11:18)
    at Object.exports.execute (/screeps/node_modules/@screeps/engine/src/processor/intents/movement.js:177:13)
    at module.exports (/screeps/node_modules/@screeps/engine/src/processor/intents/creeps/tick.js:48:18)
    at _.forEach (/screeps/node_modules/@screeps/engine/src/processor.js:243:59)
    at /screeps/node_modules/lodash/index.js:3073:15
    at baseForOwn (/screeps/node_modules/lodash/index.js:2046:14)
    at /screeps/node_modules/lodash/index.js:3043:18
    at Function.<anonymous> (/screeps/node_modules/lodash/index.js:3346:13)
    at q.when.then (/screeps/node_modules/@screeps/engine/src/processor.js:230:11)
    at _fulfilled (/screeps/node_modules/q/q.js:854:54)
    at self.promiseDispatch.done (/screeps/node_modules/q/q.js:883:30)
    at Promise.promise.promiseDispatch (/screeps/node_modules/q/q.js:816:13)
    at /screeps/node_modules/q/q.js:570:49
    at runSingle (/screeps/node_modules/q/q.js:137:13)
    at flush (/screeps/node_modules/q/q.js:125:13)
    at _combinedTickCallback (internal/process/next_tick.js:131:7)
    at process._tickDomainCallback (internal/process/next_tick.js:218:9)```

Increase creep.say character limit

Creep.say is very useful for communicating with other players, for logging what your creeps are doing to yourself for debugging purposes, and for aesthetics. But the 10 character limit is extremely restrictive; you can only log a single word, or two short words. I don't see any reason it needs to be this short; other players can always turn off messages in their visual settings, so there's no downside to allowing players to write longer messages if they want to. It would be extremely simple to change; just replace 10 with 25 in the intent.message.substring(0,10), line of src/processor/intents/creeps/say.js and src/processor/intents/power-creeps/say.js.

(If the speech bubble code can automatically handle multiple lines, I think a longer limit of around 100 characters would be ideal. But if that would require working the speech bubble code to support multiple lines, I don't think it's worth it. I'm hoping a simple 10 > 25 change might be accepted despite this project's relative inactivity because it's so easy to do.)

Feature request: cancel spawning

artch brought this up in #61 where StructureSpawn.spawning is growing up to have a prototype instead of just being a bare object. Once we have StructureSpawn.Spawning.setDirections() there's nothing technically stopping us from having .cancel().

Some folks discussed this in #general on Slack and I want to get feedback here on how spawn canceling should work.

Should you be able to use it at any time?
Should you get a refund on the energy you spent? (yes, no, partial)
Where should that refund go? (back to extensions, dropped on spawn, dropped/stored adjacent to spawn, ...)
Should you be able to start a new spawncreep on the same tick as canceling a current one?

spawnCreep should automatically assign a name

I just noticed that spawnCreep (as opposed to createCreep) does not automatically assign a name to created creeps anymore.

I think this is an unneccessary complication for new players, which should not use a deprecated method like createCreep, should they?

Was there a particular reason to leave that behaviour out? The pull request does not at all mention this change, I discovered it by chance after seeing that my spawning code does not work after changing to the new method signature.

edit: In case you want to keep the behaviour as is, the documentation of return values should be updated. Currently it only points at an errorneous creep body, but not at a missing name.

Can't create flag in room with no creeps in it.

Trying to create a flag using RoomPosition.createFlag in a room with no creeps in it fails.

let destinationPos = new RoomPosition(25, 25, roomName);
destinationPos.createFlag(flagName);

Game console output:

Error: Could not access room W3N7
    at . ([...]\steamapps\common\Screeps\server\node_modules\@screeps\engine\dist\game\rooms.js:1444:19)
    at .createFlag (evalmachine.:1:72)
    [...]

Private server version is 2.3.0

Engine using newly deprecated method

RoomPosition.prototype.lookFor() uses the deprecated Game.map.getTerrainAt() instead of the new Game.Map.getRoomTerrain if LOOK_TERRAIN is used as constant.

Lines 1459 onwards.

energyCapacityAvailable not checking controller owner

I have a room with a single spawn and no extensions owned by me. It has several hostile extensions.

running command
Game.rooms.W44N83.energyCapacityAvailable
gives a value of 550.

This should check if controller.owner == structure.owner
line 286
engine/src/game/game.js

The correct value for energyCapacityAvailable should be 300 for a single spawn.

Destroying lab does not drop minerals

Destroying a lab doesn't drop any minerals that were inside on the ground. I think the problem is that engine/src/processor/intents/room/destroy-structure.js is only checking object[resourceType] (which is the equivalent of .store? I think?)

This may also affect nukers full of ghodium; I'm not quite dedicated enough to bug reporting to test that one.

Upgrade to Latest Node Versions

It seems based on discussions in the Screeps discord the engine is not compatible with latest Node versions. It sounds like the infra is on Node 8 today? @o4kapuk is there any interest in upgrading the engine/infra to improve tick times? I can create the PR if devs want to actually do the upgrade...

Limit LOC Based On GCL

As the title says, I think the total LOC of your scripts should be limited based on GCL. I'm sick of always having TooAngel or bonzAI as my neighbor, and it's bad for the game in general when open source scripts become rampant.

It sets the barrier too high for new players. This creates a scenario where in order to even survive early on, a new player needs to be able to match the open source AIs with 50k+ lines of code, when the new player barely even understands the basics of the API.

Players using an open source AI are theoretically likely to be more aggressive than players who had to write their own AI, as they don't have any appreciation of the effort it takes to write an AI that is capable of defending rooms, attacking other players, etc, all without crashing the economy. This amplifies the above issue.

Players using an open source AI aren't likely to stick around long. The whole point of the game is programming. Take that away, and what is left? If these are Steam players, then each one will be wasting up to 10 cpu/tick for quite a while until someone decides to wipe them out. Where a player who wrote his own AI and got bored would likely be using up much less cpu/tick, as their AI will be much less robust. This also feeds into the first issue by pushing other new players into having to use an open source AI to even survive.

Your target audience, I would imagine, are programmers. People who can actually write code. Not people who can copy/paste code. I myself am a programmer, and I would much rather write my own AI than use one of the open source AIs. However, on shard1, in the initial green zone I spawned in, there was a TooAngel bot who was about on pace with me. And the only reason it wasn't well ahead of me is a combination of where I spawned giving me a choke point and the fact I reserved any rooms he would have been able to expand to before he could expand, forcing him to respawn.

After hitting GCL 3 I decided to move to a blue zone before I hit GCL 4 so that I would be able to claim a new room once I hit GCL 4. Upon doing this, I was wiped out over night by someone using the standard bonzAI layout. The place I had chosen wasn't overly close to anyone as far as I could tell, and I hadn't been aggressive towards that player. This isn't a positive new player experience. If it was bonzAI himself, that would be one thing. But when it's someone else using the bonzAI source he copy/pasted from github, that leaves a pretty sour taste in your mouth. That taste could only be more sour if that someone purchased the bonzAI source from Screeps with real currency.

Limiting the maximum lines of code per repo based on the player's GCL would go a long way towards resolving this. It could be done in a way that discourages the use of full-fledged open source AIs, but doesn't hinder the player's ability to advance. The open source AIs are in the 10s of thousands of lines of code, where a player under GCL 5 isn't likely to have more than 10,000 lines of code.

Ideally, the limit would only be for the first 10 levels, and then it gets lifted so that the player's maximum is unchanged from what it is today. The limit would also ideally have enough room after the first couple levels of GCL that the player could use third party libraries such as behavior3 or Traveler without reaching their LOC cap.

Obviously this could be circumvented by separating the code for the open source AIs out into stages that could be used at each GCL, and it won't stop the truly determined from copy/pasting an open source AI. But to separate out the open source AIs into stages would be quite an undertaking, and I doubt anyone in the community would be willing to do this just for the sake of being able to use the AI before GCL 10. Thus, it would still serve its purpose of preventing new players from copy/pasting an open source AI.

Over all, I think this change will go a long way towards improving this game. If it's not this change that solves the problem, then I think something else definitely needs to be done to solve the problem. As it is currently, it's just TooAngel vs bonzAI, and that's no fun.

Bugfix / Lab -> boostCreep(..) - partial boosting

Hi mates.
Not sure if this is the right place to announce a bug fix for the current master.

The line 30 in engine/src/processor/intents/labs/boost-creep.js

 if(intent.bodyPartsCount) {
        nonBoostedParts.slice(0,intent.bodyPartsCount);
    }

should be:

 if(intent.bodyPartsCount) {
        nonBoostedParts = nonBoostedParts.slice(0,intent.bodyPartsCount);
    }

because the slice method returns a shallow copy of the original ...

If this is not the right place, could someone make a pull request? (I'm not very familiar with git in general)

I hope this helps ..
Casegard

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.