mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-26 14:34:39 +00:00
@@ -207,11 +207,22 @@
|
||||
* use mini A* for all pathfinding DONE 12/3/2024
|
||||
* bugfix: gameStop not found error DONE 12/3/2024
|
||||
* log stack traces & display them on screen DONE 12/3/2024
|
||||
* add radiation from nuke DONE 12/4/2024
|
||||
* add cities DONE 12/4/2024
|
||||
* max price for units
|
||||
* when player dies, don't remove atom bombs
|
||||
* record and replay games for debugging purposes
|
||||
* add bug report button in game
|
||||
* bugfix: destroyers can't find path to dst and freeze
|
||||
* record single player game stats
|
||||
* add radiation from nuke
|
||||
* add cities
|
||||
* stop requesting lobby when playing game
|
||||
* nuking an enemy and accidentally destroying a trade ship shouldn't break the alliance and make you a traitor
|
||||
* you should get a notification and a reward (some money) for eliminating an enemy (perhaps take wtvr gold the enemy had)
|
||||
* emojis should be displayed on top of your name not under it
|
||||
* the notification for a successful trade should be shorter, example: " 70k Gold from trade with "X" "
|
||||
* countries don't actually spawn with some randomness, it's always the same exact spawn
|
||||
* allow longer names and allow them to be displayed in the Rank UI not be cut (many are cut for now, even for countries)
|
||||
* clicking on a player's name in the rank UI should teleport you to him (pretty useful to know who's who and to locate small nations)
|
||||
* create behavior tests
|
||||
* create perf test
|
||||
* create alternate view to show friendly & enemy units
|
||||
@@ -232,4 +243,5 @@
|
||||
|
||||
* improve front page (make map larger?)
|
||||
* REFACTOR: give terranullius an ID, game.player() returns terranullius
|
||||
* REFACTOR: ocean is considered TerraNullius ?
|
||||
* REFACTOR: ocean is considered TerraNullius ?
|
||||
|
||||
|
||||
Generated
+367
-5
@@ -7,6 +7,7 @@
|
||||
"name": "openfront-client",
|
||||
"dependencies": {
|
||||
"@datastructures-js/priority-queue": "^6.3.1",
|
||||
"@google-cloud/storage": "^7.14.0",
|
||||
"@types/dompurify": "^3.0.5",
|
||||
"@types/express": "^4.17.21",
|
||||
"@types/google-protobuf": "^3.15.12",
|
||||
@@ -2349,6 +2350,93 @@
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@google-cloud/paginator": {
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-5.0.2.tgz",
|
||||
"integrity": "sha512-DJS3s0OVH4zFDB1PzjxAsHqJT6sKVbRwwML0ZBP9PbU7Yebtu/7SWMRzvO2J3nUi9pRNITCfu4LJeooM2w4pjg==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"arrify": "^2.0.0",
|
||||
"extend": "^3.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@google-cloud/paginator/node_modules/arrify": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz",
|
||||
"integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@google-cloud/projectify": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-4.0.0.tgz",
|
||||
"integrity": "sha512-MmaX6HeSvyPbWGwFq7mXdo0uQZLGBYCwziiLIGq5JVX+/bdI3SAq6bP98trV5eTWfLuvsMcIC1YJOF2vfteLFA==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@google-cloud/promisify": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-4.0.0.tgz",
|
||||
"integrity": "sha512-Orxzlfb9c67A15cq2JQEyVc7wEsmFBmHjZWZYQMUyJ1qivXyMwdyNOs9odi79hze+2zqdTtu1E19IM/FtqZ10g==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/@google-cloud/storage": {
|
||||
"version": "7.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-7.14.0.tgz",
|
||||
"integrity": "sha512-H41bPL2cMfSi4EEnFzKvg7XSb7T67ocSXrmF7MPjfgFB0L6CKGzfIYJheAZi1iqXjz6XaCT1OBf6HCG5vDBTOQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@google-cloud/paginator": "^5.0.0",
|
||||
"@google-cloud/projectify": "^4.0.0",
|
||||
"@google-cloud/promisify": "^4.0.0",
|
||||
"abort-controller": "^3.0.0",
|
||||
"async-retry": "^1.3.3",
|
||||
"duplexify": "^4.1.3",
|
||||
"fast-xml-parser": "^4.4.1",
|
||||
"gaxios": "^6.0.2",
|
||||
"google-auth-library": "^9.6.3",
|
||||
"html-entities": "^2.5.2",
|
||||
"mime": "^3.0.0",
|
||||
"p-limit": "^3.0.1",
|
||||
"retry-request": "^7.0.0",
|
||||
"teeny-request": "^9.0.0",
|
||||
"uuid": "^8.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/@google-cloud/storage/node_modules/mime": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz",
|
||||
"integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"mime": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@google-cloud/storage/node_modules/uuid": {
|
||||
"version": "8.3.2",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"uuid": "dist/bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/cliui": {
|
||||
"version": "8.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
|
||||
@@ -3568,6 +3656,15 @@
|
||||
"integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@tootallnate/once": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
|
||||
"integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tsconfig/node10": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz",
|
||||
@@ -3661,6 +3758,12 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/caseless": {
|
||||
"version": "0.12.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.5.tgz",
|
||||
"integrity": "sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/chai": {
|
||||
"version": "4.3.20",
|
||||
"resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.20.tgz",
|
||||
@@ -4208,6 +4311,18 @@
|
||||
"safe-buffer": "~5.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/request": {
|
||||
"version": "2.48.12",
|
||||
"resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.12.tgz",
|
||||
"integrity": "sha512-G3sY+NpsA9jnwm0ixhAFQSJ3Q9JkpLZpJbI3GMv0mIAT0y3mRabYeINzal5WOChIiaTEGQYlHOKgkaM9EisWHw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/caseless": "*",
|
||||
"@types/node": "*",
|
||||
"@types/tough-cookie": "*",
|
||||
"form-data": "^2.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/retry": {
|
||||
"version": "0.12.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz",
|
||||
@@ -4287,6 +4402,12 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/tough-cookie": {
|
||||
"version": "4.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz",
|
||||
"integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/trusted-types": {
|
||||
"version": "2.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
|
||||
@@ -4855,6 +4976,30 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/async-retry": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz",
|
||||
"integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"retry": "0.13.1"
|
||||
}
|
||||
},
|
||||
"node_modules/async-retry/node_modules/retry": {
|
||||
"version": "0.13.1",
|
||||
"resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz",
|
||||
"integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
}
|
||||
},
|
||||
"node_modules/asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/babel-jest": {
|
||||
"version": "29.7.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz",
|
||||
@@ -5703,6 +5848,18 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/commander": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
|
||||
@@ -6610,6 +6767,15 @@
|
||||
"robust-predicates": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/depd": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||
@@ -6780,6 +6946,32 @@
|
||||
"tslib": "^2.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/duplexify": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.3.tgz",
|
||||
"integrity": "sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"end-of-stream": "^1.4.1",
|
||||
"inherits": "^2.0.3",
|
||||
"readable-stream": "^3.1.1",
|
||||
"stream-shift": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/duplexify/node_modules/readable-stream": {
|
||||
"version": "3.6.2",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
|
||||
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"inherits": "^2.0.3",
|
||||
"string_decoder": "^1.1.1",
|
||||
"util-deprecate": "^1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/eastasianwidth": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
|
||||
@@ -6872,6 +7064,15 @@
|
||||
"iconv-lite": "^0.6.2"
|
||||
}
|
||||
},
|
||||
"node_modules/end-of-stream": {
|
||||
"version": "1.4.4",
|
||||
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
|
||||
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"once": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/enhanced-resolve": {
|
||||
"version": "5.17.1",
|
||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz",
|
||||
@@ -7309,6 +7510,28 @@
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/fast-xml-parser": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.0.tgz",
|
||||
"integrity": "sha512-/PlTQCI96+fZMAOLMZK4CWG1ItCbfZ/0jx7UIJFChPNrx7tcEgerUgWbeieCM9MfHInUDyK8DWYZ+YrywDJuTg==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/NaturalIntelligence"
|
||||
},
|
||||
{
|
||||
"type": "paypal",
|
||||
"url": "https://paypal.me/naturalintelligence"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"strnum": "^1.0.5"
|
||||
},
|
||||
"bin": {
|
||||
"fxparser": "src/cli/cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/fastest-levenshtein": {
|
||||
"version": "1.0.16",
|
||||
"resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz",
|
||||
@@ -7550,6 +7773,41 @@
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "2.5.2",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.2.tgz",
|
||||
"integrity": "sha512-GgwY0PS7DbXqajuGf4OYlsrIu3zgxD6Vvql43IBhm6MahqA5SK/7mwhtNj2AdH2z35YR34ujJ7BN+3fFC3jP5Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.6",
|
||||
"mime-types": "^2.1.12",
|
||||
"safe-buffer": "^5.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.12"
|
||||
}
|
||||
},
|
||||
"node_modules/form-data/node_modules/safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/forwarded": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
|
||||
@@ -8041,7 +8299,6 @@
|
||||
"version": "2.5.2",
|
||||
"resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz",
|
||||
"integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
@@ -10807,7 +11064,6 @@
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"wrappy": "1"
|
||||
@@ -10861,7 +11117,6 @@
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
|
||||
"integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"yocto-queue": "^0.1.0"
|
||||
@@ -11912,6 +12167,20 @@
|
||||
"node": ">= 4"
|
||||
}
|
||||
},
|
||||
"node_modules/retry-request": {
|
||||
"version": "7.0.2",
|
||||
"resolved": "https://registry.npmjs.org/retry-request/-/retry-request-7.0.2.tgz",
|
||||
"integrity": "sha512-dUOvLMJ0/JJYEn8NrpOaGNE7X3vpI5XlZS/u0ANjqtcZVKnIxP7IgCFwrKTxENw29emmwug53awKtaMm4i9g5w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/request": "^2.48.8",
|
||||
"extend": "^3.0.2",
|
||||
"teeny-request": "^9.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/robust-predicates": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz",
|
||||
@@ -12518,6 +12787,21 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/stream-events": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz",
|
||||
"integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"stubs": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/stream-shift": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz",
|
||||
"integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/string_decoder": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
|
||||
@@ -12648,6 +12932,12 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/strnum": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz",
|
||||
"integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/strtok3": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.3.0.tgz",
|
||||
@@ -12665,6 +12955,12 @@
|
||||
"url": "https://github.com/sponsors/Borewit"
|
||||
}
|
||||
},
|
||||
"node_modules/stubs": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz",
|
||||
"integrity": "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/style-loader": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/style-loader/-/style-loader-4.0.0.tgz",
|
||||
@@ -12774,6 +13070,74 @@
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/teeny-request": {
|
||||
"version": "9.0.0",
|
||||
"resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-9.0.0.tgz",
|
||||
"integrity": "sha512-resvxdc6Mgb7YEThw6G6bExlXKkv6+YbuzGg9xuXxSgxJF7Ozs+o8Y9+2R3sArdWdW8nOokoQb1yrpFB0pQK2g==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"http-proxy-agent": "^5.0.0",
|
||||
"https-proxy-agent": "^5.0.0",
|
||||
"node-fetch": "^2.6.9",
|
||||
"stream-events": "^1.0.5",
|
||||
"uuid": "^9.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/teeny-request/node_modules/agent-base": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
|
||||
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"debug": "4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/teeny-request/node_modules/http-proxy-agent": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz",
|
||||
"integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@tootallnate/once": "2",
|
||||
"agent-base": "6",
|
||||
"debug": "4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/teeny-request/node_modules/https-proxy-agent": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
|
||||
"integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"agent-base": "6",
|
||||
"debug": "4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/teeny-request/node_modules/uuid": {
|
||||
"version": "9.0.1",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
|
||||
"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
|
||||
"funding": [
|
||||
"https://github.com/sponsors/broofa",
|
||||
"https://github.com/sponsors/ctavan"
|
||||
],
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"uuid": "dist/bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/terser": {
|
||||
"version": "5.36.0",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.36.0.tgz",
|
||||
@@ -14198,7 +14562,6 @@
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/write-file-atomic": {
|
||||
@@ -14394,7 +14757,6 @@
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
||||
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@datastructures-js/priority-queue": "^6.3.1",
|
||||
"@google-cloud/storage": "^7.14.0",
|
||||
"@types/dompurify": "^3.0.5",
|
||||
"@types/express": "^4.17.21",
|
||||
"@types/google-protobuf": "^3.15.12",
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 129 B |
@@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
|
||||
<svg
|
||||
fill="#000000"
|
||||
width="800px"
|
||||
height="800px"
|
||||
viewBox="0 0 24 24"
|
||||
version="1.1"
|
||||
id="svg4"
|
||||
sodipodi:docname="CityIconWhite.svg"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs8" />
|
||||
<sodipodi:namedview
|
||||
id="namedview6"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.295"
|
||||
inkscape:cx="401.69492"
|
||||
inkscape:cy="400"
|
||||
inkscape:window-width="1536"
|
||||
inkscape:window-height="987"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg4" />
|
||||
<path
|
||||
d="M13,9a1,1,0,0,0-1-1H3A1,1,0,0,0,2,9V22H13ZM6,20H4V18H6Zm0-4H4V14H6Zm0-4H4V10H6Zm5,8H8V18h3Zm0-4H8V14h3Zm0-4H8V10h3Zm3.5-6H6V3A1,1,0,0,1,7,2H17a1,1,0,0,1,1,1v7H15V6.5A.5.5,0,0,0,14.5,6ZM22,13v9H19.5V18h-2v4H15V13a1,1,0,0,1,1-1h5A1,1,0,0,1,22,13Z"
|
||||
id="path2" />
|
||||
<path
|
||||
style="fill:#ffffff;stroke-width:3.38983"
|
||||
d="M 67.79661,511.52542 V 290.84746 l 11.621631,-11.62163 11.621632,-11.62163 161.555287,0.94366 161.55528,0.94367 8.17902,9.51106 8.17901,9.51106 V 510.35852 732.20339 H 249.15254 67.79661 Z M 200,633.89831 V 600 h -33.89831 -33.8983 v 33.89831 33.8983 H 166.10169 200 Z m 169.49153,0 V 600 h -52.54238 -52.54237 v 33.89831 33.8983 h 52.54237 52.54238 z M 200,500 v -35.59322 h -33.89831 -33.8983 V 500 535.59322 H 166.10169 200 Z m 169.49153,0 V 464.40678 H 316.94915 264.40678 V 500 535.59322 h 52.54237 52.54238 z M 200,366.10169 v -33.8983 h -33.89831 -33.8983 V 366.10169 400 H 166.10169 200 Z m 169.49153,0 v -33.8983 H 316.94915 264.40678 V 366.10169 400 h 52.54237 52.54238 z"
|
||||
id="path183"
|
||||
transform="scale(0.03)" />
|
||||
<path
|
||||
style="fill:#ffffff;stroke-width:3.38983"
|
||||
d="m 501.69492,270.16949 c 0,-43.72881 -1.20034,-63.23423 -4.0678,-66.10169 C 494.58828,201.02896 456.35566,200 346.48184,200 H 199.40436 l 1.14528,-53.55002 c 1.24728,-58.31948 4.26404,-68.716423 21.88222,-75.414844 11.34097,-4.31183 343.79529,-4.31183 355.13628,0 4.68488,1.781189 11.26725,7.431255 14.62745,12.555701 5.54217,8.452001 6.20319,20.427403 7.11855,128.964863 l 1.00901,119.64769 h -49.3141 -49.31413 z"
|
||||
id="path185"
|
||||
transform="scale(0.03)" />
|
||||
<path
|
||||
style="fill:#ffffff;stroke-width:3.38983"
|
||||
d="M 501.69492,578.01958 V 423.83577 l 9.89142,-11.07043 9.89143,-11.07042 h 92.80003 c 83.69792,0 93.71458,0.59923 102.12428,6.10948 5.12834,3.36022 10.78159,9.94258 12.56278,14.62746 1.88177,4.94941 3.23853,71.62228 3.23853,159.14475 V 732.20339 H 691.52542 650.84746 V 666.10169 600 h -33.89831 -33.8983 v 66.10169 66.1017 h -40.67797 -40.67796 z"
|
||||
id="path187"
|
||||
transform="scale(0.03)" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.1 KiB |
@@ -8,6 +8,7 @@ import { EventBus } from "../../../core/EventBus";
|
||||
import anchorIcon from '../../../../resources/images/AnchorIcon.png';
|
||||
import missileSiloIcon from '../../../../resources/images/MissileSiloUnit.png';
|
||||
import shieldIcon from '../../../../resources/images/ShieldIcon.png';
|
||||
import cityIcon from '../../../../resources/images/CityIcon.png';
|
||||
|
||||
interface UnitRenderConfig {
|
||||
icon: string;
|
||||
@@ -38,6 +39,11 @@ export class StructureLayer implements Layer {
|
||||
icon: shieldIcon,
|
||||
borderRadius: 8,
|
||||
territoryRadius: 6
|
||||
},
|
||||
[UnitType.City]: {
|
||||
icon: cityIcon,
|
||||
borderRadius: 8,
|
||||
territoryRadius: 6
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -75,6 +75,10 @@ export class TerritoryLayer implements Layer {
|
||||
}
|
||||
|
||||
paintTerritory(tile: Tile) {
|
||||
if (tile.hasFallout()) {
|
||||
this.paintCell(tile.cell(), this.theme.falloutColor(), 150)
|
||||
return
|
||||
}
|
||||
if (!tile.hasOwner()) {
|
||||
this.clearCell(tile.cell())
|
||||
return
|
||||
|
||||
@@ -11,6 +11,7 @@ import missileSiloIcon from '../../../../../resources/images/MissileSiloIconWhit
|
||||
import goldCoinIcon from '../../../../../resources/images/GoldCoinIcon.svg';
|
||||
import portIcon from '../../../../../resources/images/PortIcon.svg';
|
||||
import shieldIcon from '../../../../../resources/images/ShieldIconWhite.svg';
|
||||
import cityIcon from '../../../../../resources/images/CityIconWhite.svg';
|
||||
import { renderNumber } from '../../Utils';
|
||||
import { ContextMenuEvent } from '../../../InputHandler';
|
||||
|
||||
@@ -27,7 +28,8 @@ const buildTable: BuildItemDisplay[][] = [
|
||||
{ unitType: UnitType.Battleship, icon: battleshipIcon },
|
||||
{ unitType: UnitType.Port, icon: portIcon },
|
||||
{ unitType: UnitType.MissileSilo, icon: missileSiloIcon },
|
||||
{ unitType: UnitType.DefensePost, icon: shieldIcon }
|
||||
{ unitType: UnitType.DefensePost, icon: shieldIcon },
|
||||
{ unitType: UnitType.City, icon: cityIcon }
|
||||
]
|
||||
];
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ export interface Config {
|
||||
}
|
||||
attackAmount(attacker: Player, defender: Player | TerraNullius): number
|
||||
maxPopulation(player: Player): number
|
||||
cityPopulationIncrease(): number
|
||||
boatAttackAmount(attacker: Player, defender: Player | TerraNullius): number
|
||||
boatMaxDistance(): number
|
||||
boatMaxNumber(): number
|
||||
@@ -62,6 +63,9 @@ export interface Config {
|
||||
tradeShipSpawnRate(): number
|
||||
defensePostRange(): number
|
||||
defensePostDefenseBonus(): number
|
||||
falloutDefenseModifier(): number
|
||||
maxUnitCost(): number
|
||||
gameStorageBucketName(): string
|
||||
}
|
||||
|
||||
export interface Theme {
|
||||
@@ -71,6 +75,7 @@ export interface Theme {
|
||||
defendedBorderColor(playerInfo: PlayerInfo): Colord;
|
||||
terrainColor(tile: Tile): Colord;
|
||||
backgroundColor(): Colord;
|
||||
falloutColor(): Colord
|
||||
font(): string;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,22 @@ import { pastelTheme } from "./PastelTheme";
|
||||
|
||||
|
||||
export class DefaultConfig implements Config {
|
||||
|
||||
maxUnitCost(): number {
|
||||
return 99_999_999
|
||||
}
|
||||
|
||||
cityPopulationIncrease(): number {
|
||||
return 250_000
|
||||
}
|
||||
|
||||
falloutDefenseModifier(): number {
|
||||
return 2
|
||||
}
|
||||
|
||||
gameStorageBucketName(): string {
|
||||
return "openfront-games"
|
||||
}
|
||||
defensePostRange(): number {
|
||||
return 30
|
||||
}
|
||||
@@ -23,61 +39,73 @@ export class DefaultConfig implements Config {
|
||||
tradeShipSpawnRate(): number {
|
||||
return 500
|
||||
}
|
||||
|
||||
unitInfo(type: UnitType): UnitInfo {
|
||||
switch (type) {
|
||||
case UnitType.TransportShip:
|
||||
return {
|
||||
cost: () => 0,
|
||||
territoryBound: false
|
||||
}
|
||||
case UnitType.Destroyer:
|
||||
return {
|
||||
cost: (p: Player) => (p.units(UnitType.Destroyer).length + 1) * 250_000,
|
||||
territoryBound: false
|
||||
}
|
||||
case UnitType.Battleship:
|
||||
return {
|
||||
cost: (p: Player) => (p.units(UnitType.Battleship).length + 1) * 500_000,
|
||||
territoryBound: false
|
||||
}
|
||||
case UnitType.Shell:
|
||||
return {
|
||||
cost: (p: Player) => 0,
|
||||
territoryBound: false
|
||||
}
|
||||
case UnitType.Port:
|
||||
return {
|
||||
cost: (p: Player) => Math.pow(2, p.units(UnitType.Port).length) * 250_000,
|
||||
territoryBound: true
|
||||
}
|
||||
case UnitType.AtomBomb:
|
||||
return {
|
||||
cost: () => 1_000_000,
|
||||
territoryBound: false
|
||||
}
|
||||
case UnitType.HydrogenBomb:
|
||||
return {
|
||||
cost: () => 5_000_000,
|
||||
territoryBound: false
|
||||
}
|
||||
case UnitType.TradeShip:
|
||||
return {
|
||||
cost: () => 0,
|
||||
territoryBound: false
|
||||
}
|
||||
case UnitType.MissileSilo:
|
||||
return {
|
||||
cost: () => 1_000_000,
|
||||
territoryBound: true
|
||||
}
|
||||
case UnitType.DefensePost:
|
||||
return {
|
||||
cost: (p: Player) => Math.pow(2, p.units(UnitType.Port).length) * 100_000,
|
||||
territoryBound: true
|
||||
}
|
||||
default:
|
||||
assertNever(type)
|
||||
const fn = () => {
|
||||
switch (type) {
|
||||
case UnitType.TransportShip:
|
||||
return {
|
||||
cost: () => 0,
|
||||
territoryBound: false
|
||||
}
|
||||
case UnitType.Destroyer:
|
||||
return {
|
||||
cost: (p: Player) => (p.units(UnitType.Destroyer).length + 1) * 250_000,
|
||||
territoryBound: false
|
||||
}
|
||||
case UnitType.Battleship:
|
||||
return {
|
||||
cost: (p: Player) => (p.units(UnitType.Battleship).length + 1) * 500_000,
|
||||
territoryBound: false
|
||||
}
|
||||
case UnitType.Shell:
|
||||
return {
|
||||
cost: (p: Player) => 0,
|
||||
territoryBound: false
|
||||
}
|
||||
case UnitType.Port:
|
||||
return {
|
||||
cost: (p: Player) => Math.pow(2, p.units(UnitType.Port).length) * 250_000,
|
||||
territoryBound: true
|
||||
}
|
||||
case UnitType.AtomBomb:
|
||||
return {
|
||||
cost: () => 1_000_000,
|
||||
territoryBound: false
|
||||
}
|
||||
case UnitType.HydrogenBomb:
|
||||
return {
|
||||
cost: () => 5_000_000,
|
||||
territoryBound: false
|
||||
}
|
||||
case UnitType.TradeShip:
|
||||
return {
|
||||
cost: () => 0,
|
||||
territoryBound: false
|
||||
}
|
||||
case UnitType.MissileSilo:
|
||||
return {
|
||||
cost: () => 1_000_000,
|
||||
territoryBound: true
|
||||
}
|
||||
case UnitType.DefensePost:
|
||||
return {
|
||||
cost: (p: Player) => Math.pow(2, p.units(UnitType.Port).length) * 100_000,
|
||||
territoryBound: true
|
||||
}
|
||||
case UnitType.City:
|
||||
return {
|
||||
cost: (p: Player) => Math.pow(2, p.units(UnitType.Port).length) * 250_000,
|
||||
territoryBound: true
|
||||
}
|
||||
default:
|
||||
assertNever(type)
|
||||
}
|
||||
}
|
||||
const ui = fn()
|
||||
const oldCost = ui.cost
|
||||
ui.cost = (p: Player) => Math.min(this.maxUnitCost(), oldCost(p))
|
||||
return ui
|
||||
}
|
||||
defaultDonationAmount(sender: Player): number {
|
||||
return Math.floor(sender.troops() / 3)
|
||||
@@ -148,6 +176,10 @@ export class DefaultConfig implements Config {
|
||||
}
|
||||
mag *= tileToConquer.defenseBonus(attacker)
|
||||
speed *= tileToConquer.defenseBonus(attacker)
|
||||
if (tileToConquer.hasFallout()) {
|
||||
mag *= this.falloutDefenseModifier()
|
||||
speed *= this.falloutDefenseModifier()
|
||||
}
|
||||
|
||||
if (attacker.isPlayer() && defender.isPlayer()) {
|
||||
if (attacker.type() == PlayerType.Human && defender.type() == PlayerType.Bot) {
|
||||
@@ -208,7 +240,7 @@ export class DefaultConfig implements Config {
|
||||
if (player.type() == PlayerType.Bot) {
|
||||
return maxPop
|
||||
}
|
||||
return maxPop * 2
|
||||
return maxPop * 2 + player.units(UnitType.City).length * this.cityPopulationIncrease()
|
||||
}
|
||||
|
||||
populationIncreaseRate(player: Player): number {
|
||||
|
||||
@@ -5,9 +5,12 @@ export const devConfig = new class extends DefaultConfig {
|
||||
unitInfo(type: UnitType): UnitInfo {
|
||||
const info = super.unitInfo(type)
|
||||
const oldCost = info.cost
|
||||
info.cost = (p: Player) => oldCost(p) / 100000
|
||||
info.cost = (p: Player) => oldCost(p) / 1000
|
||||
return info
|
||||
}
|
||||
maxUnitCost(): number {
|
||||
return 10000
|
||||
}
|
||||
|
||||
percentageTilesOwnedToWin(): number {
|
||||
return 95
|
||||
|
||||
@@ -1,123 +1,129 @@
|
||||
import {Colord, colord, random} from "colord";
|
||||
import {PlayerID, PlayerInfo, TerrainType, Tile} from "../game/Game";
|
||||
import {Theme} from "./Config";
|
||||
import {time} from "console";
|
||||
import {PseudoRandom} from "../PseudoRandom";
|
||||
import {simpleHash} from "../Util";
|
||||
import { Colord, colord, random } from "colord";
|
||||
import { PlayerID, PlayerInfo, TerrainType, Tile } from "../game/Game";
|
||||
import { Theme } from "./Config";
|
||||
import { time } from "console";
|
||||
import { PseudoRandom } from "../PseudoRandom";
|
||||
import { simpleHash } from "../Util";
|
||||
|
||||
export const pastelTheme = new class implements Theme {
|
||||
|
||||
|
||||
private rand = new PseudoRandom(123)
|
||||
|
||||
private background = colord({r: 60, g: 60, b: 60});
|
||||
private land = colord({r: 194, g: 193, b: 148});
|
||||
private shore = colord({r: 204, g: 203, b: 158});
|
||||
|
||||
private water = colord({r: 75, g: 142, b: 190});
|
||||
private shorelineWater = colord({r: 100, g: 143, b: 255});
|
||||
private background = colord({ r: 60, g: 60, b: 60 });
|
||||
private land = colord({ r: 194, g: 193, b: 148 });
|
||||
private shore = colord({ r: 204, g: 203, b: 158 });
|
||||
private falloutColors = [
|
||||
colord({ r: 120, g: 255, b: 71 }), // Original color
|
||||
colord({ r: 130, g: 255, b: 85 }), // Slightly lighter
|
||||
colord({ r: 110, g: 245, b: 65 }), // Slightly darker
|
||||
colord({ r: 125, g: 255, b: 75 }), // Warmer tint
|
||||
colord({ r: 115, g: 250, b: 68 }) // Cooler tint
|
||||
];
|
||||
private water = colord({ r: 75, g: 142, b: 190 });
|
||||
private shorelineWater = colord({ r: 100, g: 143, b: 255 });
|
||||
|
||||
private territoryColors: Colord[] = [
|
||||
colord({r: 230, g: 100, b: 100}), // Bright Red
|
||||
colord({r: 100, g: 180, b: 230}), // Sky Blue
|
||||
colord({r: 230, g: 180, b: 80}), // Golden Yellow
|
||||
colord({r: 180, g: 100, b: 230}), // Purple
|
||||
colord({r: 80, g: 200, b: 120}), // Emerald Green
|
||||
colord({r: 230, g: 130, b: 180}), // Pink
|
||||
colord({r: 100, g: 160, b: 80}), // Olive Green
|
||||
colord({r: 230, g: 150, b: 100}), // Peach
|
||||
colord({r: 80, g: 130, b: 190}), // Navy Blue
|
||||
colord({r: 210, g: 210, b: 100}), // Lime Yellow
|
||||
colord({r: 190, g: 100, b: 130}), // Maroon
|
||||
colord({r: 100, g: 210, b: 210}), // Turquoise
|
||||
colord({r: 210, g: 140, b: 80}), // Light Orange
|
||||
colord({r: 150, g: 110, b: 190}), // Lavender
|
||||
colord({r: 180, g: 210, b: 120}), // Light Green
|
||||
colord({r: 210, g: 100, b: 160}), // Hot Pink
|
||||
colord({r: 100, g: 140, b: 110}), // Sea Green
|
||||
colord({r: 230, g: 180, b: 180}), // Light Pink
|
||||
colord({r: 120, g: 120, b: 190}), // Periwinkle
|
||||
colord({r: 190, g: 170, b: 100}), // Sand
|
||||
colord({r: 100, g: 180, b: 160}), // Aquamarine
|
||||
colord({r: 210, g: 160, b: 200}), // Orchid
|
||||
colord({r: 170, g: 190, b: 100}), // Yellow Green
|
||||
colord({r: 100, g: 130, b: 150}), // Steel Blue
|
||||
colord({r: 230, g: 140, b: 140}), // Salmon
|
||||
colord({r: 140, g: 180, b: 220}), // Light Blue
|
||||
colord({r: 200, g: 160, b: 110}), // Tan
|
||||
colord({r: 180, g: 130, b: 180}), // Plum
|
||||
colord({r: 130, g: 200, b: 130}), // Light Sea Green
|
||||
colord({r: 220, g: 120, b: 120}), // Coral
|
||||
colord({r: 120, g: 160, b: 200}), // Cornflower Blue
|
||||
colord({r: 200, g: 200, b: 140}), // Khaki
|
||||
colord({r: 160, g: 120, b: 160}), // Purple Gray
|
||||
colord({r: 140, g: 180, b: 140}), // Dark Sea Green
|
||||
colord({r: 200, g: 130, b: 110}), // Dark Salmon
|
||||
colord({r: 130, g: 170, b: 190}), // Cadet Blue
|
||||
colord({r: 190, g: 180, b: 160}), // Tan Gray
|
||||
colord({r: 170, g: 140, b: 190}), // Medium Purple
|
||||
colord({r: 160, g: 190, b: 160}), // Pale Green
|
||||
colord({r: 190, g: 150, b: 130}), // Rosy Brown
|
||||
colord({r: 140, g: 150, b: 180}), // Light Slate Gray
|
||||
colord({r: 180, g: 170, b: 140}), // Dark Khaki
|
||||
colord({r: 150, g: 130, b: 150}), // Thistle
|
||||
colord({r: 170, g: 190, b: 180}), // Pale Blue Green
|
||||
colord({r: 190, g: 140, b: 150}), // Puce
|
||||
colord({r: 130, g: 180, b: 170}), // Medium Aquamarine
|
||||
colord({r: 180, g: 160, b: 180}), // Mauve
|
||||
colord({r: 160, g: 180, b: 140}), // Dark Olive Green
|
||||
colord({r: 170, g: 150, b: 170}), // Dusty Rose
|
||||
colord({r: 100, g: 180, b: 230}), // Sky Blue
|
||||
colord({r: 230, g: 180, b: 80}), // Golden Yellow
|
||||
colord({r: 180, g: 100, b: 230}), // Purple
|
||||
colord({r: 80, g: 200, b: 120}), // Emerald Green
|
||||
colord({r: 230, g: 130, b: 180}), // Pink
|
||||
colord({r: 100, g: 160, b: 80}), // Olive Green
|
||||
colord({r: 230, g: 150, b: 100}), // Peach
|
||||
colord({r: 80, g: 130, b: 190}), // Navy Blue
|
||||
colord({r: 210, g: 210, b: 100}), // Lime Yellow
|
||||
colord({r: 190, g: 100, b: 130}), // Maroon
|
||||
colord({r: 100, g: 210, b: 210}), // Turquoise
|
||||
colord({r: 210, g: 140, b: 80}), // Light Orange
|
||||
colord({r: 150, g: 110, b: 190}), // Lavender
|
||||
colord({r: 180, g: 210, b: 120}), // Light Green
|
||||
colord({r: 210, g: 100, b: 160}), // Hot Pink
|
||||
colord({r: 100, g: 140, b: 110}), // Sea Green
|
||||
colord({r: 230, g: 180, b: 180}), // Light Pink
|
||||
colord({r: 120, g: 120, b: 190}), // Periwinkle
|
||||
colord({r: 190, g: 170, b: 100}), // Sand
|
||||
colord({r: 100, g: 180, b: 160}), // Aquamarine
|
||||
colord({r: 210, g: 160, b: 200}), // Orchid
|
||||
colord({r: 170, g: 190, b: 100}), // Yellow Green
|
||||
colord({r: 100, g: 130, b: 150}), // Steel Blue
|
||||
colord({r: 230, g: 140, b: 140}), // Salmon
|
||||
colord({r: 140, g: 180, b: 220}), // Light Blue
|
||||
colord({r: 200, g: 160, b: 110}), // Tan
|
||||
colord({r: 180, g: 130, b: 180}), // Plum
|
||||
colord({r: 130, g: 200, b: 130}), // Light Sea Green
|
||||
colord({r: 220, g: 120, b: 120}), // Coral
|
||||
colord({r: 120, g: 160, b: 200}), // Cornflower Blue
|
||||
colord({r: 200, g: 200, b: 140}), // Khaki
|
||||
colord({r: 160, g: 120, b: 160}), // Purple Gray
|
||||
colord({r: 140, g: 180, b: 140}), // Dark Sea Green
|
||||
colord({r: 200, g: 130, b: 110}), // Dark Salmon
|
||||
colord({r: 130, g: 170, b: 190}), // Cadet Blue
|
||||
colord({r: 190, g: 180, b: 160}), // Tan Gray
|
||||
colord({r: 170, g: 140, b: 190}), // Medium Purple
|
||||
colord({r: 160, g: 190, b: 160}), // Pale Green
|
||||
colord({r: 190, g: 150, b: 130}), // Rosy Brown
|
||||
colord({r: 140, g: 150, b: 180}), // Light Slate Gray
|
||||
colord({r: 180, g: 170, b: 140}), // Dark Khaki
|
||||
colord({r: 150, g: 130, b: 150}), // Thistle
|
||||
colord({r: 170, g: 190, b: 180}), // Pale Blue Green
|
||||
colord({r: 190, g: 140, b: 150}), // Puce
|
||||
colord({r: 130, g: 180, b: 170}), // Medium Aquamarine
|
||||
colord({r: 180, g: 160, b: 180}), // Mauve
|
||||
colord({r: 160, g: 180, b: 140}), // Dark Olive Green
|
||||
colord({r: 170, g: 150, b: 170}) // Dusty Rose
|
||||
colord({ r: 230, g: 100, b: 100 }), // Bright Red
|
||||
colord({ r: 100, g: 180, b: 230 }), // Sky Blue
|
||||
colord({ r: 230, g: 180, b: 80 }), // Golden Yellow
|
||||
colord({ r: 180, g: 100, b: 230 }), // Purple
|
||||
colord({ r: 80, g: 200, b: 120 }), // Emerald Green
|
||||
colord({ r: 230, g: 130, b: 180 }), // Pink
|
||||
colord({ r: 100, g: 160, b: 80 }), // Olive Green
|
||||
colord({ r: 230, g: 150, b: 100 }), // Peach
|
||||
colord({ r: 80, g: 130, b: 190 }), // Navy Blue
|
||||
colord({ r: 210, g: 210, b: 100 }), // Lime Yellow
|
||||
colord({ r: 190, g: 100, b: 130 }), // Maroon
|
||||
colord({ r: 100, g: 210, b: 210 }), // Turquoise
|
||||
colord({ r: 210, g: 140, b: 80 }), // Light Orange
|
||||
colord({ r: 150, g: 110, b: 190 }), // Lavender
|
||||
colord({ r: 180, g: 210, b: 120 }), // Light Green
|
||||
colord({ r: 210, g: 100, b: 160 }), // Hot Pink
|
||||
colord({ r: 100, g: 140, b: 110 }), // Sea Green
|
||||
colord({ r: 230, g: 180, b: 180 }), // Light Pink
|
||||
colord({ r: 120, g: 120, b: 190 }), // Periwinkle
|
||||
colord({ r: 190, g: 170, b: 100 }), // Sand
|
||||
colord({ r: 100, g: 180, b: 160 }), // Aquamarine
|
||||
colord({ r: 210, g: 160, b: 200 }), // Orchid
|
||||
colord({ r: 170, g: 190, b: 100 }), // Yellow Green
|
||||
colord({ r: 100, g: 130, b: 150 }), // Steel Blue
|
||||
colord({ r: 230, g: 140, b: 140 }), // Salmon
|
||||
colord({ r: 140, g: 180, b: 220 }), // Light Blue
|
||||
colord({ r: 200, g: 160, b: 110 }), // Tan
|
||||
colord({ r: 180, g: 130, b: 180 }), // Plum
|
||||
colord({ r: 130, g: 200, b: 130 }), // Light Sea Green
|
||||
colord({ r: 220, g: 120, b: 120 }), // Coral
|
||||
colord({ r: 120, g: 160, b: 200 }), // Cornflower Blue
|
||||
colord({ r: 200, g: 200, b: 140 }), // Khaki
|
||||
colord({ r: 160, g: 120, b: 160 }), // Purple Gray
|
||||
colord({ r: 140, g: 180, b: 140 }), // Dark Sea Green
|
||||
colord({ r: 200, g: 130, b: 110 }), // Dark Salmon
|
||||
colord({ r: 130, g: 170, b: 190 }), // Cadet Blue
|
||||
colord({ r: 190, g: 180, b: 160 }), // Tan Gray
|
||||
colord({ r: 170, g: 140, b: 190 }), // Medium Purple
|
||||
colord({ r: 160, g: 190, b: 160 }), // Pale Green
|
||||
colord({ r: 190, g: 150, b: 130 }), // Rosy Brown
|
||||
colord({ r: 140, g: 150, b: 180 }), // Light Slate Gray
|
||||
colord({ r: 180, g: 170, b: 140 }), // Dark Khaki
|
||||
colord({ r: 150, g: 130, b: 150 }), // Thistle
|
||||
colord({ r: 170, g: 190, b: 180 }), // Pale Blue Green
|
||||
colord({ r: 190, g: 140, b: 150 }), // Puce
|
||||
colord({ r: 130, g: 180, b: 170 }), // Medium Aquamarine
|
||||
colord({ r: 180, g: 160, b: 180 }), // Mauve
|
||||
colord({ r: 160, g: 180, b: 140 }), // Dark Olive Green
|
||||
colord({ r: 170, g: 150, b: 170 }), // Dusty Rose
|
||||
colord({ r: 100, g: 180, b: 230 }), // Sky Blue
|
||||
colord({ r: 230, g: 180, b: 80 }), // Golden Yellow
|
||||
colord({ r: 180, g: 100, b: 230 }), // Purple
|
||||
colord({ r: 80, g: 200, b: 120 }), // Emerald Green
|
||||
colord({ r: 230, g: 130, b: 180 }), // Pink
|
||||
colord({ r: 100, g: 160, b: 80 }), // Olive Green
|
||||
colord({ r: 230, g: 150, b: 100 }), // Peach
|
||||
colord({ r: 80, g: 130, b: 190 }), // Navy Blue
|
||||
colord({ r: 210, g: 210, b: 100 }), // Lime Yellow
|
||||
colord({ r: 190, g: 100, b: 130 }), // Maroon
|
||||
colord({ r: 100, g: 210, b: 210 }), // Turquoise
|
||||
colord({ r: 210, g: 140, b: 80 }), // Light Orange
|
||||
colord({ r: 150, g: 110, b: 190 }), // Lavender
|
||||
colord({ r: 180, g: 210, b: 120 }), // Light Green
|
||||
colord({ r: 210, g: 100, b: 160 }), // Hot Pink
|
||||
colord({ r: 100, g: 140, b: 110 }), // Sea Green
|
||||
colord({ r: 230, g: 180, b: 180 }), // Light Pink
|
||||
colord({ r: 120, g: 120, b: 190 }), // Periwinkle
|
||||
colord({ r: 190, g: 170, b: 100 }), // Sand
|
||||
colord({ r: 100, g: 180, b: 160 }), // Aquamarine
|
||||
colord({ r: 210, g: 160, b: 200 }), // Orchid
|
||||
colord({ r: 170, g: 190, b: 100 }), // Yellow Green
|
||||
colord({ r: 100, g: 130, b: 150 }), // Steel Blue
|
||||
colord({ r: 230, g: 140, b: 140 }), // Salmon
|
||||
colord({ r: 140, g: 180, b: 220 }), // Light Blue
|
||||
colord({ r: 200, g: 160, b: 110 }), // Tan
|
||||
colord({ r: 180, g: 130, b: 180 }), // Plum
|
||||
colord({ r: 130, g: 200, b: 130 }), // Light Sea Green
|
||||
colord({ r: 220, g: 120, b: 120 }), // Coral
|
||||
colord({ r: 120, g: 160, b: 200 }), // Cornflower Blue
|
||||
colord({ r: 200, g: 200, b: 140 }), // Khaki
|
||||
colord({ r: 160, g: 120, b: 160 }), // Purple Gray
|
||||
colord({ r: 140, g: 180, b: 140 }), // Dark Sea Green
|
||||
colord({ r: 200, g: 130, b: 110 }), // Dark Salmon
|
||||
colord({ r: 130, g: 170, b: 190 }), // Cadet Blue
|
||||
colord({ r: 190, g: 180, b: 160 }), // Tan Gray
|
||||
colord({ r: 170, g: 140, b: 190 }), // Medium Purple
|
||||
colord({ r: 160, g: 190, b: 160 }), // Pale Green
|
||||
colord({ r: 190, g: 150, b: 130 }), // Rosy Brown
|
||||
colord({ r: 140, g: 150, b: 180 }), // Light Slate Gray
|
||||
colord({ r: 180, g: 170, b: 140 }), // Dark Khaki
|
||||
colord({ r: 150, g: 130, b: 150 }), // Thistle
|
||||
colord({ r: 170, g: 190, b: 180 }), // Pale Blue Green
|
||||
colord({ r: 190, g: 140, b: 150 }), // Puce
|
||||
colord({ r: 130, g: 180, b: 170 }), // Medium Aquamarine
|
||||
colord({ r: 180, g: 160, b: 180 }), // Mauve
|
||||
colord({ r: 160, g: 180, b: 140 }), // Dark Olive Green
|
||||
colord({ r: 170, g: 150, b: 170 }) // Dusty Rose
|
||||
];
|
||||
|
||||
playerInfoColor(id: PlayerID): Colord {
|
||||
return colord({r: 50, g: 50, b: 50})
|
||||
return colord({ r: 50, g: 50, b: 50 })
|
||||
}
|
||||
|
||||
territoryColor(playerInfo: PlayerInfo): Colord {
|
||||
@@ -186,6 +192,10 @@ export const pastelTheme = new class implements Theme {
|
||||
return this.background;
|
||||
}
|
||||
|
||||
falloutColor(): Colord {
|
||||
return this.rand.randElement(this.falloutColors)
|
||||
}
|
||||
|
||||
font(): string {
|
||||
return "Overpass, sans-serif";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
import { Cell, DefenseBonus, Execution, MutableGame, MutablePlayer, MutableUnit, PlayerID, Tile, UnitType } from "../game/Game";
|
||||
import { bfs, dist } from "../Util";
|
||||
|
||||
export class CityExecution implements Execution {
|
||||
|
||||
private player: MutablePlayer
|
||||
private mg: MutableGame
|
||||
private city: MutableUnit
|
||||
private tile: Tile
|
||||
private active: boolean = true
|
||||
|
||||
constructor(private ownerId: PlayerID, private cell: Cell) { }
|
||||
|
||||
init(mg: MutableGame, ticks: number): void {
|
||||
this.mg = mg
|
||||
this.tile = mg.tile(this.cell)
|
||||
this.player = mg.player(this.ownerId)
|
||||
}
|
||||
|
||||
tick(ticks: number): void {
|
||||
if (this.city == null) {
|
||||
const spawnTile = this.player.canBuild(UnitType.City, this.tile)
|
||||
if (spawnTile == false) {
|
||||
console.warn('cannot build Defense Post')
|
||||
this.active = false
|
||||
return
|
||||
}
|
||||
this.city = this.player.buildUnit(UnitType.City, 0, spawnTile)
|
||||
}
|
||||
if (!this.city.isActive()) {
|
||||
this.active = false
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
owner(): MutablePlayer {
|
||||
return null
|
||||
}
|
||||
|
||||
isActive(): boolean {
|
||||
return this.active
|
||||
}
|
||||
|
||||
activeDuringSpawnPhase(): boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import { BattleshipExecution } from "./BattleshipExecution";
|
||||
import { PathFinder } from "../pathfinding/PathFinding";
|
||||
import { WorkerClient } from "../worker/WorkerClient";
|
||||
import { DefensePostExecution } from "./DefensePostExecution";
|
||||
import { CityExecution } from "./CityExecution";
|
||||
|
||||
|
||||
|
||||
@@ -100,6 +101,8 @@ export class Executor {
|
||||
return new MissileSiloExecution(intent.player, new Cell(intent.x, intent.y))
|
||||
case UnitType.DefensePost:
|
||||
return new DefensePostExecution(intent.player, new Cell(intent.x, intent.y))
|
||||
case UnitType.City:
|
||||
return new CityExecution(intent.player, new Cell(intent.x, intent.y))
|
||||
default:
|
||||
throw Error(`unit type ${intent.unit} not supported`)
|
||||
}
|
||||
|
||||
@@ -83,6 +83,9 @@ export class NukeExecution implements Execution {
|
||||
mp.removeTroops(2 * ratio[mp.id()])
|
||||
others.add(mp)
|
||||
}
|
||||
if (tile.isLand()) {
|
||||
this.mg.addFallout(tile)
|
||||
}
|
||||
}
|
||||
for (const other of others) {
|
||||
const alliance = this.player.allianceWith(other)
|
||||
|
||||
@@ -39,7 +39,8 @@ export enum UnitType {
|
||||
HydrogenBomb = "Hydrogen Bomb",
|
||||
TradeShip = "Trade Ship",
|
||||
MissileSilo = "Missile Silo",
|
||||
DefensePost = "Defense Post"
|
||||
DefensePost = "Defense Post",
|
||||
City = "City"
|
||||
}
|
||||
|
||||
export class Nation {
|
||||
@@ -174,6 +175,7 @@ export interface Tile extends SearchNode {
|
||||
defenseBonuses(): DefenseBonus[]
|
||||
// defense bonus against this player
|
||||
defenseBonus(player: Player): number
|
||||
hasFallout(): boolean
|
||||
}
|
||||
|
||||
export interface Unit {
|
||||
@@ -314,6 +316,7 @@ export interface MutableGame extends Game {
|
||||
units(...types: UnitType[]): MutableUnit[]
|
||||
addTileDefenseBonus(tile: Tile, unit: Unit, amount: number): DefenseBonus
|
||||
removeTileDefenseBonus(bonus: DefenseBonus): void
|
||||
addFallout(tile: Tile)
|
||||
}
|
||||
|
||||
export class TileEvent implements GameEvent {
|
||||
|
||||
@@ -65,6 +65,15 @@ export class GameImpl implements MutableGame {
|
||||
})
|
||||
}
|
||||
|
||||
addFallout(tile: Tile) {
|
||||
const ti = tile as TileImpl
|
||||
if (tile.hasOwner()) {
|
||||
throw Error(`cannot set fallout, tile ${tile} has owner`)
|
||||
}
|
||||
ti._hasFallout = true
|
||||
this.eventBus.emit(new TileEvent(tile))
|
||||
}
|
||||
|
||||
addTileDefenseBonus(tile: Tile, unit: Unit, amount: number): DefenseBonus {
|
||||
const df = { unit: unit, tile: tile, amount: amount };
|
||||
(tile as TileImpl)._defenseBonuses.push(df)
|
||||
@@ -322,6 +331,7 @@ export class GameImpl implements MutableGame {
|
||||
tileImpl._owner = owner
|
||||
owner._tiles.set(tile.cell().toString(), tile)
|
||||
this.updateBorders(tile)
|
||||
tileImpl._hasFallout = false
|
||||
this.eventBus.emit(new TileEvent(tile))
|
||||
}
|
||||
|
||||
|
||||
@@ -372,6 +372,8 @@ export class PlayerImpl implements MutablePlayer {
|
||||
return this.transportShipSpawn(targetTile)
|
||||
case UnitType.TradeShip:
|
||||
return this.tradeShipSpawn(targetTile)
|
||||
case UnitType.City:
|
||||
return this.landBasedStructureSpawn(targetTile)
|
||||
default:
|
||||
assertNever(unitType)
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@ export class TileImpl implements Tile {
|
||||
|
||||
public _defenseBonuses: DefenseBonus[] = []
|
||||
|
||||
public _hasFallout = false
|
||||
|
||||
constructor(
|
||||
private readonly gs: GameImpl,
|
||||
public _owner: PlayerImpl | TerraNulliusImpl,
|
||||
@@ -20,6 +22,10 @@ export class TileImpl implements Tile {
|
||||
private readonly _terrain: TerrainTileImpl
|
||||
) { }
|
||||
|
||||
hasFallout(): boolean {
|
||||
return this._hasFallout
|
||||
}
|
||||
|
||||
terrainType(): TerrainType {
|
||||
return this._terrain.type
|
||||
}
|
||||
|
||||
@@ -74,9 +74,7 @@ export class GameManager {
|
||||
active.filter(g => !g.hasStarted() && g.isPublic).forEach(g => {
|
||||
g.start()
|
||||
})
|
||||
finished.forEach(g => {
|
||||
g.endGame()
|
||||
})
|
||||
finished.map(g => g.endGame()); // Fire and forget
|
||||
this.games = [...lobbies, ...active]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,9 @@ import { Config } from "../core/configuration/Config";
|
||||
import { Client } from "./Client";
|
||||
import WebSocket from 'ws';
|
||||
import { slog } from "./StructuredLog";
|
||||
import { Storage } from '@google-cloud/storage';
|
||||
|
||||
const storage = new Storage();
|
||||
|
||||
export enum GamePhase {
|
||||
Lobby = 'LOBBY',
|
||||
@@ -14,7 +16,7 @@ export enum GamePhase {
|
||||
export class GameServer {
|
||||
|
||||
|
||||
private maxGameDuration = 60 * 60 * 1000 // 1 hour
|
||||
private maxGameDuration = 2 * 60 * 60 * 1000 // 2 hours
|
||||
|
||||
private turns: Turn[] = []
|
||||
private intents: Intent[] = []
|
||||
@@ -135,7 +137,7 @@ export class GameServer {
|
||||
})
|
||||
}
|
||||
|
||||
endGame() {
|
||||
async endGame() {
|
||||
// Close all WebSocket connections
|
||||
clearInterval(this.endTurnIntervalID);
|
||||
this.clients.forEach(client => {
|
||||
@@ -144,6 +146,22 @@ export class GameServer {
|
||||
client.ws.close();
|
||||
}
|
||||
});
|
||||
try {
|
||||
if (this.turns.length > 100 && this.clients.length > 0) {
|
||||
const bucket = storage.bucket(this.config.gameStorageBucketName());
|
||||
const file = bucket.file(this.id);
|
||||
const game = {
|
||||
id: this.id,
|
||||
date: new Date().toISOString().split('T')[0],
|
||||
turns: this.turns
|
||||
}
|
||||
await file.save(JSON.stringify(game), {
|
||||
contentType: 'application/json'
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('error writing game to gcs: ' + error)
|
||||
}
|
||||
}
|
||||
|
||||
phase(): GamePhase {
|
||||
|
||||
Reference in New Issue
Block a user