mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-07-01 01:23:25 +00:00
proto
This commit is contained in:
Generated
+93
-33
@@ -43,6 +43,7 @@
|
||||
"@babel/core": "^7.25.2",
|
||||
"@babel/preset-env": "^7.25.3",
|
||||
"@babel/preset-typescript": "^7.24.7",
|
||||
"@bufbuild/protobuf": "^2.10.2",
|
||||
"@datastructures-js/priority-queue": "^6.3.3",
|
||||
"@eslint/compat": "^1.2.7",
|
||||
"@eslint/js": "^9.21.0",
|
||||
@@ -105,6 +106,7 @@
|
||||
"style-loader": "^4.0.0",
|
||||
"tailwindcss": "^3.4.17",
|
||||
"ts-loader": "^9.5.2",
|
||||
"ts-proto": "^2.8.3",
|
||||
"tsconfig-paths": "^4.2.0",
|
||||
"tsx": "^4.17.0",
|
||||
"typescript": "^5.7.2",
|
||||
@@ -1049,7 +1051,6 @@
|
||||
"integrity": "sha512-bXYxrXFubeYdvB0NhD/NBB3Qi6aZeV20GOWVI47t2dkecCEoneR4NPVcb7abpXDEvejgrUfFtG6vG/zxAKmg+g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@ampproject/remapping": "^2.2.0",
|
||||
"@babel/code-frame": "^7.27.1",
|
||||
@@ -2803,6 +2804,13 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@bufbuild/protobuf": {
|
||||
"version": "2.10.2",
|
||||
"resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.10.2.tgz",
|
||||
"integrity": "sha512-uFsRXwIGyu+r6AMdz+XijIIZJYpoWeYzILt5yZ2d3mCjQrWUTVpVD9WL/jZAbvp+Ed04rOhrsk7FiTcEDseB5A==",
|
||||
"dev": true,
|
||||
"license": "(Apache-2.0 AND BSD-3-Clause)"
|
||||
},
|
||||
"node_modules/@colors/colors": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz",
|
||||
@@ -2922,7 +2930,6 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
@@ -2946,7 +2953,6 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
@@ -5101,7 +5107,6 @@
|
||||
"resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz",
|
||||
"integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
}
|
||||
@@ -6420,6 +6425,7 @@
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
@@ -6436,6 +6442,7 @@
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
@@ -6452,6 +6459,7 @@
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
@@ -6468,6 +6476,7 @@
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
@@ -6484,6 +6493,7 @@
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
@@ -6500,6 +6510,7 @@
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
@@ -6516,6 +6527,7 @@
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
@@ -6532,6 +6544,7 @@
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
@@ -6548,6 +6561,7 @@
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
@@ -6564,6 +6578,7 @@
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
@@ -6599,6 +6614,7 @@
|
||||
"integrity": "sha512-u1iIVZV9Q0jxY+yM2vw/hZGDNudsN85bBpTqzAQ9rzkxW9D+e3aEM4Han+ow518gSewkXgjmEK0BD79ZcNVgPw==",
|
||||
"devOptional": true,
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@swc/counter": "^0.1.3"
|
||||
}
|
||||
@@ -7253,7 +7269,6 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.32.tgz",
|
||||
"integrity": "sha512-3jigKqgSjsH6gYZv2nEsqdXfZqIFGAV36XYYjf9KGZ3PSG+IhLecqPnI310RvjutyMwifE2hhhNEklOUrvx/wA==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"undici-types": "~6.21.0"
|
||||
}
|
||||
@@ -7488,7 +7503,6 @@
|
||||
"integrity": "sha512-4O3idHxhyzjClSMJ0a29AcoK0+YwnEqzI6oz3vlRf3xw0zbzt15MzXwItOlnr5nIth6zlY2RENLsOPvhyrKAQA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "8.34.1",
|
||||
"@typescript-eslint/types": "8.34.1",
|
||||
@@ -8259,7 +8273,6 @@
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
|
||||
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
@@ -8318,7 +8331,6 @@
|
||||
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
@@ -8884,7 +8896,6 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"caniuse-lite": "^1.0.30001718",
|
||||
"electron-to-chromium": "^1.5.160",
|
||||
@@ -9063,7 +9074,6 @@
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"node-addon-api": "^7.0.0",
|
||||
"prebuild-install": "^7.1.1"
|
||||
@@ -9079,13 +9089,25 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/case-anything": {
|
||||
"version": "2.1.13",
|
||||
"resolved": "https://registry.npmjs.org/case-anything/-/case-anything-2.1.13.tgz",
|
||||
"integrity": "sha512-zlOQ80VrQ2Ue+ymH5OuM/DlDq64mEm+B9UTdHULv5osUMD6HalNTblf2b1u/m6QecjsnOkBpqVZ+XPwIVsy7Ng==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12.13"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/mesqueeb"
|
||||
}
|
||||
},
|
||||
"node_modules/chai": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/chai/-/chai-5.2.0.tgz",
|
||||
"integrity": "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"assertion-error": "^2.0.1",
|
||||
"check-error": "^2.1.1",
|
||||
@@ -9690,7 +9712,6 @@
|
||||
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"fast-uri": "^3.0.1",
|
||||
@@ -10278,7 +10299,6 @@
|
||||
"integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
@@ -10739,6 +10759,29 @@
|
||||
"url": "https://dotenvx.com"
|
||||
}
|
||||
},
|
||||
"node_modules/dprint-node": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/dprint-node/-/dprint-node-1.0.8.tgz",
|
||||
"integrity": "sha512-iVKnUtYfGrYcW1ZAlfR/F59cUVL8QIhWoBJoSjkkdua/dkWIgjZfiLMeTjiB06X0ZLkQ0M2C1VbUj/CxkIf1zg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"detect-libc": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/dprint-node/node_modules/detect-libc": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
|
||||
"integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"detect-libc": "bin/detect-libc.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/dunder-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||
@@ -11021,7 +11064,6 @@
|
||||
"integrity": "sha512-GsGizj2Y1rCWDu6XoEekL3RLilp0voSePurjZIkxL3wlm5o5EC9VpgaP7lrCvjnkuLvzFBQWB3vWB3K5KQTveQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.2.0",
|
||||
"@eslint-community/regexpp": "^4.12.1",
|
||||
@@ -11191,7 +11233,6 @@
|
||||
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"fast-uri": "^3.0.1",
|
||||
@@ -11550,7 +11591,6 @@
|
||||
"resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz",
|
||||
"integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"accepts": "~1.3.8",
|
||||
"array-flatten": "1.1.1",
|
||||
@@ -12451,7 +12491,6 @@
|
||||
"integrity": "sha512-QSf1yjtSAsmf7rYBV7XX86uua4W/vkhIt0xNXKbsi2foEeW7vjJQz4bhnpL3xH+l1ryl1680uNv968Z+X6jSYg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/html-minifier-terser": "^6.0.0",
|
||||
"html-minifier-terser": "^6.0.2",
|
||||
@@ -14981,7 +15020,6 @@
|
||||
"integrity": "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"cssstyle": "^4.2.1",
|
||||
"data-urls": "^5.0.0",
|
||||
@@ -16695,7 +16733,6 @@
|
||||
"integrity": "sha512-dyuThzncsgEgJZnvd/A/5x6IkUERbK+phXqUQrI+0C6WE+8xqGH5VChRTLecemhgZF0kQ+gZOM3tJTX9937xpg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@pixi/colord": "^2.9.6",
|
||||
"@types/css-font-loading-module": "^0.0.12",
|
||||
@@ -16753,7 +16790,6 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"nanoid": "^3.3.11",
|
||||
"picocolors": "^1.1.1",
|
||||
@@ -17092,7 +17128,6 @@
|
||||
"integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"prettier": "bin/prettier.cjs"
|
||||
},
|
||||
@@ -18362,7 +18397,6 @@
|
||||
"integrity": "sha512-TOgRcwFPbfGtpqvZw+hyqJDvqfapr1qUlOizROIk4bBLjlsjlB00Pg6wMFXNtJRpu+eCZuVOaLatG7M8105kAw==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@sinonjs/commons": "^3.0.1",
|
||||
"@sinonjs/fake-timers": "^13.0.5",
|
||||
@@ -19075,7 +19109,6 @@
|
||||
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"fast-uri": "^3.0.1",
|
||||
@@ -19307,7 +19340,6 @@
|
||||
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
@@ -19495,7 +19527,6 @@
|
||||
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
|
||||
"integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@cspotcode/source-map-support": "^0.8.0",
|
||||
"@tsconfig/node10": "^1.0.7",
|
||||
@@ -19549,6 +19580,42 @@
|
||||
"node": ">=0.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-poet": {
|
||||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/ts-poet/-/ts-poet-6.12.0.tgz",
|
||||
"integrity": "sha512-xo+iRNMWqyvXpFTaOAvLPA5QAWO6TZrSUs5s4Odaya3epqofBu/fMLHEWl8jPmjhA0s9sgj9sNvF1BmaQlmQkA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"dprint-node": "^1.0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-proto": {
|
||||
"version": "2.8.3",
|
||||
"resolved": "https://registry.npmjs.org/ts-proto/-/ts-proto-2.8.3.tgz",
|
||||
"integrity": "sha512-TdXInqG+61pj/TvORqITWjvjTTsL1EZxwX49iEj89+xFAcqPT8tjChpAGQXzfcF4MJwvNiuoCEbBOKqVf3ds3g==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@bufbuild/protobuf": "^2.0.0",
|
||||
"case-anything": "^2.1.13",
|
||||
"ts-poet": "^6.12.0",
|
||||
"ts-proto-descriptors": "2.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"protoc-gen-ts_proto": "protoc-gen-ts_proto"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-proto-descriptors": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ts-proto-descriptors/-/ts-proto-descriptors-2.0.0.tgz",
|
||||
"integrity": "sha512-wHcTH3xIv11jxgkX5OyCSFfw27agpInAd6yh89hKG6zqIXnjW9SYqSER2CVQxdPj4czeOhGagNvZBEbJPy7qkw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@bufbuild/protobuf": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tsconfig-paths": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz",
|
||||
@@ -19578,8 +19645,7 @@
|
||||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||
"license": "0BSD",
|
||||
"peer": true
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/tsx": {
|
||||
"version": "4.20.3",
|
||||
@@ -19668,7 +19734,6 @@
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
|
||||
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
@@ -19963,7 +20028,6 @@
|
||||
"integrity": "sha512-QaNKAvGCDRh3wW1dsDjeMdDXwZm2vqq3zn6Pvq4rHOEOGSaUMgOOjG2Y9ZbIGzpfkJk9ZYTHpDqgDfeBDcnLaw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/eslint-scope": "^3.7.7",
|
||||
"@types/estree": "^1.0.8",
|
||||
@@ -20013,7 +20077,6 @@
|
||||
"integrity": "sha512-MfwFQ6SfwinsUVi0rNJm7rHZ31GyTcpVE5pgVA3hwFRb7COD4TzjUUwhGWKfO50+xdc2MQPuEBBJoqIMGt3JDw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@discoveryjs/json-ext": "^0.6.1",
|
||||
"@webpack-cli/configtest": "^3.0.1",
|
||||
@@ -20097,7 +20160,6 @@
|
||||
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"fast-uri": "^3.0.1",
|
||||
@@ -20213,7 +20275,6 @@
|
||||
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"fast-uri": "^3.0.1",
|
||||
@@ -20306,7 +20367,6 @@
|
||||
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"fast-uri": "^3.0.1",
|
||||
|
||||
+4
-1
@@ -18,7 +18,8 @@
|
||||
"lint": "eslint",
|
||||
"lint:fix": "eslint --fix",
|
||||
"prepare": "husky",
|
||||
"gen-maps": "cd map-generator && go run . && npm run format"
|
||||
"gen-maps": "cd map-generator && go run . && npm run format",
|
||||
"gen-proto": "npx protoc --plugin=./node_modules/.bin/protoc-gen-ts_proto --ts_proto_out=. src/core/game/GameUpdates.proto --ts_proto_opt=unrecognizedEnum=false"
|
||||
},
|
||||
"lint-staged": {
|
||||
"**/*": [
|
||||
@@ -30,6 +31,7 @@
|
||||
"@babel/core": "^7.25.2",
|
||||
"@babel/preset-env": "^7.25.3",
|
||||
"@babel/preset-typescript": "^7.24.7",
|
||||
"@bufbuild/protobuf": "^2.10.2",
|
||||
"@datastructures-js/priority-queue": "^6.3.3",
|
||||
"@eslint/compat": "^1.2.7",
|
||||
"@eslint/js": "^9.21.0",
|
||||
@@ -92,6 +94,7 @@
|
||||
"style-loader": "^4.0.0",
|
||||
"tailwindcss": "^3.4.17",
|
||||
"ts-loader": "^9.5.2",
|
||||
"ts-proto": "^2.8.3",
|
||||
"tsconfig-paths": "^4.2.0",
|
||||
"tsx": "^4.17.0",
|
||||
"typescript": "^5.7.2",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { translateText } from "../client/Utils";
|
||||
import { EventBus } from "../core/EventBus";
|
||||
import {
|
||||
AllPlayersStats,
|
||||
ClientID,
|
||||
GameID,
|
||||
GameRecord,
|
||||
@@ -8,18 +9,19 @@ import {
|
||||
PlayerCosmeticRefs,
|
||||
PlayerRecord,
|
||||
ServerMessage,
|
||||
Winner,
|
||||
} from "../core/Schemas";
|
||||
import { createPartialGameRecord, replacer } from "../core/Util";
|
||||
import { ServerConfig } from "../core/configuration/Config";
|
||||
import { getConfig } from "../core/configuration/ConfigLoader";
|
||||
import { PlayerActions, UnitType } from "../core/game/Game";
|
||||
import { PlayerActions } from "../core/game/Game";
|
||||
import { TileRef } from "../core/game/GameMap";
|
||||
import { GameMapLoader } from "../core/game/GameMapLoader";
|
||||
import {
|
||||
ErrorUpdate,
|
||||
GameUpdateType,
|
||||
GameUpdateViewData,
|
||||
HashUpdate,
|
||||
UnitType,
|
||||
WinUpdate,
|
||||
} from "../core/game/GameUpdates";
|
||||
import { GameView, PlayerView } from "../core/game/GameView";
|
||||
@@ -241,18 +243,20 @@ export class ClientGameRunner {
|
||||
if (this.myPlayer === null) {
|
||||
return;
|
||||
}
|
||||
const stats = JSON.parse(update.stats) as AllPlayersStats;
|
||||
const players: PlayerRecord[] = [
|
||||
{
|
||||
persistentID: getPersistentID(),
|
||||
username: this.lobby.playerName,
|
||||
clientID: this.lobby.clientID,
|
||||
stats: update.allPlayersStats[this.lobby.clientID],
|
||||
stats: stats[this.lobby.clientID],
|
||||
},
|
||||
];
|
||||
|
||||
if (this.lobby.gameStartInfo === undefined) {
|
||||
throw new Error("missing gameStartInfo");
|
||||
}
|
||||
const winner = JSON.parse(update.winner) as Winner;
|
||||
const record = createPartialGameRecord(
|
||||
this.lobby.gameStartInfo.gameID,
|
||||
this.lobby.gameStartInfo.config,
|
||||
@@ -261,7 +265,7 @@ export class ClientGameRunner {
|
||||
[],
|
||||
startTime(),
|
||||
Date.now(),
|
||||
update.winner,
|
||||
winner,
|
||||
this.lobby.gameStartInfo.lobbyCreatedAt,
|
||||
);
|
||||
endGame(record);
|
||||
@@ -310,8 +314,10 @@ export class ClientGameRunner {
|
||||
return;
|
||||
}
|
||||
this.transport.turnComplete();
|
||||
gu.updates[GameUpdateType.Hash].forEach((hu: HashUpdate) => {
|
||||
this.eventBus.emit(new SendHashEvent(hu.tick, hu.hash));
|
||||
gu.updates[GameUpdateType.Hash].updates.forEach((update) => {
|
||||
this.eventBus.emit(
|
||||
new SendHashEvent(update.hash!.tick, update.hash!.hash),
|
||||
);
|
||||
});
|
||||
this.gameView.update(gu);
|
||||
this.renderer.tick();
|
||||
@@ -324,7 +330,7 @@ export class ClientGameRunner {
|
||||
// Reset tick delay for next measurement
|
||||
this.currentTickDelay = undefined;
|
||||
|
||||
if (gu.updates[GameUpdateType.Win].length > 0) {
|
||||
if (gu.updates[GameUpdateType.Win]?.updates.length > 0) {
|
||||
this.saveGame(gu.updates[GameUpdateType.Win][0]);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -12,9 +12,9 @@ import {
|
||||
HumansVsNations,
|
||||
Quads,
|
||||
Trios,
|
||||
UnitType,
|
||||
mapCategories,
|
||||
} from "../core/game/Game";
|
||||
import { UnitType } from "../core/game/GameUpdates";
|
||||
import { UserSettings } from "../core/game/UserSettings";
|
||||
import {
|
||||
ClientInfo,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { EventBus, GameEvent } from "../core/EventBus";
|
||||
import { UnitType } from "../core/game/Game";
|
||||
import { UnitType } from "../core/game/GameUpdates";
|
||||
import { UnitView } from "../core/game/GameView";
|
||||
import { UserSettings } from "../core/game/UserSettings";
|
||||
import { UIState } from "./graphics/UIState";
|
||||
|
||||
@@ -12,9 +12,9 @@ import {
|
||||
HumansVsNations,
|
||||
Quads,
|
||||
Trios,
|
||||
UnitType,
|
||||
mapCategories,
|
||||
} from "../core/game/Game";
|
||||
import { UnitType } from "../core/game/GameUpdates";
|
||||
import { UserSettings } from "../core/game/UserSettings";
|
||||
import { TeamCountConfig } from "../core/Schemas";
|
||||
import { generateID } from "../core/Util";
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
import { z } from "zod";
|
||||
import { EventBus, GameEvent } from "../core/EventBus";
|
||||
import {
|
||||
AllPlayers,
|
||||
GameType,
|
||||
Gold,
|
||||
PlayerID,
|
||||
Tick,
|
||||
UnitType,
|
||||
} from "../core/game/Game";
|
||||
import { AllPlayers, GameType, Gold, PlayerID, Tick } from "../core/game/Game";
|
||||
import { TileRef } from "../core/game/GameMap";
|
||||
import { UnitType } from "../core/game/GameUpdates";
|
||||
import { PlayerView } from "../core/game/GameView";
|
||||
import {
|
||||
AllPlayersStats,
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import IntlMessageFormat from "intl-messageformat";
|
||||
import { MessageType } from "../core/game/Game";
|
||||
import { MessageType } from "../core/game/GameUpdates";
|
||||
import { LangSelector } from "./LangSelector";
|
||||
|
||||
export function renderDuration(totalSeconds: number): string {
|
||||
|
||||
@@ -8,11 +8,11 @@ import {
|
||||
GameMode,
|
||||
HumansVsNations,
|
||||
PlayerInfo,
|
||||
PlayerType,
|
||||
Quads,
|
||||
Team,
|
||||
Trios,
|
||||
} from "../../core/game/Game";
|
||||
import { PlayerType } from "../../core/game/GameUpdates";
|
||||
import { assignTeamsLobbyPreview } from "../../core/game/TeamAssignment";
|
||||
import { ClientInfo, TeamCountConfig } from "../../core/Schemas";
|
||||
import { translateText } from "../Utils";
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Cell, Game, NameViewData, Player } from "../../core/game/Game";
|
||||
import { Cell, Game, Player } from "../../core/game/Game";
|
||||
import { NameViewData } from "../../core/game/GameUpdates";
|
||||
import { calculateBoundingBox } from "../../core/Util";
|
||||
|
||||
export interface Point {
|
||||
|
||||
@@ -11,7 +11,7 @@ import nukeWhiteIcon from "../../../resources/images/NukeIconWhite.svg";
|
||||
import questionMarkIcon from "../../../resources/images/QuestionMarkIcon.svg";
|
||||
import targetIcon from "../../../resources/images/TargetIcon.svg";
|
||||
import traitorIcon from "../../../resources/images/TraitorIcon.svg";
|
||||
import { AllPlayers, nukeTypes } from "../../core/game/Game";
|
||||
import { nukeTypes } from "../../core/game/Game";
|
||||
import { GameView, PlayerView } from "../../core/game/GameView";
|
||||
|
||||
export type PlayerIconId =
|
||||
@@ -114,15 +114,14 @@ export function getPlayerIcons(
|
||||
.outgoingEmojis()
|
||||
.filter(
|
||||
(emoji) =>
|
||||
emoji.recipientID === AllPlayers ||
|
||||
emoji.recipientID === myPlayer?.smallID(),
|
||||
emoji.allPlayers ?? emoji.recipientId === myPlayer?.smallID(),
|
||||
);
|
||||
|
||||
if (emojis.length > 0) {
|
||||
icons.push({
|
||||
id: "emoji",
|
||||
kind: "emoji",
|
||||
text: emojis[0].message,
|
||||
text: emojis[0].emoji,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import trainEngineSprite from "../../../resources/sprites/trainEngine.png";
|
||||
import transportShipSprite from "../../../resources/sprites/transportship.png";
|
||||
import warshipSprite from "../../../resources/sprites/warship.png";
|
||||
import { Theme } from "../../core/configuration/Config";
|
||||
import { TrainType, UnitType } from "../../core/game/Game";
|
||||
import { TrainType, UnitType } from "../../core/game/GameUpdates";
|
||||
import { UnitView } from "../../core/game/GameView";
|
||||
|
||||
// Can't reuse TrainType because "loaded" is not a type, just an attribute
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { UnitType } from "../../core/game/Game";
|
||||
import { UnitType } from "../../core/game/GameUpdates";
|
||||
|
||||
export interface UIState {
|
||||
attackRatio: number;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ConquestUpdate } from "../../../core/game/GameUpdates";
|
||||
import { GameView } from "../../../core/game/GameView";
|
||||
import { GameView, PlayerView } from "../../../core/game/GameView";
|
||||
import { renderNumber } from "../../Utils";
|
||||
import { AnimatedSpriteLoader } from "../AnimatedSpriteLoader";
|
||||
import { Fx, FxType } from "./Fx";
|
||||
@@ -17,7 +17,7 @@ export function conquestFxFactory(
|
||||
game: GameView,
|
||||
): Fx[] {
|
||||
const conquestFx: Fx[] = [];
|
||||
const conquered = game.player(conquest.conqueredId);
|
||||
const conquered = game.playerBySmallID(conquest.conqueredId) as PlayerView;
|
||||
const x = conquered.nameLocation().x;
|
||||
const y = conquered.nameLocation().y;
|
||||
|
||||
|
||||
@@ -108,8 +108,8 @@ export class AlertFrame extends LitElement implements Layer {
|
||||
// Check for BrokeAllianceUpdate events
|
||||
this.game
|
||||
.updatesSinceLastTick()
|
||||
?.[GameUpdateType.BrokeAlliance]?.forEach((update) => {
|
||||
this.onBrokeAllianceUpdate(update as BrokeAllianceUpdate);
|
||||
?.[GameUpdateType.BrokeAlliance]?.updates.forEach((update) => {
|
||||
this.onBrokeAllianceUpdate(update.brokeAlliance!);
|
||||
});
|
||||
|
||||
// Check for new incoming attacks
|
||||
@@ -125,7 +125,7 @@ export class AlertFrame extends LitElement implements Layer {
|
||||
const myPlayer = this.game.myPlayer();
|
||||
if (!myPlayer) return;
|
||||
|
||||
const betrayed = this.game.playerBySmallID(update.betrayedID);
|
||||
const betrayed = this.game.playerBySmallID(update.betrayedId);
|
||||
|
||||
// Only trigger alert if the current player is the betrayed one
|
||||
if (betrayed === myPlayer) {
|
||||
@@ -154,8 +154,8 @@ export class AlertFrame extends LitElement implements Layer {
|
||||
// Track when we attack other players (not terra nullius)
|
||||
for (const attack of outgoingAttacks) {
|
||||
// Only track attacks on players (targetID !== 0 means it's a player, not unclaimed land)
|
||||
if (attack.targetID !== 0 && !attack.retreating) {
|
||||
const existingTick = this.outgoingAttackTicks.get(attack.targetID);
|
||||
if (attack.targetId !== 0 && !attack.retreating) {
|
||||
const existingTick = this.outgoingAttackTicks.get(attack.targetId);
|
||||
|
||||
// Only update timestamp if:
|
||||
// 1. This is a new attack (not in map yet), OR
|
||||
@@ -164,7 +164,7 @@ export class AlertFrame extends LitElement implements Layer {
|
||||
existingTick === undefined ||
|
||||
currentTick - existingTick >= RETALIATION_WINDOW_TICKS
|
||||
) {
|
||||
this.outgoingAttackTicks.set(attack.targetID, currentTick);
|
||||
this.outgoingAttackTicks.set(attack.targetId, currentTick);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -199,7 +199,7 @@ export class AlertFrame extends LitElement implements Layer {
|
||||
// Only alert for non-retreating attacks
|
||||
if (!attack.retreating && !this.seenAttackIds.has(attack.id)) {
|
||||
// Check if this is a retaliation (we attacked them recently)
|
||||
const ourAttackTick = this.outgoingAttackTicks.get(attack.attackerID);
|
||||
const ourAttackTick = this.outgoingAttackTicks.get(attack.attackerId);
|
||||
const isRetaliation =
|
||||
ourAttackTick !== undefined &&
|
||||
currentTick - ourAttackTick < RETALIATION_WINDOW_TICKS;
|
||||
|
||||
@@ -13,13 +13,9 @@ import samlauncherIcon from "../../../../resources/images/SamLauncherIconWhite.s
|
||||
import shieldIcon from "../../../../resources/images/ShieldIconWhite.svg";
|
||||
import { translateText } from "../../../client/Utils";
|
||||
import { EventBus } from "../../../core/EventBus";
|
||||
import {
|
||||
BuildableUnit,
|
||||
Gold,
|
||||
PlayerActions,
|
||||
UnitType,
|
||||
} from "../../../core/game/Game";
|
||||
import { BuildableUnit, Gold, PlayerActions } from "../../../core/game/Game";
|
||||
import { TileRef } from "../../../core/game/GameMap";
|
||||
import { UnitType } from "../../../core/game/GameUpdates";
|
||||
import { GameView } from "../../../core/game/GameView";
|
||||
import {
|
||||
CloseViewEvent,
|
||||
|
||||
@@ -3,10 +3,10 @@ import { customElement, state } from "lit/decorators.js";
|
||||
import { DirectiveResult } from "lit/directive.js";
|
||||
import { unsafeHTML, UnsafeHTMLDirective } from "lit/directives/unsafe-html.js";
|
||||
import { EventBus } from "../../../core/EventBus";
|
||||
import { MessageType } from "../../../core/game/Game";
|
||||
import {
|
||||
DisplayMessageUpdate,
|
||||
GameUpdateType,
|
||||
MessageType,
|
||||
} from "../../../core/game/GameUpdates";
|
||||
import { GameView } from "../../../core/game/GameView";
|
||||
import { onlyImages } from "../../../core/Util";
|
||||
@@ -57,8 +57,8 @@ export class ChatDisplay extends LitElement implements Layer {
|
||||
if (event.messageType !== MessageType.CHAT) return;
|
||||
const myPlayer = this.game.myPlayer();
|
||||
if (
|
||||
event.playerID !== null &&
|
||||
(!myPlayer || myPlayer.smallID() !== event.playerID)
|
||||
event.playerId !== null &&
|
||||
(!myPlayer || myPlayer.smallID() !== event.playerId)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
@@ -76,31 +76,26 @@ export class ChatDisplay extends LitElement implements Layer {
|
||||
tick() {
|
||||
// this.active = true;
|
||||
const updates = this.game.updatesSinceLastTick();
|
||||
if (updates === null) return;
|
||||
const messages = updates[GameUpdateType.DisplayEvent] as
|
||||
| DisplayMessageUpdate[]
|
||||
| undefined;
|
||||
|
||||
if (messages) {
|
||||
for (const msg of messages) {
|
||||
if (msg.messageType === MessageType.CHAT) {
|
||||
const myPlayer = this.game.myPlayer();
|
||||
if (
|
||||
msg.playerID !== null &&
|
||||
(!myPlayer || myPlayer.smallID() !== msg.playerID)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
this.chatEvents = [
|
||||
...this.chatEvents,
|
||||
{
|
||||
description: msg.message,
|
||||
unsafeDescription: true,
|
||||
createdAt: this.game.ticks(),
|
||||
},
|
||||
];
|
||||
for (const update of updates?.[GameUpdateType.DisplayEvent]?.updates ??
|
||||
[]) {
|
||||
const msg = update.displayMessage!;
|
||||
if (msg.messageType === MessageType.CHAT) {
|
||||
const myPlayer = this.game.myPlayer();
|
||||
if (
|
||||
msg.playerId !== null &&
|
||||
(!myPlayer || myPlayer.smallID() !== msg.playerId)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
this.chatEvents = [
|
||||
...this.chatEvents,
|
||||
{
|
||||
description: msg.message,
|
||||
unsafeDescription: true,
|
||||
createdAt: this.game.ticks(),
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { LitElement, html } from "lit";
|
||||
import { customElement, query } from "lit/decorators.js";
|
||||
|
||||
import { PlayerType } from "../../../core/game/Game";
|
||||
import { PlayerType } from "../../../core/game/GameUpdates";
|
||||
import { GameView, PlayerView } from "../../../core/game/GameView";
|
||||
|
||||
import quickChatData from "../../../../resources/QuickChat.json";
|
||||
|
||||
@@ -8,15 +8,7 @@ import donateGoldIcon from "../../../../resources/images/DonateGoldIconWhite.svg
|
||||
import nukeIcon from "../../../../resources/images/NukeIconWhite.svg";
|
||||
import swordIcon from "../../../../resources/images/SwordIconWhite.svg";
|
||||
import { EventBus } from "../../../core/EventBus";
|
||||
import {
|
||||
AllPlayers,
|
||||
getMessageCategory,
|
||||
MessageCategory,
|
||||
MessageType,
|
||||
PlayerType,
|
||||
Tick,
|
||||
UnitType,
|
||||
} from "../../../core/game/Game";
|
||||
import { AllPlayers, getMessageCategory, Tick } from "../../../core/game/Game";
|
||||
import {
|
||||
AllianceExpiredUpdate,
|
||||
AllianceRequestReplyUpdate,
|
||||
@@ -27,8 +19,12 @@ import {
|
||||
DisplayMessageUpdate,
|
||||
EmojiUpdate,
|
||||
GameUpdateType,
|
||||
MessageCategory,
|
||||
MessageType,
|
||||
PlayerType,
|
||||
TargetPlayerUpdate,
|
||||
UnitIncomingUpdate,
|
||||
UnitType,
|
||||
} from "../../../core/game/GameUpdates";
|
||||
import {
|
||||
CancelAttackIntentEvent,
|
||||
@@ -96,7 +92,7 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
[MessageCategory.NUKE, false],
|
||||
[MessageCategory.TRADE, false],
|
||||
[MessageCategory.ALLIANCE, false],
|
||||
[MessageCategory.CHAT, false],
|
||||
[MessageCategory.CHAT_CATEGORY, false],
|
||||
]);
|
||||
|
||||
@query(".events-container")
|
||||
@@ -228,7 +224,7 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
const updates = this.game.updatesSinceLastTick();
|
||||
if (updates) {
|
||||
for (const [ut, fn] of this.updateMap) {
|
||||
updates[ut]?.forEach(fn as (event: unknown) => void);
|
||||
updates[ut]?.updates.forEach(fn as (event: unknown) => void);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,17 +249,17 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
|
||||
// Update attacks
|
||||
this.incomingAttacks = myPlayer.incomingAttacks().filter((a) => {
|
||||
const t = (this.game.playerBySmallID(a.attackerID) as PlayerView).type();
|
||||
const t = (this.game.playerBySmallID(a.attackerId) as PlayerView).type();
|
||||
return t !== PlayerType.Bot;
|
||||
});
|
||||
|
||||
this.outgoingAttacks = myPlayer
|
||||
.outgoingAttacks()
|
||||
.filter((a) => a.targetID !== 0);
|
||||
.filter((a) => a.targetId !== 0);
|
||||
|
||||
this.outgoingLandAttacks = myPlayer
|
||||
.outgoingAttacks()
|
||||
.filter((a) => a.targetID === 0);
|
||||
.filter((a) => a.targetId === 0);
|
||||
|
||||
this.outgoingBoats = myPlayer
|
||||
.units()
|
||||
@@ -362,15 +358,15 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
onDisplayMessageEvent(event: DisplayMessageUpdate) {
|
||||
const myPlayer = this.game.myPlayer();
|
||||
if (
|
||||
event.playerID !== null &&
|
||||
(!myPlayer || myPlayer.smallID() !== event.playerID)
|
||||
event.playerId !== null &&
|
||||
(!myPlayer || myPlayer.smallID() !== event.playerId)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.goldAmount !== undefined) {
|
||||
const hasChanged = this.latestGoldAmount !== event.goldAmount;
|
||||
this.latestGoldAmount = event.goldAmount;
|
||||
const hasChanged = this.latestGoldAmount !== BigInt(event.goldAmount);
|
||||
this.latestGoldAmount = BigInt(event.goldAmount);
|
||||
|
||||
if (this.goldAmountTimeoutId !== null) {
|
||||
clearTimeout(this.goldAmountTimeoutId);
|
||||
@@ -408,9 +404,9 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
onDisplayChatEvent(event: DisplayChatMessageUpdate) {
|
||||
const myPlayer = this.game.myPlayer();
|
||||
if (
|
||||
event.playerID === null ||
|
||||
event.playerId === null ||
|
||||
!myPlayer ||
|
||||
myPlayer.smallID() !== event.playerID
|
||||
myPlayer.smallID() !== event.playerId
|
||||
) {
|
||||
return;
|
||||
}
|
||||
@@ -452,15 +448,15 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
|
||||
onAllianceRequestEvent(update: AllianceRequestUpdate) {
|
||||
const myPlayer = this.game.myPlayer();
|
||||
if (!myPlayer || update.recipientID !== myPlayer.smallID()) {
|
||||
if (!myPlayer || update.recipientId !== myPlayer.smallID()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const requestor = this.game.playerBySmallID(
|
||||
update.requestorID,
|
||||
update.requestorId,
|
||||
) as PlayerView;
|
||||
const recipient = this.game.playerBySmallID(
|
||||
update.recipientID,
|
||||
update.recipientId,
|
||||
) as PlayerView;
|
||||
|
||||
this.addEvent({
|
||||
@@ -500,7 +496,7 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
// Recipient sent a separate request, so they became allied without the recipient responding.
|
||||
return requestor.isAlliedWith(recipient);
|
||||
},
|
||||
focusID: update.requestorID,
|
||||
focusID: update.requestorId,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -510,25 +506,25 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
return;
|
||||
}
|
||||
// myPlayer can deny alliances without clicking on the button
|
||||
if (update.request.recipientID === myPlayer.smallID()) {
|
||||
if (update.request!.recipientId === myPlayer.smallID()) {
|
||||
// Remove alliance requests whose requestors are the same as the reply's requestor
|
||||
// Noop unless the request was denied through other means (e.g attacking the requestor)
|
||||
this.events = this.events.filter(
|
||||
(event) =>
|
||||
!(
|
||||
event.type === MessageType.ALLIANCE_REQUEST &&
|
||||
event.focusID === update.request.requestorID
|
||||
event.focusID === update.request!.requestorId
|
||||
),
|
||||
);
|
||||
this.requestUpdate();
|
||||
return;
|
||||
}
|
||||
if (update.request.requestorID !== myPlayer.smallID()) {
|
||||
if (update.request!.requestorId !== myPlayer.smallID()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const recipient = this.game.playerBySmallID(
|
||||
update.request.recipientID,
|
||||
update.request!.recipientId,
|
||||
) as PlayerView;
|
||||
this.addEvent({
|
||||
description: translateText("events_display.alliance_request_status", {
|
||||
@@ -542,7 +538,7 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
: MessageType.ALLIANCE_REJECTED,
|
||||
highlight: true,
|
||||
createdAt: this.game.ticks(),
|
||||
focusID: update.request.recipientID,
|
||||
focusID: update.request!.recipientId,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -550,8 +546,8 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
const myPlayer = this.game.myPlayer();
|
||||
if (!myPlayer) return;
|
||||
|
||||
const betrayed = this.game.playerBySmallID(update.betrayedID) as PlayerView;
|
||||
const traitor = this.game.playerBySmallID(update.traitorID) as PlayerView;
|
||||
const betrayed = this.game.playerBySmallID(update.betrayedId) as PlayerView;
|
||||
const traitor = this.game.playerBySmallID(update.traitorId) as PlayerView;
|
||||
|
||||
if (betrayed.isDisconnected()) return; // Do not send the message if betraying a disconnected player
|
||||
|
||||
@@ -579,7 +575,7 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
type: MessageType.ALLIANCE_BROKEN,
|
||||
highlight: true,
|
||||
createdAt: this.game.ticks(),
|
||||
focusID: update.betrayedID,
|
||||
focusID: update.betrayedId,
|
||||
});
|
||||
} else if (betrayed === myPlayer) {
|
||||
const buttons = [
|
||||
@@ -597,7 +593,7 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
type: MessageType.ALLIANCE_BROKEN,
|
||||
highlight: true,
|
||||
createdAt: this.game.ticks(),
|
||||
focusID: update.traitorID,
|
||||
focusID: update.traitorId,
|
||||
buttons,
|
||||
});
|
||||
}
|
||||
@@ -608,10 +604,10 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
if (!myPlayer) return;
|
||||
|
||||
const otherID =
|
||||
update.player1ID === myPlayer.smallID()
|
||||
? update.player2ID
|
||||
: update.player2ID === myPlayer.smallID()
|
||||
? update.player1ID
|
||||
update.player1Id === myPlayer.smallID()
|
||||
? update.player2Id
|
||||
: update.player2Id === myPlayer.smallID()
|
||||
? update.player1Id
|
||||
: null;
|
||||
if (otherID === null) return;
|
||||
const other = this.game.playerBySmallID(otherID) as PlayerView;
|
||||
@@ -629,11 +625,11 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
}
|
||||
|
||||
onTargetPlayerEvent(event: TargetPlayerUpdate) {
|
||||
const other = this.game.playerBySmallID(event.playerID) as PlayerView;
|
||||
const other = this.game.playerBySmallID(event.playerId) as PlayerView;
|
||||
const myPlayer = this.game.myPlayer() as PlayerView;
|
||||
if (!myPlayer || !myPlayer.isFriendly(other)) return;
|
||||
|
||||
const target = this.game.playerBySmallID(event.targetID) as PlayerView;
|
||||
const target = this.game.playerBySmallID(event.targetId) as PlayerView;
|
||||
|
||||
this.addEvent({
|
||||
description: translateText("events_display.attack_request", {
|
||||
@@ -643,7 +639,7 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
type: MessageType.ATTACK_REQUEST,
|
||||
highlight: true,
|
||||
createdAt: this.game.ticks(),
|
||||
focusID: event.targetID,
|
||||
focusID: event.targetId,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -677,28 +673,27 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
const myPlayer = this.game.myPlayer();
|
||||
if (!myPlayer) return;
|
||||
|
||||
const recipient =
|
||||
update.emoji.recipientID === AllPlayers
|
||||
? AllPlayers
|
||||
: this.game.playerBySmallID(update.emoji.recipientID);
|
||||
const recipient = update.emoji!.allPlayers
|
||||
? AllPlayers
|
||||
: this.game.playerBySmallID(update.emoji!.recipientId!);
|
||||
const sender = this.game.playerBySmallID(
|
||||
update.emoji.senderID,
|
||||
update.emoji!.senderId,
|
||||
) as PlayerView;
|
||||
|
||||
if (recipient === myPlayer) {
|
||||
this.addEvent({
|
||||
description: `${sender.displayName()}: ${update.emoji.message}`,
|
||||
description: `${sender.displayName()}: ${update.emoji!.emoji}`,
|
||||
unsafeDescription: true,
|
||||
type: MessageType.CHAT,
|
||||
highlight: true,
|
||||
createdAt: this.game.ticks(),
|
||||
focusID: update.emoji.senderID,
|
||||
focusID: update.emoji!.senderId,
|
||||
});
|
||||
} else if (sender === myPlayer && recipient !== AllPlayers) {
|
||||
this.addEvent({
|
||||
description: translateText("events_display.sent_emoji", {
|
||||
name: (recipient as PlayerView).displayName(),
|
||||
emoji: update.emoji.message,
|
||||
emoji: update.emoji!.emoji,
|
||||
}),
|
||||
unsafeDescription: true,
|
||||
type: MessageType.CHAT,
|
||||
@@ -712,11 +707,11 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
onUnitIncomingEvent(event: UnitIncomingUpdate) {
|
||||
const myPlayer = this.game.myPlayer();
|
||||
|
||||
if (!myPlayer || myPlayer.smallID() !== event.playerID) {
|
||||
if (!myPlayer || myPlayer.smallID() !== event.playerId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const unitView = this.game.unit(event.unitID);
|
||||
const unitView = this.game.unit(event.unitId);
|
||||
|
||||
this.addEvent({
|
||||
description: event.message,
|
||||
@@ -737,27 +732,27 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
}
|
||||
|
||||
private async attackWarningOnClick(attack: AttackUpdate) {
|
||||
const playerView = this.game.playerBySmallID(attack.attackerID);
|
||||
const playerView = this.game.playerBySmallID(attack.attackerId);
|
||||
if (playerView !== undefined) {
|
||||
if (playerView instanceof PlayerView) {
|
||||
const averagePosition = await playerView.attackAveragePosition(
|
||||
attack.attackerID,
|
||||
attack.attackerId,
|
||||
attack.id,
|
||||
);
|
||||
|
||||
if (averagePosition === null) {
|
||||
this.emitGoToPlayerEvent(attack.attackerID);
|
||||
this.emitGoToPlayerEvent(attack.attackerId);
|
||||
} else {
|
||||
this.emitGoToPositionEvent(averagePosition.x, averagePosition.y);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.emitGoToPlayerEvent(attack.attackerID);
|
||||
this.emitGoToPlayerEvent(attack.attackerId);
|
||||
}
|
||||
}
|
||||
|
||||
private handleRetaliate(attack: AttackUpdate) {
|
||||
const attacker = this.game.playerBySmallID(attack.attackerID) as PlayerView;
|
||||
const attacker = this.game.playerBySmallID(attack.attackerId) as PlayerView;
|
||||
if (!attacker) return;
|
||||
|
||||
const myPlayer = this.game.myPlayer();
|
||||
@@ -780,7 +775,7 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
${renderTroops(attack.troops)}
|
||||
${(
|
||||
this.game.playerBySmallID(
|
||||
attack.attackerID,
|
||||
attack.attackerId,
|
||||
) as PlayerView
|
||||
)?.name()}
|
||||
${attack.retreating
|
||||
@@ -822,7 +817,7 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
${renderTroops(attack.troops)}
|
||||
${(
|
||||
this.game.playerBySmallID(
|
||||
attack.targetID,
|
||||
attack.targetId,
|
||||
) as PlayerView
|
||||
)?.name()}
|
||||
`,
|
||||
@@ -1032,7 +1027,10 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
allianceIcon,
|
||||
MessageCategory.ALLIANCE,
|
||||
)}
|
||||
${this.renderToggleButton(chatIcon, MessageCategory.CHAT)}
|
||||
${this.renderToggleButton(
|
||||
chatIcon,
|
||||
MessageCategory.CHAT_CATEGORY,
|
||||
)}
|
||||
</div>
|
||||
<div class="flex items-center gap-3">
|
||||
${this.latestGoldAmount !== null
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Theme } from "../../../core/configuration/Config";
|
||||
import { UnitType } from "../../../core/game/Game";
|
||||
import {
|
||||
BonusEventUpdate,
|
||||
ConquestUpdate,
|
||||
GameUpdateType,
|
||||
RailroadUpdate,
|
||||
UnitType,
|
||||
} from "../../../core/game/GameUpdates";
|
||||
import { GameView, UnitView } from "../../../core/game/GameView";
|
||||
import SoundManager, { SoundEffect } from "../../sound/SoundManager";
|
||||
@@ -45,29 +45,31 @@ export class FxLayer implements Layer {
|
||||
this.manageBoatTargetFx();
|
||||
this.game
|
||||
.updatesSinceLastTick()
|
||||
?.[GameUpdateType.Unit]?.map((unit) => this.game.unit(unit.id))
|
||||
?.[GameUpdateType.Unit]?.updates.map((update) =>
|
||||
this.game.unit(update.unit!.id),
|
||||
)
|
||||
?.forEach((unitView) => {
|
||||
if (unitView === undefined) return;
|
||||
this.onUnitEvent(unitView);
|
||||
});
|
||||
this.game
|
||||
.updatesSinceLastTick()
|
||||
?.[GameUpdateType.BonusEvent]?.forEach((bonusEvent) => {
|
||||
if (bonusEvent === undefined) return;
|
||||
this.onBonusEvent(bonusEvent);
|
||||
?.[GameUpdateType.BonusEvent]?.updates.forEach((update) => {
|
||||
if (update === undefined) return;
|
||||
this.onBonusEvent(update.bonusEvent!);
|
||||
});
|
||||
|
||||
this.game
|
||||
.updatesSinceLastTick()
|
||||
?.[GameUpdateType.RailroadEvent]?.forEach((update) => {
|
||||
?.[GameUpdateType.RailroadEvent]?.updates.forEach((update) => {
|
||||
if (update === undefined) return;
|
||||
this.onRailroadEvent(update);
|
||||
this.onRailroadEvent(update.railroad!);
|
||||
});
|
||||
this.game
|
||||
.updatesSinceLastTick()
|
||||
?.[GameUpdateType.ConquestEvent]?.forEach((update) => {
|
||||
?.[GameUpdateType.ConquestEvent]?.updates.forEach((update) => {
|
||||
if (update === undefined) return;
|
||||
this.onConquestEvent(update);
|
||||
this.onConquestEvent(update.conquest!);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -249,7 +251,7 @@ export class FxLayer implements Layer {
|
||||
|
||||
onConquestEvent(conquest: ConquestUpdate) {
|
||||
// Only display fx for the current player
|
||||
const conqueror = this.game.player(conquest.conquerorId);
|
||||
const conqueror = this.game.playerBySmallID(conquest.conquerorId);
|
||||
if (conqueror !== this.game.myPlayer()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -54,7 +54,8 @@ export class GameRightSidebar extends LitElement implements Layer {
|
||||
// Timer logic
|
||||
const updates = this.game.updatesSinceLastTick();
|
||||
if (updates) {
|
||||
this.hasWinner = this.hasWinner || updates[GameUpdateType.Win].length > 0;
|
||||
this.hasWinner =
|
||||
this.hasWinner || updates[GameUpdateType.Win]?.updates.length > 0;
|
||||
}
|
||||
const maxTimerValue = this.game.config().gameConfig().maxTimerValue;
|
||||
if (maxTimerValue !== undefined) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { EventBus } from "../../../core/EventBus";
|
||||
import { UnitType } from "../../../core/game/Game";
|
||||
import { TileRef } from "../../../core/game/GameMap";
|
||||
import { UnitType } from "../../../core/game/GameUpdates";
|
||||
import { GameView } from "../../../core/game/GameView";
|
||||
import { ParabolaPathFinder } from "../../../core/pathfinding/PathFinding";
|
||||
import { GhostStructureChangedEvent, MouseMoveEvent } from "../../InputHandler";
|
||||
|
||||
@@ -11,15 +11,13 @@ import portIcon from "../../../../resources/images/PortIcon.svg";
|
||||
import samLauncherIcon from "../../../../resources/images/SamLauncherIconWhite.svg";
|
||||
import { renderPlayerFlag } from "../../../core/CustomFlag";
|
||||
import { EventBus } from "../../../core/EventBus";
|
||||
import {
|
||||
PlayerProfile,
|
||||
PlayerType,
|
||||
Relation,
|
||||
Unit,
|
||||
UnitType,
|
||||
} from "../../../core/game/Game";
|
||||
import { PlayerProfile, Relation, Unit } from "../../../core/game/Game";
|
||||
import { TileRef } from "../../../core/game/GameMap";
|
||||
import { AllianceView } from "../../../core/game/GameUpdates";
|
||||
import {
|
||||
AllianceView,
|
||||
PlayerType,
|
||||
UnitType,
|
||||
} from "../../../core/game/GameUpdates";
|
||||
import { GameView, PlayerView, UnitView } from "../../../core/game/GameView";
|
||||
import { ContextMenuEvent, MouseMoveEvent } from "../../InputHandler";
|
||||
import {
|
||||
|
||||
@@ -15,10 +15,10 @@ import {
|
||||
AllPlayers,
|
||||
PlayerActions,
|
||||
PlayerProfile,
|
||||
PlayerType,
|
||||
Relation,
|
||||
} from "../../../core/game/Game";
|
||||
import { TileRef } from "../../../core/game/GameMap";
|
||||
import { PlayerType } from "../../../core/game/GameUpdates";
|
||||
import { GameView, PlayerView } from "../../../core/game/GameView";
|
||||
import { Emoji, flattenedEmojiTable } from "../../../core/Util";
|
||||
import { actionButton } from "../../components/ui/ActionButton";
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Config } from "../../../core/configuration/Config";
|
||||
import { AllPlayers, PlayerActions, UnitType } from "../../../core/game/Game";
|
||||
import { AllPlayers, PlayerActions } from "../../../core/game/Game";
|
||||
import { TileRef } from "../../../core/game/GameMap";
|
||||
import { UnitType } from "../../../core/game/GameUpdates";
|
||||
import { GameView, PlayerView } from "../../../core/game/GameView";
|
||||
import { Emoji, flattenedEmojiTable } from "../../../core/Util";
|
||||
import { renderNumber, translateText } from "../../Utils";
|
||||
|
||||
@@ -45,9 +45,9 @@ export class RailroadLayer implements Layer {
|
||||
tick() {
|
||||
const updates = this.game.updatesSinceLastTick();
|
||||
const railUpdates =
|
||||
updates !== null ? updates[GameUpdateType.RailroadEvent] : [];
|
||||
updates !== null ? updates[GameUpdateType.RailroadEvent].updates : [];
|
||||
for (const rail of railUpdates) {
|
||||
this.handleRailroadRendering(rail);
|
||||
this.handleRailroadRendering(rail.railroad!);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
import { RailType } from "../../../core/game/GameUpdates";
|
||||
|
||||
const railTypeToFunctionMap: Record<RailType, () => number[][]> = {
|
||||
[RailType.TOP_RIGHT]: topRightRailroadCornerRects,
|
||||
[RailType.BOTTOM_LEFT]: bottomLeftRailroadCornerRects,
|
||||
[RailType.TOP_LEFT]: topLeftRailroadCornerRects,
|
||||
[RailType.BOTTOM_RIGHT]: bottomRightRailroadCornerRects,
|
||||
[RailType.HORIZONTAL]: horizontalRailroadRects,
|
||||
[RailType.VERTICAL]: verticalRailroadRects,
|
||||
[RailType.topRight]: topRightRailroadCornerRects,
|
||||
[RailType.bottomLeft]: bottomLeftRailroadCornerRects,
|
||||
[RailType.topLeft]: topLeftRailroadCornerRects,
|
||||
[RailType.bottomRight]: bottomRightRailroadCornerRects,
|
||||
[RailType.horizontal]: horizontalRailroadRects,
|
||||
[RailType.vertical]: verticalRailroadRects,
|
||||
};
|
||||
|
||||
const railTypeToBridgeFunctionMap: Record<RailType, () => number[][]> = {
|
||||
[RailType.TOP_RIGHT]: topRightBridgeCornerRects,
|
||||
[RailType.BOTTOM_LEFT]: bottomLeftBridgeCornerRects,
|
||||
[RailType.TOP_LEFT]: topLeftBridgeCornerRects,
|
||||
[RailType.BOTTOM_RIGHT]: bottomRightBridgeCornerRects,
|
||||
[RailType.HORIZONTAL]: horizontalBridge,
|
||||
[RailType.VERTICAL]: verticalBridge,
|
||||
[RailType.topRight]: topRightBridgeCornerRects,
|
||||
[RailType.bottomLeft]: bottomLeftBridgeCornerRects,
|
||||
[RailType.topLeft]: topLeftBridgeCornerRects,
|
||||
[RailType.bottomRight]: bottomRightBridgeCornerRects,
|
||||
[RailType.horizontal]: horizontalBridge,
|
||||
[RailType.vertical]: verticalBridge,
|
||||
};
|
||||
|
||||
export function getRailroadRects(type: RailType): number[][] {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import type { EventBus } from "../../../core/EventBus";
|
||||
import { UnitType } from "../../../core/game/Game";
|
||||
import { GameUpdateType } from "../../../core/game/GameUpdates";
|
||||
import { GameUpdateType, UnitType } from "../../../core/game/GameUpdates";
|
||||
import type { GameView, PlayerView } from "../../../core/game/GameView";
|
||||
import { ToggleStructureEvent } from "../../InputHandler";
|
||||
import { TransformHandler } from "../TransformHandler";
|
||||
@@ -76,7 +75,8 @@ export class SAMRadiusLayer implements Layer {
|
||||
if (unitUpdates) {
|
||||
let hasChanges = false;
|
||||
|
||||
for (const update of unitUpdates) {
|
||||
for (const u of unitUpdates?.updates ?? []) {
|
||||
const update = u.unit!;
|
||||
const unit = this.game.unit(update.id);
|
||||
if (unit && unit.type() === UnitType.SAMLauncher) {
|
||||
const wasTracked = this.samLaunchers.has(update.id);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import * as PIXI from "pixi.js";
|
||||
import { Theme } from "../../../core/configuration/Config";
|
||||
import { Cell, UnitType } from "../../../core/game/Game";
|
||||
import { Cell } from "../../../core/game/Game";
|
||||
import { UnitType } from "../../../core/game/GameUpdates";
|
||||
import { GameView, PlayerView, UnitView } from "../../../core/game/GameView";
|
||||
import { TransformHandler } from "../TransformHandler";
|
||||
|
||||
|
||||
@@ -10,10 +10,9 @@ import {
|
||||
Cell,
|
||||
PlayerActions,
|
||||
PlayerID,
|
||||
UnitType,
|
||||
} from "../../../core/game/Game";
|
||||
import { TileRef } from "../../../core/game/GameMap";
|
||||
import { GameUpdateType } from "../../../core/game/GameUpdates";
|
||||
import { GameUpdateType, UnitType } from "../../../core/game/GameUpdates";
|
||||
import { GameView, UnitView } from "../../../core/game/GameView";
|
||||
import {
|
||||
GhostStructureChangedEvent,
|
||||
@@ -178,7 +177,9 @@ export class StructureIconsLayer implements Layer {
|
||||
tick() {
|
||||
this.game
|
||||
.updatesSinceLastTick()
|
||||
?.[GameUpdateType.Unit]?.map((unit) => this.game.unit(unit.id))
|
||||
?.[GameUpdateType.Unit]?.updates.map((unit) =>
|
||||
this.game.unit(unit.unit!.id),
|
||||
)
|
||||
?.forEach((unitView) => {
|
||||
if (unitView === undefined) return;
|
||||
|
||||
|
||||
@@ -10,9 +10,9 @@ import shieldIcon from "../../../../resources/images/buildings/fortAlt3.png";
|
||||
import anchorIcon from "../../../../resources/images/buildings/port1.png";
|
||||
import missileSiloIcon from "../../../../resources/images/buildings/silo1.png";
|
||||
import SAMMissileIcon from "../../../../resources/images/buildings/silo4.png";
|
||||
import { Cell, UnitType } from "../../../core/game/Game";
|
||||
import { AllUnitTypes, Cell } from "../../../core/game/Game";
|
||||
import { euclDistFN, isometricDistFN } from "../../../core/game/GameMap";
|
||||
import { GameUpdateType } from "../../../core/game/GameUpdates";
|
||||
import { GameUpdateType, UnitType } from "../../../core/game/GameUpdates";
|
||||
import { GameView, UnitView } from "../../../core/game/GameView";
|
||||
|
||||
const underConstructionColor = colord("rgb(150,150,150)");
|
||||
@@ -32,7 +32,7 @@ interface UnitRenderConfig {
|
||||
export class StructureLayer implements Layer {
|
||||
private canvas: HTMLCanvasElement;
|
||||
private context: CanvasRenderingContext2D;
|
||||
private unitIcons: Map<string, HTMLImageElement> = new Map();
|
||||
private unitIcons: Map<UnitType, HTMLImageElement> = new Map();
|
||||
private theme: Theme;
|
||||
private tempCanvas: HTMLCanvasElement;
|
||||
private tempContext: CanvasRenderingContext2D;
|
||||
@@ -84,7 +84,7 @@ export class StructureLayer implements Layer {
|
||||
this.loadIconData();
|
||||
}
|
||||
|
||||
private loadIcon(unitType: string, config: UnitRenderConfig) {
|
||||
private loadIcon(unitType: UnitType, config: UnitRenderConfig) {
|
||||
const image = new Image();
|
||||
image.src = config.icon;
|
||||
image.onload = () => {
|
||||
@@ -99,8 +99,11 @@ export class StructureLayer implements Layer {
|
||||
}
|
||||
|
||||
private loadIconData() {
|
||||
Object.entries(this.unitConfigs).forEach(([unitType, config]) => {
|
||||
this.loadIcon(unitType, config);
|
||||
AllUnitTypes.forEach((unitType) => {
|
||||
const config = this.unitConfigs[unitType];
|
||||
if (config) {
|
||||
this.loadIcon(unitType, this.unitConfigs[unitType]!);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -110,9 +113,10 @@ export class StructureLayer implements Layer {
|
||||
|
||||
tick() {
|
||||
const updates = this.game.updatesSinceLastTick();
|
||||
const unitUpdates = updates !== null ? updates[GameUpdateType.Unit] : [];
|
||||
const unitUpdates =
|
||||
updates !== null ? (updates[GameUpdateType.Unit]?.updates ?? []) : [];
|
||||
for (const u of unitUpdates) {
|
||||
const unit = this.game.unit(u.id);
|
||||
const unit = this.game.unit(u.unit!.id);
|
||||
if (unit === undefined) continue;
|
||||
this.handleUnitRendering(unit);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { LitElement, html } from "lit";
|
||||
import { customElement, property } from "lit/decorators.js";
|
||||
import { EventBus } from "../../../core/EventBus";
|
||||
import { GameMode, Team, UnitType } from "../../../core/game/Game";
|
||||
import { GameMode, Team } from "../../../core/game/Game";
|
||||
import { UnitType } from "../../../core/game/GameUpdates";
|
||||
import { GameView, PlayerView } from "../../../core/game/GameView";
|
||||
import { renderNumber, translateText } from "../../Utils";
|
||||
import { Layer } from "./Layer";
|
||||
|
||||
@@ -2,15 +2,13 @@ import { PriorityQueue } from "@datastructures-js/priority-queue";
|
||||
import { Colord } from "colord";
|
||||
import { Theme } from "../../../core/configuration/Config";
|
||||
import { EventBus } from "../../../core/EventBus";
|
||||
import {
|
||||
Cell,
|
||||
ColoredTeams,
|
||||
PlayerType,
|
||||
Team,
|
||||
UnitType,
|
||||
} from "../../../core/game/Game";
|
||||
import { Cell, ColoredTeams, Team } from "../../../core/game/Game";
|
||||
import { euclDistFN, TileRef } from "../../../core/game/GameMap";
|
||||
import { GameUpdateType } from "../../../core/game/GameUpdates";
|
||||
import {
|
||||
GameUpdateType,
|
||||
PlayerType,
|
||||
UnitType,
|
||||
} from "../../../core/game/GameUpdates";
|
||||
import { GameView, PlayerView } from "../../../core/game/GameView";
|
||||
import { UserSettings } from "../../../core/game/UserSettings";
|
||||
import { PseudoRandom } from "../../../core/PseudoRandom";
|
||||
@@ -87,8 +85,8 @@ export class TerritoryLayer implements Layer {
|
||||
|
||||
this.game.recentlyUpdatedTiles().forEach((t) => this.enqueueTile(t));
|
||||
const updates = this.game.updatesSinceLastTick();
|
||||
const unitUpdates = updates !== null ? updates[GameUpdateType.Unit] : [];
|
||||
unitUpdates.forEach((update) => {
|
||||
updates[GameUpdateType.Unit]?.updates.forEach((u) => {
|
||||
const update = u.unit!;
|
||||
if (update.unitType === UnitType.DefensePost) {
|
||||
// Only update borders if the defense post is not under construction
|
||||
if (update.underConstruction) {
|
||||
@@ -101,8 +99,8 @@ export class TerritoryLayer implements Layer {
|
||||
.forEach((t) => {
|
||||
if (
|
||||
this.game.isBorder(t) &&
|
||||
(this.game.ownerID(t) === update.ownerID ||
|
||||
this.game.ownerID(t) === update.lastOwnerID)
|
||||
(this.game.ownerID(t) === update.ownerId ||
|
||||
this.game.ownerID(t) === update.lastOwnerId)
|
||||
) {
|
||||
this.enqueueTile(t);
|
||||
}
|
||||
@@ -113,33 +111,42 @@ export class TerritoryLayer implements Layer {
|
||||
// Detect alliance mutations
|
||||
const myPlayer = this.game.myPlayer();
|
||||
if (myPlayer) {
|
||||
updates?.[GameUpdateType.BrokeAlliance]?.forEach((update) => {
|
||||
const territory = this.game.playerBySmallID(update.betrayedID);
|
||||
updates?.[GameUpdateType.BrokeAlliance]?.updates.forEach((update) => {
|
||||
const brokeAllianceUpdate = update.brokeAlliance!;
|
||||
const territory = this.game.playerBySmallID(
|
||||
brokeAllianceUpdate.betrayedId,
|
||||
);
|
||||
if (territory && territory instanceof PlayerView) {
|
||||
this.redrawBorder(territory);
|
||||
}
|
||||
});
|
||||
|
||||
updates?.[GameUpdateType.AllianceRequestReply]?.forEach((update) => {
|
||||
if (
|
||||
update.accepted &&
|
||||
(update.request.requestorID === myPlayer.smallID() ||
|
||||
update.request.recipientID === myPlayer.smallID())
|
||||
) {
|
||||
const territoryId =
|
||||
update.request.requestorID === myPlayer.smallID()
|
||||
? update.request.recipientID
|
||||
: update.request.requestorID;
|
||||
const territory = this.game.playerBySmallID(territoryId);
|
||||
if (territory && territory instanceof PlayerView) {
|
||||
this.redrawBorder(territory);
|
||||
updates?.[GameUpdateType.AllianceRequestReply]?.updates.forEach(
|
||||
(update) => {
|
||||
const au = update.allianceRequestReply!;
|
||||
if (
|
||||
au.accepted &&
|
||||
(au.request!.requestorId === myPlayer.smallID() ||
|
||||
au.request!.recipientId === myPlayer.smallID())
|
||||
) {
|
||||
const territoryId =
|
||||
au.request!.requestorId === myPlayer.smallID()
|
||||
? au.request!.recipientId
|
||||
: au.request!.requestorId;
|
||||
const territory = this.game.playerBySmallID(territoryId);
|
||||
if (territory && territory instanceof PlayerView) {
|
||||
this.redrawBorder(territory);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
updates?.[GameUpdateType.EmbargoEvent]?.forEach((update) => {
|
||||
const player = this.game.playerBySmallID(update.playerID) as PlayerView;
|
||||
},
|
||||
);
|
||||
updates?.[GameUpdateType.EmbargoEvent]?.updates.forEach((update) => {
|
||||
const embargoUpdate = update.embargo!;
|
||||
const player = this.game.playerBySmallID(
|
||||
embargoUpdate.playerId,
|
||||
) as PlayerView;
|
||||
const embargoed = this.game.playerBySmallID(
|
||||
update.embargoedID,
|
||||
embargoUpdate.embargoedId,
|
||||
) as PlayerView;
|
||||
|
||||
if (
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { Colord } from "colord";
|
||||
import { EventBus } from "../../../core/EventBus";
|
||||
import { Theme } from "../../../core/configuration/Config";
|
||||
import { UnitType } from "../../../core/game/Game";
|
||||
import { GameUpdateType } from "../../../core/game/GameUpdates";
|
||||
import { GameUpdateType, UnitType } from "../../../core/game/GameUpdates";
|
||||
import { GameView, UnitView } from "../../../core/game/GameView";
|
||||
import { UserSettings } from "../../../core/game/UserSettings";
|
||||
import { UnitSelectionEvent } from "../../InputHandler";
|
||||
@@ -71,7 +70,9 @@ export class UILayer implements Layer {
|
||||
|
||||
this.game
|
||||
.updatesSinceLastTick()
|
||||
?.[GameUpdateType.Unit]?.map((unit) => this.game.unit(unit.id))
|
||||
?.[GameUpdateType.Unit]?.updates.map((unit) =>
|
||||
this.game.unit(unit.unit!.id),
|
||||
)
|
||||
?.forEach((unitView) => {
|
||||
if (unitView === undefined) return;
|
||||
this.onUnitEvent(unitView);
|
||||
|
||||
@@ -11,7 +11,8 @@ import portIcon from "../../../../resources/images/PortIcon.svg";
|
||||
import samLauncherIcon from "../../../../resources/images/SamLauncherIconWhite.svg";
|
||||
import defensePostIcon from "../../../../resources/images/ShieldIconWhite.svg";
|
||||
import { EventBus } from "../../../core/EventBus";
|
||||
import { Gold, PlayerActions, UnitType } from "../../../core/game/Game";
|
||||
import { Gold, PlayerActions } from "../../../core/game/Game";
|
||||
import { UnitType } from "../../../core/game/GameUpdates";
|
||||
import { GameView } from "../../../core/game/GameView";
|
||||
import {
|
||||
GhostStructureChangedEvent,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { colord, Colord } from "colord";
|
||||
import { EventBus } from "../../../core/EventBus";
|
||||
import { Theme } from "../../../core/configuration/Config";
|
||||
import { UnitType } from "../../../core/game/Game";
|
||||
import { TileRef } from "../../../core/game/GameMap";
|
||||
import { UnitType } from "../../../core/game/GameUpdates";
|
||||
import { GameView, UnitView } from "../../../core/game/GameView";
|
||||
import { BezenhamLine } from "../../../core/utilities/Line";
|
||||
import {
|
||||
@@ -67,7 +67,7 @@ export class UnitLayer implements Layer {
|
||||
tick() {
|
||||
const unitIds = this.game
|
||||
.updatesSinceLastTick()
|
||||
?.[GameUpdateType.Unit]?.map((unit) => unit.id);
|
||||
?.[GameUpdateType.Unit]?.updates.map((unit) => unit.unit!.id);
|
||||
|
||||
this.updateUnitsSprites(unitIds ?? []);
|
||||
}
|
||||
|
||||
@@ -315,12 +315,17 @@ export class WinModal extends LitElement implements Layer {
|
||||
this.show();
|
||||
}
|
||||
const updates = this.game.updatesSinceLastTick();
|
||||
const winUpdates = updates !== null ? updates[GameUpdateType.Win] : [];
|
||||
winUpdates.forEach((wu) => {
|
||||
const winUpdates =
|
||||
updates !== null ? updates[GameUpdateType.Win].updates : [];
|
||||
winUpdates.forEach((update) => {
|
||||
const wu = update.win!;
|
||||
|
||||
if (wu.winner === undefined) {
|
||||
// ...
|
||||
} else if (wu.winner[0] === "team") {
|
||||
this.eventBus.emit(new SendWinnerEvent(wu.winner, wu.allPlayersStats));
|
||||
this.eventBus.emit(
|
||||
new SendWinnerEvent(JSON.parse(wu.winner), JSON.parse(wu.stats)),
|
||||
);
|
||||
if (wu.winner[1] === this.game.myPlayer()?.team()) {
|
||||
this._title = translateText("win_modal.your_team");
|
||||
this.isWin = true;
|
||||
@@ -337,7 +342,7 @@ export class WinModal extends LitElement implements Layer {
|
||||
const winnerClient = winner.clientID();
|
||||
if (winnerClient !== null) {
|
||||
this.eventBus.emit(
|
||||
new SendWinnerEvent(["player", winnerClient], wu.allPlayersStats),
|
||||
new SendWinnerEvent(["player", winnerClient], JSON.parse(wu.stats)),
|
||||
);
|
||||
}
|
||||
if (
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// renderUnitTypeOptions.ts
|
||||
import { html, TemplateResult } from "lit";
|
||||
import { UnitType } from "../../core/game/Game";
|
||||
import { UnitType } from "../../core/game/GameUpdates";
|
||||
import { translateText } from "../Utils";
|
||||
|
||||
export interface UnitTypeRenderContext {
|
||||
|
||||
+5
-20
@@ -7,8 +7,6 @@ import {
|
||||
Attack,
|
||||
Cell,
|
||||
Game,
|
||||
GameUpdates,
|
||||
NameViewData,
|
||||
Nation,
|
||||
Player,
|
||||
PlayerActions,
|
||||
@@ -16,15 +14,15 @@ import {
|
||||
PlayerID,
|
||||
PlayerInfo,
|
||||
PlayerProfile,
|
||||
PlayerType,
|
||||
} from "./game/Game";
|
||||
import { createGame } from "./game/GameImpl";
|
||||
import { TileRef } from "./game/GameMap";
|
||||
import { GameMapLoader } from "./game/GameMapLoader";
|
||||
import {
|
||||
ErrorUpdate,
|
||||
GameUpdateType,
|
||||
GameUpdateViewData,
|
||||
NameViewData,
|
||||
PlayerType,
|
||||
} from "./game/GameUpdates";
|
||||
import { loadTerrainMap as loadGameMap } from "./game/TerrainMapLoader";
|
||||
import { PseudoRandom } from "./PseudoRandom";
|
||||
@@ -134,17 +132,14 @@ export class GameRunner {
|
||||
);
|
||||
this.currTurn++;
|
||||
|
||||
let updates: GameUpdates;
|
||||
let tickExecutionDuration: number = 0;
|
||||
let updates: GameUpdateViewData;
|
||||
|
||||
try {
|
||||
const startTime = performance.now();
|
||||
updates = this.game.executeNextTick();
|
||||
const endTime = performance.now();
|
||||
tickExecutionDuration = endTime - startTime;
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof Error) {
|
||||
console.error("Game tick error:", error.message);
|
||||
console.error("Stack trace:", error.stack);
|
||||
this.callBack({
|
||||
errMsg: error.message,
|
||||
stack: error.stack,
|
||||
@@ -173,17 +168,7 @@ export class GameRunner {
|
||||
});
|
||||
}
|
||||
|
||||
// Many tiles are updated to pack it into an array
|
||||
const packedTileUpdates = updates[GameUpdateType.Tile].map((u) => u.update);
|
||||
updates[GameUpdateType.Tile] = [];
|
||||
|
||||
this.callBack({
|
||||
tick: this.game.ticks(),
|
||||
packedTileUpdates: new BigUint64Array(packedTileUpdates),
|
||||
updates: updates,
|
||||
playerNameViewData: this.playerViewData,
|
||||
tickExecutionDuration: tickExecutionDuration,
|
||||
});
|
||||
this.callBack(updates);
|
||||
this.isExecuting = false;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -17,8 +17,8 @@ import {
|
||||
HumansVsNations,
|
||||
Quads,
|
||||
Trios,
|
||||
UnitType,
|
||||
} from "./game/Game";
|
||||
import { UnitType } from "./game/GameUpdates";
|
||||
import { PlayerStatsSchema } from "./StatsSchemas";
|
||||
import { flattenedEmojiTable } from "./Util";
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { z } from "zod";
|
||||
import { UnitType } from "./game/Game";
|
||||
import { UnitType } from "./game/GameUpdates";
|
||||
|
||||
export const bombUnits = ["abomb", "hbomb", "mirv", "mirvw"] as const;
|
||||
export const BombUnitSchema = z.enum(bombUnits);
|
||||
|
||||
+3
-2
@@ -16,6 +16,7 @@ import {
|
||||
BOT_NAME_PREFIXES,
|
||||
BOT_NAME_SUFFIXES,
|
||||
} from "./execution/utils/BotNames";
|
||||
import { PlayerType } from "./game/GameUpdates";
|
||||
|
||||
export function manhattanDistWrapped(
|
||||
c1: Cell,
|
||||
@@ -290,10 +291,10 @@ export function withinInt(num: bigint, min: bigint, max: bigint): bigint {
|
||||
|
||||
export function createRandomName(
|
||||
name: string,
|
||||
playerType: string,
|
||||
playerType: PlayerType,
|
||||
): string | null {
|
||||
let randomName: string | null = null;
|
||||
if (playerType === "HUMAN") {
|
||||
if (playerType === PlayerType.Human) {
|
||||
const hash = simpleHash(name);
|
||||
const prefixIndex = hash % BOT_NAME_PREFIXES.length;
|
||||
const suffixIndex =
|
||||
|
||||
@@ -12,9 +12,9 @@ import {
|
||||
TerraNullius,
|
||||
Tick,
|
||||
UnitInfo,
|
||||
UnitType,
|
||||
} from "../game/Game";
|
||||
import { GameMap, TileRef } from "../game/GameMap";
|
||||
import { UnitType } from "../game/GameUpdates";
|
||||
import { PlayerView } from "../game/GameView";
|
||||
import { UserSettings } from "../game/UserSettings";
|
||||
import { GameConfig, GameID, TeamCountConfig } from "../Schemas";
|
||||
|
||||
@@ -11,16 +11,15 @@ import {
|
||||
HumansVsNations,
|
||||
Player,
|
||||
PlayerInfo,
|
||||
PlayerType,
|
||||
Quads,
|
||||
TerrainType,
|
||||
TerraNullius,
|
||||
Tick,
|
||||
Trios,
|
||||
UnitInfo,
|
||||
UnitType,
|
||||
} from "../game/Game";
|
||||
import { TileRef } from "../game/GameMap";
|
||||
import { PlayerType, UnitType } from "../game/GameUpdates";
|
||||
import { PlayerView } from "../game/GameView";
|
||||
import { UserSettings } from "../game/UserSettings";
|
||||
import { GameConfig, GameID, TeamCountConfig } from "../Schemas";
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { Colord, colord, LabaColor } from "colord";
|
||||
import { PseudoRandom } from "../PseudoRandom";
|
||||
import { PlayerType, Team, TerrainType } from "../game/Game";
|
||||
import { Team, TerrainType } from "../game/Game";
|
||||
import { GameMap, TileRef } from "../game/GameMap";
|
||||
import { PlayerType } from "../game/GameUpdates";
|
||||
import { PlayerView } from "../game/GameView";
|
||||
import { ColorAllocator } from "./ColorAllocator";
|
||||
import { botColors, fallbackColors, humanColors, nationColors } from "./Colors";
|
||||
|
||||
@@ -3,14 +3,13 @@ import {
|
||||
Attack,
|
||||
Execution,
|
||||
Game,
|
||||
MessageType,
|
||||
Player,
|
||||
PlayerID,
|
||||
PlayerType,
|
||||
TerrainType,
|
||||
TerraNullius,
|
||||
} from "../game/Game";
|
||||
import { TileRef } from "../game/GameMap";
|
||||
import { MessageType, PlayerType } from "../game/GameUpdates";
|
||||
import { PseudoRandom } from "../PseudoRandom";
|
||||
import { FlatBinaryHeap } from "./utils/FlatBinaryHeap"; // adjust path if needed
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Execution, Game, Player, UnitType } from "../game/Game";
|
||||
import { Execution, Game, Player } from "../game/Game";
|
||||
import { UnitType } from "../game/GameUpdates";
|
||||
|
||||
export class BoatRetreatExecution implements Execution {
|
||||
private active = true;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Game, PlayerInfo, PlayerType } from "../game/Game";
|
||||
import { Game, PlayerInfo } from "../game/Game";
|
||||
import { TileRef } from "../game/GameMap";
|
||||
import { PlayerType } from "../game/GameUpdates";
|
||||
import { PseudoRandom } from "../PseudoRandom";
|
||||
import { GameID } from "../Schemas";
|
||||
import { simpleHash } from "../Util";
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Execution, Game, Unit, UnitType } from "../game/Game";
|
||||
import { Execution, Game, Unit } from "../game/Game";
|
||||
import { UnitType } from "../game/GameUpdates";
|
||||
import { TrainStationExecution } from "./TrainStationExecution";
|
||||
|
||||
export class CityExecution implements Execution {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Execution, Game, Player, Tick, Unit, UnitType } from "../game/Game";
|
||||
import { Execution, Game, Player, Tick, Unit } from "../game/Game";
|
||||
import { TileRef } from "../game/GameMap";
|
||||
import { UnitType } from "../game/GameUpdates";
|
||||
import { CityExecution } from "./CityExecution";
|
||||
import { DefensePostExecution } from "./DefensePostExecution";
|
||||
import { FactoryExecution } from "./FactoryExecution";
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Execution, Game, MessageType, Player, Unit } from "../game/Game";
|
||||
import { Execution, Game, Player, Unit } from "../game/Game";
|
||||
import { MessageType } from "../game/GameUpdates";
|
||||
|
||||
export class DeleteUnitExecution implements Execution {
|
||||
private active: boolean = true;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Execution, Game, Player, PlayerType } from "../game/Game";
|
||||
import { Execution, Game, Player } from "../game/Game";
|
||||
import { PlayerType } from "../game/GameUpdates";
|
||||
|
||||
export class EmbargoAllExecution implements Execution {
|
||||
constructor(
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
import {
|
||||
AllPlayers,
|
||||
Execution,
|
||||
Game,
|
||||
Player,
|
||||
PlayerID,
|
||||
PlayerType,
|
||||
} from "../game/Game";
|
||||
import { AllPlayers, Execution, Game, Player, PlayerID } from "../game/Game";
|
||||
import { PlayerType } from "../game/GameUpdates";
|
||||
import { flattenedEmojiTable } from "../Util";
|
||||
|
||||
export class EmojiExecution implements Execution {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Execution, Game, Unit, UnitType } from "../game/Game";
|
||||
import { Execution, Game, Unit } from "../game/Game";
|
||||
import { UnitType } from "../game/GameUpdates";
|
||||
import { TrainStationExecution } from "./TrainStationExecution";
|
||||
|
||||
export class FactoryExecution implements Execution {
|
||||
|
||||
@@ -7,14 +7,13 @@ import {
|
||||
Nation,
|
||||
Player,
|
||||
PlayerID,
|
||||
PlayerType,
|
||||
Relation,
|
||||
TerrainType,
|
||||
Tick,
|
||||
Unit,
|
||||
UnitType,
|
||||
} from "../game/Game";
|
||||
import { TileRef, euclDistFN } from "../game/GameMap";
|
||||
import { PlayerType, UnitType } from "../game/GameUpdates";
|
||||
import { PseudoRandom } from "../PseudoRandom";
|
||||
import { GameID } from "../Schemas";
|
||||
import { boundingBoxTiles, calculateBoundingBox, simpleHash } from "../Util";
|
||||
|
||||
@@ -1,13 +1,6 @@
|
||||
import {
|
||||
Execution,
|
||||
Game,
|
||||
MessageType,
|
||||
Player,
|
||||
TerraNullius,
|
||||
Unit,
|
||||
UnitType,
|
||||
} from "../game/Game";
|
||||
import { Execution, Game, Player, TerraNullius, Unit } from "../game/Game";
|
||||
import { TileRef } from "../game/GameMap";
|
||||
import { MessageType, UnitType } from "../game/GameUpdates";
|
||||
import { ParabolaPathFinder } from "../pathfinding/PathFinding";
|
||||
import { PseudoRandom } from "../PseudoRandom";
|
||||
import { simpleHash } from "../Util";
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Execution, Game, Player, UnitType } from "../game/Game";
|
||||
import { Execution, Game, Player } from "../game/Game";
|
||||
import { TileRef } from "../game/GameMap";
|
||||
import { UnitType } from "../game/GameUpdates";
|
||||
|
||||
export class MoveWarshipExecution implements Execution {
|
||||
constructor(
|
||||
|
||||
@@ -2,14 +2,13 @@ import {
|
||||
Execution,
|
||||
Game,
|
||||
isStructureType,
|
||||
MessageType,
|
||||
Player,
|
||||
TerraNullius,
|
||||
TrajectoryTile,
|
||||
Unit,
|
||||
UnitType,
|
||||
} from "../game/Game";
|
||||
import { TileRef } from "../game/GameMap";
|
||||
import { MessageType, UnitType } from "../game/GameUpdates";
|
||||
import { ParabolaPathFinder } from "../pathfinding/PathFinding";
|
||||
import { PseudoRandom } from "../PseudoRandom";
|
||||
import { NukeType } from "../StatsSchemas";
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Config } from "../configuration/Config";
|
||||
import { Execution, Game, Player, UnitType } from "../game/Game";
|
||||
import { Execution, Game, Player } from "../game/Game";
|
||||
import { TileRef } from "../game/GameMap";
|
||||
import { UnitType } from "../game/GameUpdates";
|
||||
import { calculateBoundingBox, getMode, inscribed, simpleHash } from "../Util";
|
||||
|
||||
interface ClusterTraversalState {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Execution, Game, Unit, UnitType } from "../game/Game";
|
||||
import { Execution, Game, Unit } from "../game/Game";
|
||||
import { UnitType } from "../game/GameUpdates";
|
||||
import { PseudoRandom } from "../PseudoRandom";
|
||||
import { TradeShipExecution } from "./TradeShipExecution";
|
||||
import { TrainStationExecution } from "./TrainStationExecution";
|
||||
|
||||
@@ -27,7 +27,7 @@ export class RailroadExecution implements Execution {
|
||||
railType:
|
||||
tiles.length > 0
|
||||
? this.computeExtremityDirection(tiles[0], tiles[1])
|
||||
: RailType.VERTICAL,
|
||||
: RailType.vertical,
|
||||
});
|
||||
for (let i = 1; i < tiles.length - 1; i++) {
|
||||
const direction = this.computeDirection(
|
||||
@@ -45,7 +45,7 @@ export class RailroadExecution implements Execution {
|
||||
tiles[tiles.length - 1],
|
||||
tiles[tiles.length - 2],
|
||||
)
|
||||
: RailType.VERTICAL,
|
||||
: RailType.vertical,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -58,14 +58,14 @@ export class RailroadExecution implements Execution {
|
||||
const dx = nextX - x;
|
||||
const dy = nextY - y;
|
||||
|
||||
if (dx === 0 && dy === 0) return RailType.VERTICAL; // No movement
|
||||
if (dx === 0 && dy === 0) return RailType.vertical; // No movement
|
||||
|
||||
if (dx === 0) {
|
||||
return RailType.VERTICAL;
|
||||
return RailType.vertical;
|
||||
} else if (dy === 0) {
|
||||
return RailType.HORIZONTAL;
|
||||
return RailType.horizontal;
|
||||
}
|
||||
return RailType.VERTICAL;
|
||||
return RailType.vertical;
|
||||
}
|
||||
|
||||
private computeDirection(
|
||||
@@ -90,25 +90,25 @@ export class RailroadExecution implements Execution {
|
||||
|
||||
// Straight line
|
||||
if (dx1 === dx2 && dy1 === dy2) {
|
||||
if (dx1 !== 0) return RailType.HORIZONTAL;
|
||||
if (dy1 !== 0) return RailType.VERTICAL;
|
||||
if (dx1 !== 0) return RailType.horizontal;
|
||||
if (dy1 !== 0) return RailType.vertical;
|
||||
}
|
||||
|
||||
// Turn (corner) cases
|
||||
if ((dx1 === 0 && dx2 !== 0) || (dx1 !== 0 && dx2 === 0)) {
|
||||
// Now figure out which type of corner
|
||||
if (dx1 === 0 && dx2 === 1 && dy1 === -1) return RailType.BOTTOM_RIGHT;
|
||||
if (dx1 === 0 && dx2 === -1 && dy1 === -1) return RailType.BOTTOM_LEFT;
|
||||
if (dx1 === 0 && dx2 === 1 && dy1 === 1) return RailType.TOP_RIGHT;
|
||||
if (dx1 === 0 && dx2 === -1 && dy1 === 1) return RailType.TOP_LEFT;
|
||||
if (dx1 === 0 && dx2 === 1 && dy1 === -1) return RailType.bottomRight;
|
||||
if (dx1 === 0 && dx2 === -1 && dy1 === -1) return RailType.bottomLeft;
|
||||
if (dx1 === 0 && dx2 === 1 && dy1 === 1) return RailType.topRight;
|
||||
if (dx1 === 0 && dx2 === -1 && dy1 === 1) return RailType.topLeft;
|
||||
|
||||
if (dx1 === 1 && dx2 === 0 && dy2 === -1) return RailType.TOP_LEFT;
|
||||
if (dx1 === -1 && dx2 === 0 && dy2 === -1) return RailType.TOP_RIGHT;
|
||||
if (dx1 === 1 && dx2 === 0 && dy2 === 1) return RailType.BOTTOM_LEFT;
|
||||
if (dx1 === -1 && dx2 === 0 && dy2 === 1) return RailType.BOTTOM_RIGHT;
|
||||
if (dx1 === 1 && dx2 === 0 && dy2 === -1) return RailType.topLeft;
|
||||
if (dx1 === -1 && dx2 === 0 && dy2 === -1) return RailType.topRight;
|
||||
if (dx1 === 1 && dx2 === 0 && dy2 === 1) return RailType.bottomLeft;
|
||||
if (dx1 === -1 && dx2 === 0 && dy2 === 1) return RailType.bottomRight;
|
||||
}
|
||||
console.warn(`Invalid rail segment: ${dx1}:${dy1}, ${dx2}:${dy2}`);
|
||||
return RailType.VERTICAL;
|
||||
return RailType.vertical;
|
||||
}
|
||||
|
||||
tick(ticks: number): void {
|
||||
@@ -144,8 +144,10 @@ export class RailroadExecution implements Execution {
|
||||
if (updatedRailTiles) {
|
||||
this.mg.addUpdate({
|
||||
type: GameUpdateType.RailroadEvent,
|
||||
isActive: true,
|
||||
railTiles: updatedRailTiles,
|
||||
railroad: {
|
||||
isActive: true,
|
||||
railTiles: updatedRailTiles,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,6 @@
|
||||
import {
|
||||
Execution,
|
||||
Game,
|
||||
isUnit,
|
||||
MessageType,
|
||||
Player,
|
||||
Unit,
|
||||
UnitType,
|
||||
} from "../game/Game";
|
||||
import { Execution, Game, isUnit, Player, Unit } from "../game/Game";
|
||||
import { TileRef } from "../game/GameMap";
|
||||
import { MessageType, UnitType } from "../game/GameUpdates";
|
||||
import { PseudoRandom } from "../PseudoRandom";
|
||||
import { SAMMissileExecution } from "./SAMMissileExecution";
|
||||
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
import {
|
||||
Execution,
|
||||
Game,
|
||||
MessageType,
|
||||
Player,
|
||||
Unit,
|
||||
UnitType,
|
||||
} from "../game/Game";
|
||||
import { Execution, Game, Player, Unit } from "../game/Game";
|
||||
import { TileRef } from "../game/GameMap";
|
||||
import { MessageType, UnitType } from "../game/GameUpdates";
|
||||
import { AirPathFinder } from "../pathfinding/PathFinding";
|
||||
import { PseudoRandom } from "../PseudoRandom";
|
||||
import { NukeType } from "../StatsSchemas";
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Execution, Game, Player, Unit, UnitType } from "../game/Game";
|
||||
import { Execution, Game, Player, Unit } from "../game/Game";
|
||||
import { TileRef } from "../game/GameMap";
|
||||
import { UnitType } from "../game/GameUpdates";
|
||||
import { AirPathFinder } from "../pathfinding/PathFinding";
|
||||
import { PseudoRandom } from "../PseudoRandom";
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Execution, Game, Player, PlayerInfo, PlayerType } from "../game/Game";
|
||||
import { Execution, Game, Player, PlayerInfo } from "../game/Game";
|
||||
import { TileRef } from "../game/GameMap";
|
||||
import { PlayerType } from "../game/GameUpdates";
|
||||
import { BotExecution } from "./BotExecution";
|
||||
import { PlayerExecution } from "./PlayerExecution";
|
||||
import { getSpawnTiles } from "./Util";
|
||||
|
||||
@@ -1,13 +1,7 @@
|
||||
import { renderNumber } from "../../client/Utils";
|
||||
import {
|
||||
Execution,
|
||||
Game,
|
||||
MessageType,
|
||||
Player,
|
||||
Unit,
|
||||
UnitType,
|
||||
} from "../game/Game";
|
||||
import { Execution, Game, Player, Unit } from "../game/Game";
|
||||
import { TileRef } from "../game/GameMap";
|
||||
import { MessageType, UnitType } from "../game/GameUpdates";
|
||||
import { PathFindResultType } from "../pathfinding/AStar";
|
||||
import { PathFinder } from "../pathfinding/PathFinding";
|
||||
import { distSortUnit } from "../Util";
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
import {
|
||||
Execution,
|
||||
Game,
|
||||
Player,
|
||||
TrainType,
|
||||
Unit,
|
||||
UnitType,
|
||||
} from "../game/Game";
|
||||
import { Execution, Game, Player, Unit } from "../game/Game";
|
||||
import { TileRef } from "../game/GameMap";
|
||||
import { TrainType, UnitType } from "../game/GameUpdates";
|
||||
import { RailNetwork } from "../game/RailNetwork";
|
||||
import { getOrientedRailroad, OrientedRailroad } from "../game/Railroad";
|
||||
import { TrainStation } from "../game/TrainStation";
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Execution, Game, Unit, UnitType } from "../game/Game";
|
||||
import { Execution, Game, Unit } from "../game/Game";
|
||||
import { UnitType } from "../game/GameUpdates";
|
||||
import { TrainStation } from "../game/TrainStation";
|
||||
import { PseudoRandom } from "../PseudoRandom";
|
||||
import { TrainExecution } from "./TrainExecution";
|
||||
|
||||
@@ -2,14 +2,13 @@ import { renderTroops } from "../../client/Utils";
|
||||
import {
|
||||
Execution,
|
||||
Game,
|
||||
MessageType,
|
||||
Player,
|
||||
PlayerID,
|
||||
TerraNullius,
|
||||
Unit,
|
||||
UnitType,
|
||||
} from "../game/Game";
|
||||
import { TileRef } from "../game/GameMap";
|
||||
import { MessageType, UnitType } from "../game/GameUpdates";
|
||||
import { targetTransportTile } from "../game/TransportShipUtils";
|
||||
import { PathFindResultType } from "../pathfinding/AStar";
|
||||
import { PathFinder } from "../pathfinding/PathFinding";
|
||||
|
||||
@@ -5,9 +5,9 @@ import {
|
||||
OwnerComp,
|
||||
Unit,
|
||||
UnitParams,
|
||||
UnitType,
|
||||
} from "../game/Game";
|
||||
import { TileRef } from "../game/GameMap";
|
||||
import { UnitType } from "../game/GameUpdates";
|
||||
import { PathFindResultType } from "../pathfinding/AStar";
|
||||
import { PathFinder } from "../pathfinding/PathFinding";
|
||||
import { PseudoRandom } from "../PseudoRandom";
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
import {
|
||||
Execution,
|
||||
Game,
|
||||
MessageType,
|
||||
Player,
|
||||
PlayerID,
|
||||
} from "../../game/Game";
|
||||
import { Execution, Game, Player, PlayerID } from "../../game/Game";
|
||||
import { MessageType } from "../../game/GameUpdates";
|
||||
|
||||
export class AllianceExtensionExecution implements Execution {
|
||||
constructor(
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Game, Player, Relation, UnitType } from "../../game/Game";
|
||||
import { Game, Player, Relation } from "../../game/Game";
|
||||
import { TileRef } from "../../game/GameMap";
|
||||
import { UnitType } from "../../game/GameUpdates";
|
||||
import { closestTile, closestTwoTiles } from "../Util";
|
||||
|
||||
export function structureSpawnTileValue(
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
import {
|
||||
Difficulty,
|
||||
Game,
|
||||
Player,
|
||||
PlayerType,
|
||||
Relation,
|
||||
} from "../../game/Game";
|
||||
import { Difficulty, Game, Player, Relation } from "../../game/Game";
|
||||
import { PlayerType } from "../../game/GameUpdates";
|
||||
import { PseudoRandom } from "../../PseudoRandom";
|
||||
import { AllianceExtensionExecution } from "../alliance/AllianceExtensionExecution";
|
||||
import { AllianceRequestExecution } from "../alliance/AllianceRequestExecution";
|
||||
|
||||
@@ -2,11 +2,11 @@ import {
|
||||
Difficulty,
|
||||
Game,
|
||||
Player,
|
||||
PlayerType,
|
||||
Relation,
|
||||
TerraNullius,
|
||||
Tick,
|
||||
} from "../../game/Game";
|
||||
import { PlayerType } from "../../game/GameUpdates";
|
||||
import { PseudoRandom } from "../../PseudoRandom";
|
||||
import {
|
||||
boundingBoxCenter,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Game, PlayerType } from "../../game/Game";
|
||||
import { Game } from "../../game/Game";
|
||||
import { TileRef } from "../../game/GameMap";
|
||||
import { PlayerType } from "../../game/GameUpdates";
|
||||
import { PseudoRandom } from "../../PseudoRandom";
|
||||
import { GameID } from "../../Schemas";
|
||||
import { simpleHash } from "../../Util";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { AllianceRequest, Player, Tick } from "./Game";
|
||||
import { GameImpl } from "./GameImpl";
|
||||
import { AllianceRequestUpdate, GameUpdateType } from "./GameUpdates";
|
||||
import { GameUpdate, GameUpdateType } from "./GameUpdates";
|
||||
|
||||
export class AllianceRequestImpl implements AllianceRequest {
|
||||
private status_: "pending" | "accepted" | "rejected" = "pending";
|
||||
@@ -37,12 +37,14 @@ export class AllianceRequestImpl implements AllianceRequest {
|
||||
this.game.rejectAllianceRequest(this);
|
||||
}
|
||||
|
||||
toUpdate(): AllianceRequestUpdate {
|
||||
toUpdate(): GameUpdate {
|
||||
return {
|
||||
type: GameUpdateType.AllianceRequest,
|
||||
requestorID: this.requestor_.smallID(),
|
||||
recipientID: this.recipient_.smallID(),
|
||||
createdAt: this.tickCreated,
|
||||
allianceRequest: {
|
||||
requestorId: this.requestor_.smallID(),
|
||||
recipientId: this.recipient_.smallID(),
|
||||
createdAt: this.tickCreated,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
+16
-96
@@ -3,9 +3,14 @@ import { AllPlayersStats, ClientID } from "../Schemas";
|
||||
import { getClanTag } from "../Util";
|
||||
import { GameMap, TileRef } from "./GameMap";
|
||||
import {
|
||||
EmojiMessage,
|
||||
GameUpdate,
|
||||
GameUpdateType,
|
||||
PlayerUpdate,
|
||||
GameUpdateViewData,
|
||||
MessageCategory,
|
||||
MessageType,
|
||||
PlayerType,
|
||||
TrainType,
|
||||
UnitType,
|
||||
UnitUpdate,
|
||||
} from "./GameUpdates";
|
||||
import { RailNetwork } from "./RailNetwork";
|
||||
@@ -25,14 +30,9 @@ export type Gold = bigint;
|
||||
|
||||
export const AllPlayers = "AllPlayers" as const;
|
||||
|
||||
// export type GameUpdates = Record<GameUpdateType, GameUpdate[]>;
|
||||
// Create a type that maps GameUpdateType to its corresponding update type
|
||||
type UpdateTypeMap<T extends GameUpdateType> = Extract<GameUpdate, { type: T }>;
|
||||
|
||||
// Then use it to create the record type
|
||||
export type GameUpdates = {
|
||||
[K in GameUpdateType]: UpdateTypeMap<K>[];
|
||||
};
|
||||
export const AllUnitTypes = Object.values(UnitType).filter(
|
||||
(v): v is UnitType => typeof v === "number",
|
||||
) as UnitType[];
|
||||
|
||||
export interface MapPos {
|
||||
x: number;
|
||||
@@ -188,30 +188,6 @@ export interface UnitInfo {
|
||||
experimental?: boolean;
|
||||
}
|
||||
|
||||
export enum UnitType {
|
||||
TransportShip = "Transport",
|
||||
Warship = "Warship",
|
||||
Shell = "Shell",
|
||||
SAMMissile = "SAMMissile",
|
||||
Port = "Port",
|
||||
AtomBomb = "Atom Bomb",
|
||||
HydrogenBomb = "Hydrogen Bomb",
|
||||
TradeShip = "Trade Ship",
|
||||
MissileSilo = "Missile Silo",
|
||||
DefensePost = "Defense Post",
|
||||
SAMLauncher = "SAM Launcher",
|
||||
City = "City",
|
||||
MIRV = "MIRV",
|
||||
MIRVWarhead = "MIRV Warhead",
|
||||
Train = "Train",
|
||||
Factory = "Factory",
|
||||
}
|
||||
|
||||
export enum TrainType {
|
||||
Engine = "Engine",
|
||||
Carriage = "Carriage",
|
||||
}
|
||||
|
||||
const _structureTypes: ReadonlySet<UnitType> = new Set([
|
||||
UnitType.City,
|
||||
UnitType.DefensePost,
|
||||
@@ -290,7 +266,7 @@ export interface UnitParamsMap {
|
||||
}
|
||||
|
||||
// Type helper to get params type for a specific unit type
|
||||
export type UnitParams<T extends UnitType> = UnitParamsMap[T];
|
||||
export type UnitParams<T extends keyof UnitParamsMap> = UnitParamsMap[T];
|
||||
|
||||
export type AllUnitParams = UnitParamsMap[keyof UnitParamsMap];
|
||||
|
||||
@@ -347,12 +323,6 @@ export enum TerrainType {
|
||||
Ocean,
|
||||
}
|
||||
|
||||
export enum PlayerType {
|
||||
Bot = "BOT",
|
||||
Human = "HUMAN",
|
||||
FakeHuman = "FAKEHUMAN",
|
||||
}
|
||||
|
||||
export interface Execution {
|
||||
isActive(): boolean;
|
||||
activeDuringSpawnPhase(): boolean;
|
||||
@@ -579,7 +549,7 @@ export interface Player {
|
||||
buildUnit<T extends UnitType>(
|
||||
type: T,
|
||||
spawnTile: TileRef,
|
||||
params: UnitParams<T>,
|
||||
params: UnitParams<keyof UnitParamsMap>,
|
||||
): Unit;
|
||||
|
||||
// Returns the existing unit that can be upgraded,
|
||||
@@ -660,7 +630,7 @@ export interface Player {
|
||||
executeRetreat(attackID: string): void;
|
||||
|
||||
// Misc
|
||||
toUpdate(): PlayerUpdate;
|
||||
toUpdate(): GameUpdate;
|
||||
playerProfile(): PlayerProfile;
|
||||
// WARNING: this operation is expensive.
|
||||
bestTransportShipSpawn(tile: TileRef): TileRef | false;
|
||||
@@ -704,7 +674,7 @@ export interface Game extends GameMap {
|
||||
// Game State
|
||||
ticks(): Tick;
|
||||
inSpawnPhase(): boolean;
|
||||
executeNextTick(): GameUpdates;
|
||||
executeNextTick(): GameUpdateViewData;
|
||||
setWinner(winner: Player | Team, allPlayersStats: AllPlayersStats): void;
|
||||
config(): Config;
|
||||
|
||||
@@ -799,52 +769,8 @@ export interface PlayerInteraction {
|
||||
allianceExpiresAt?: Tick;
|
||||
}
|
||||
|
||||
export interface EmojiMessage {
|
||||
message: string;
|
||||
senderID: number;
|
||||
recipientID: number | typeof AllPlayers;
|
||||
createdAt: Tick;
|
||||
}
|
||||
|
||||
export enum MessageType {
|
||||
ATTACK_FAILED,
|
||||
ATTACK_CANCELLED,
|
||||
ATTACK_REQUEST,
|
||||
CONQUERED_PLAYER,
|
||||
MIRV_INBOUND,
|
||||
NUKE_INBOUND,
|
||||
HYDROGEN_BOMB_INBOUND,
|
||||
NAVAL_INVASION_INBOUND,
|
||||
SAM_MISS,
|
||||
SAM_HIT,
|
||||
CAPTURED_ENEMY_UNIT,
|
||||
UNIT_CAPTURED_BY_ENEMY,
|
||||
UNIT_DESTROYED,
|
||||
ALLIANCE_ACCEPTED,
|
||||
ALLIANCE_REJECTED,
|
||||
ALLIANCE_REQUEST,
|
||||
ALLIANCE_BROKEN,
|
||||
ALLIANCE_EXPIRED,
|
||||
SENT_GOLD_TO_PLAYER,
|
||||
RECEIVED_GOLD_FROM_PLAYER,
|
||||
RECEIVED_GOLD_FROM_TRADE,
|
||||
SENT_TROOPS_TO_PLAYER,
|
||||
RECEIVED_TROOPS_FROM_PLAYER,
|
||||
CHAT,
|
||||
RENEW_ALLIANCE,
|
||||
}
|
||||
|
||||
// Message categories used for filtering events in the EventsDisplay
|
||||
export enum MessageCategory {
|
||||
ATTACK = "ATTACK",
|
||||
NUKE = "NUKE",
|
||||
ALLIANCE = "ALLIANCE",
|
||||
TRADE = "TRADE",
|
||||
CHAT = "CHAT",
|
||||
}
|
||||
|
||||
// Ensures that all message types are included in a category
|
||||
export const MESSAGE_TYPE_CATEGORIES: Record<MessageType, MessageCategory> = {
|
||||
export const MESSAGE_TYPE_CATEGORIES: Record<number, MessageCategory> = {
|
||||
[MessageType.ATTACK_FAILED]: MessageCategory.ATTACK,
|
||||
[MessageType.ATTACK_CANCELLED]: MessageCategory.ATTACK,
|
||||
[MessageType.ATTACK_REQUEST]: MessageCategory.ATTACK,
|
||||
@@ -869,7 +795,7 @@ export const MESSAGE_TYPE_CATEGORIES: Record<MessageType, MessageCategory> = {
|
||||
[MessageType.RECEIVED_GOLD_FROM_TRADE]: MessageCategory.TRADE,
|
||||
[MessageType.SENT_TROOPS_TO_PLAYER]: MessageCategory.TRADE,
|
||||
[MessageType.RECEIVED_TROOPS_FROM_PLAYER]: MessageCategory.TRADE,
|
||||
[MessageType.CHAT]: MessageCategory.CHAT,
|
||||
[MessageType.CHAT]: MessageCategory.CHAT_CATEGORY,
|
||||
} as const;
|
||||
|
||||
/**
|
||||
@@ -878,9 +804,3 @@ export const MESSAGE_TYPE_CATEGORIES: Record<MessageType, MessageCategory> = {
|
||||
export function getMessageCategory(messageType: MessageType): MessageCategory {
|
||||
return MESSAGE_TYPE_CATEGORIES[messageType];
|
||||
}
|
||||
|
||||
export interface NameViewData {
|
||||
x: number;
|
||||
y: number;
|
||||
size: number;
|
||||
}
|
||||
|
||||
+105
-60
@@ -10,19 +10,15 @@ import {
|
||||
Cell,
|
||||
ColoredTeams,
|
||||
Duos,
|
||||
EmojiMessage,
|
||||
Execution,
|
||||
Game,
|
||||
GameMode,
|
||||
GameUpdates,
|
||||
HumansVsNations,
|
||||
MessageType,
|
||||
MutableAlliance,
|
||||
Nation,
|
||||
Player,
|
||||
PlayerID,
|
||||
PlayerInfo,
|
||||
PlayerType,
|
||||
Quads,
|
||||
Team,
|
||||
TerrainType,
|
||||
@@ -30,10 +26,18 @@ import {
|
||||
Trios,
|
||||
Unit,
|
||||
UnitInfo,
|
||||
UnitType,
|
||||
} from "./Game";
|
||||
import { GameMap, TileRef, TileUpdate } from "./GameMap";
|
||||
import { GameUpdate, GameUpdateType } from "./GameUpdates";
|
||||
import {
|
||||
EmojiMessage,
|
||||
GameUpdate,
|
||||
GameUpdates,
|
||||
GameUpdateType,
|
||||
GameUpdateViewData,
|
||||
MessageType,
|
||||
PlayerType,
|
||||
UnitType,
|
||||
} from "./GameUpdates";
|
||||
import { PlayerImpl } from "./PlayerImpl";
|
||||
import { RailNetwork } from "./RailNetwork";
|
||||
import { createRailNetwork } from "./RailNetworkImpl";
|
||||
@@ -75,7 +79,7 @@ export class GameImpl implements Game {
|
||||
private nextPlayerID = 1;
|
||||
private _nextUnitID = 1;
|
||||
|
||||
private updates: GameUpdates = createGameUpdatesMap();
|
||||
private gameViewData = createGameUpdateViewData();
|
||||
private unitGrid: UnitGrid;
|
||||
|
||||
private playerTeams: Team[];
|
||||
@@ -197,12 +201,17 @@ export class GameImpl implements Game {
|
||||
map(): GameMap {
|
||||
return this._map;
|
||||
}
|
||||
|
||||
miniMap(): GameMap {
|
||||
return this.miniGameMap;
|
||||
}
|
||||
|
||||
addTileUpdate(tile: TileRef) {
|
||||
this.gameViewData.tileUpdates.push(Number(this.toTileUpdate(tile)));
|
||||
}
|
||||
|
||||
addUpdate(update: GameUpdate) {
|
||||
(this.updates[update.type] as GameUpdate[]).push(update);
|
||||
this.gameViewData.updates[update.type].updates.push(update);
|
||||
}
|
||||
|
||||
nextUnitID(): number {
|
||||
@@ -219,10 +228,7 @@ export class GameImpl implements Game {
|
||||
return;
|
||||
}
|
||||
this._map.setFallout(tile, value);
|
||||
this.addUpdate({
|
||||
type: GameUpdateType.Tile,
|
||||
update: this.toTileUpdate(tile),
|
||||
});
|
||||
this.addTileUpdate(tile);
|
||||
}
|
||||
|
||||
units(...types: UnitType[]): Unit[] {
|
||||
@@ -311,8 +317,14 @@ export class GameImpl implements Game {
|
||||
|
||||
this.addUpdate({
|
||||
type: GameUpdateType.AllianceRequestReply,
|
||||
request: request.toUpdate(),
|
||||
accepted: true,
|
||||
allianceRequestReply: {
|
||||
request: {
|
||||
requestorId: requestor.smallID(),
|
||||
recipientId: recipient.smallID(),
|
||||
createdAt: request.createdAt(),
|
||||
},
|
||||
accepted: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -325,8 +337,14 @@ export class GameImpl implements Game {
|
||||
);
|
||||
this.addUpdate({
|
||||
type: GameUpdateType.AllianceRequestReply,
|
||||
request: request.toUpdate(),
|
||||
accepted: false,
|
||||
allianceRequestReply: {
|
||||
request: {
|
||||
requestorId: request.requestor().smallID(),
|
||||
recipientId: request.recipient().smallID(),
|
||||
createdAt: request.createdAt(),
|
||||
},
|
||||
accepted: false,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -345,8 +363,8 @@ export class GameImpl implements Game {
|
||||
return this._ticks;
|
||||
}
|
||||
|
||||
executeNextTick(): GameUpdates {
|
||||
this.updates = createGameUpdatesMap();
|
||||
executeNextTick(): GameUpdateViewData {
|
||||
this.gameViewData = createGameUpdateViewData();
|
||||
this.execs.forEach((e) => {
|
||||
if (
|
||||
(!this.inSpawnPhase() || e.activeDuringSpawnPhase()) &&
|
||||
@@ -377,12 +395,14 @@ export class GameImpl implements Game {
|
||||
if (this.ticks() % 10 === 0) {
|
||||
this.addUpdate({
|
||||
type: GameUpdateType.Hash,
|
||||
tick: this.ticks(),
|
||||
hash: this.hash(),
|
||||
hash: {
|
||||
tick: this.ticks(),
|
||||
hash: this.hash(),
|
||||
},
|
||||
});
|
||||
}
|
||||
this._ticks++;
|
||||
return this.updates;
|
||||
return this.gameViewData;
|
||||
}
|
||||
|
||||
private hash(): number {
|
||||
@@ -556,10 +576,7 @@ export class GameImpl implements Game {
|
||||
owner._lastTileChange = this._ticks;
|
||||
this.updateBorders(tile);
|
||||
this._map.setFallout(tile, false);
|
||||
this.addUpdate({
|
||||
type: GameUpdateType.Tile,
|
||||
update: this.toTileUpdate(tile),
|
||||
});
|
||||
this.addTileUpdate(tile);
|
||||
}
|
||||
|
||||
relinquish(tile: TileRef) {
|
||||
@@ -577,10 +594,7 @@ export class GameImpl implements Game {
|
||||
|
||||
this._map.setOwnerID(tile, 0);
|
||||
this.updateBorders(tile);
|
||||
this.addUpdate({
|
||||
type: GameUpdateType.Tile,
|
||||
update: this.toTileUpdate(tile),
|
||||
});
|
||||
this.addTileUpdate(tile);
|
||||
}
|
||||
|
||||
private updateBorders(tile: TileRef) {
|
||||
@@ -616,8 +630,10 @@ export class GameImpl implements Game {
|
||||
target(targeter: Player, target: Player) {
|
||||
this.addUpdate({
|
||||
type: GameUpdateType.TargetPlayer,
|
||||
playerID: targeter.smallID(),
|
||||
targetID: target.smallID(),
|
||||
targetPlayer: {
|
||||
playerId: targeter.smallID(),
|
||||
targetId: target.smallID(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -647,8 +663,10 @@ export class GameImpl implements Game {
|
||||
this.alliances_ = this.alliances_.filter((a) => a !== alliances[0]);
|
||||
this.addUpdate({
|
||||
type: GameUpdateType.BrokeAlliance,
|
||||
traitorID: breaker.smallID(),
|
||||
betrayedID: other.smallID(),
|
||||
brokeAlliance: {
|
||||
traitorId: breaker.smallID(),
|
||||
betrayedId: other.smallID(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -666,23 +684,29 @@ export class GameImpl implements Game {
|
||||
this.alliances_ = this.alliances_.filter((a) => a !== alliances[0]);
|
||||
this.addUpdate({
|
||||
type: GameUpdateType.AllianceExpired,
|
||||
player1ID: alliance.requestor().smallID(),
|
||||
player2ID: alliance.recipient().smallID(),
|
||||
allianceExpired: {
|
||||
player1Id: alliance.requestor().smallID(),
|
||||
player2Id: alliance.recipient().smallID(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
sendEmojiUpdate(msg: EmojiMessage): void {
|
||||
this.addUpdate({
|
||||
type: GameUpdateType.Emoji,
|
||||
emoji: msg,
|
||||
emoji: {
|
||||
emoji: msg,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
setWinner(winner: Player | Team, allPlayersStats: AllPlayersStats): void {
|
||||
this.addUpdate({
|
||||
type: GameUpdateType.Win,
|
||||
winner: this.makeWinner(winner),
|
||||
allPlayersStats,
|
||||
win: {
|
||||
winner: JSON.stringify(this.makeWinner(winner)),
|
||||
stats: JSON.stringify(allPlayersStats),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -718,7 +742,7 @@ export class GameImpl implements Game {
|
||||
type: MessageType,
|
||||
playerID: PlayerID | null,
|
||||
goldAmount?: bigint,
|
||||
params?: Record<string, string | number>,
|
||||
params?: Record<string, string>,
|
||||
): void {
|
||||
let id: number | null = null;
|
||||
if (playerID !== null) {
|
||||
@@ -726,11 +750,13 @@ export class GameImpl implements Game {
|
||||
}
|
||||
this.addUpdate({
|
||||
type: GameUpdateType.DisplayEvent,
|
||||
messageType: type,
|
||||
message: message,
|
||||
playerID: id,
|
||||
goldAmount: goldAmount,
|
||||
params: params,
|
||||
displayMessage: {
|
||||
message: message,
|
||||
messageType: type,
|
||||
playerId: id ?? undefined,
|
||||
goldAmount: Number(goldAmount),
|
||||
params: params ?? {},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -748,12 +774,14 @@ export class GameImpl implements Game {
|
||||
}
|
||||
this.addUpdate({
|
||||
type: GameUpdateType.DisplayChatEvent,
|
||||
key: message,
|
||||
category: category,
|
||||
target: target,
|
||||
playerID: id,
|
||||
isFrom,
|
||||
recipient: recipient,
|
||||
displayChatMessage: {
|
||||
key: message,
|
||||
category: category,
|
||||
target: target,
|
||||
playerId: id ?? undefined,
|
||||
isFrom: isFrom,
|
||||
recipient: recipient,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -767,10 +795,12 @@ export class GameImpl implements Game {
|
||||
|
||||
this.addUpdate({
|
||||
type: GameUpdateType.UnitIncoming,
|
||||
unitID: unitID,
|
||||
message: message,
|
||||
messageType: type,
|
||||
playerID: id,
|
||||
unitIncoming: {
|
||||
unitId: unitID,
|
||||
message: message,
|
||||
messageType: type,
|
||||
playerId: id,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -964,9 +994,11 @@ export class GameImpl implements Game {
|
||||
conquered.removeGold(gold);
|
||||
this.addUpdate({
|
||||
type: GameUpdateType.ConquestEvent,
|
||||
conquerorId: conqueror.id(),
|
||||
conqueredId: conquered.id(),
|
||||
gold,
|
||||
conquest: {
|
||||
conquerorId: conqueror.smallID(),
|
||||
conqueredId: conquered.smallID(),
|
||||
gold: Number(gold),
|
||||
},
|
||||
});
|
||||
|
||||
// Record stats
|
||||
@@ -975,12 +1007,25 @@ export class GameImpl implements Game {
|
||||
}
|
||||
|
||||
// Or a more dynamic approach that will catch new enum values:
|
||||
const createGameUpdatesMap = (): GameUpdates => {
|
||||
const map = {} as GameUpdates;
|
||||
const createGameUpdatesMap = (): Record<GameUpdateType, GameUpdates> => {
|
||||
const map = {} as Record<GameUpdateType, GameUpdates>;
|
||||
Object.values(GameUpdateType)
|
||||
.filter((key) => !isNaN(Number(key))) // Filter out reverse mappings
|
||||
.forEach((key) => {
|
||||
map[key as GameUpdateType] = [];
|
||||
map[key as GameUpdateType] = {
|
||||
type: key as GameUpdateType,
|
||||
updates: [],
|
||||
};
|
||||
});
|
||||
return map;
|
||||
};
|
||||
|
||||
const createGameUpdateViewData = (): GameUpdateViewData => {
|
||||
return {
|
||||
tick: 0,
|
||||
updates: createGameUpdatesMap(),
|
||||
tileUpdates: [],
|
||||
playerNameViewData: {},
|
||||
tickExecutionDuration: undefined,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -0,0 +1,337 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package game;
|
||||
|
||||
enum PlayerType {
|
||||
Bot = 0;
|
||||
Human = 1;
|
||||
FakeHuman = 2;
|
||||
}
|
||||
|
||||
enum UnitType {
|
||||
TransportShip = 0;
|
||||
Warship = 1;
|
||||
Shell = 2;
|
||||
SAMMissile = 3;
|
||||
Port = 4;
|
||||
AtomBomb = 5;
|
||||
HydrogenBomb = 6;
|
||||
TradeShip = 7;
|
||||
MissileSilo = 8;
|
||||
DefensePost = 9;
|
||||
SAMLauncher = 10;
|
||||
City = 11;
|
||||
MIRV = 12;
|
||||
MIRVWarhead = 13;
|
||||
Train = 14;
|
||||
Factory = 15;
|
||||
}
|
||||
|
||||
enum TrainType {
|
||||
Engine = 0;
|
||||
Carriage = 1;
|
||||
}
|
||||
|
||||
message NameViewData {
|
||||
int32 x = 1;
|
||||
int32 y = 2;
|
||||
int32 size = 3;
|
||||
}
|
||||
|
||||
message EmojiMessage {
|
||||
int32 sender_id = 1;
|
||||
string emoji = 2;
|
||||
oneof recipient {
|
||||
bool allPlayers = 3;
|
||||
int32 recipient_id = 4;
|
||||
}
|
||||
int32 createdAt = 5;
|
||||
}
|
||||
|
||||
// Enums
|
||||
enum GameUpdateType {
|
||||
Tile = 0;
|
||||
Unit = 1;
|
||||
Player = 2;
|
||||
DisplayEvent = 3;
|
||||
DisplayChatEvent = 4;
|
||||
AllianceRequest = 5;
|
||||
AllianceRequestReply = 6;
|
||||
BrokeAlliance = 7;
|
||||
AllianceExpired = 8;
|
||||
AllianceExtension = 9;
|
||||
TargetPlayer = 10;
|
||||
Emoji = 11;
|
||||
Win = 12;
|
||||
Hash = 13;
|
||||
UnitIncoming = 14;
|
||||
BonusEvent = 15;
|
||||
RailroadEvent = 16;
|
||||
ConquestEvent = 17;
|
||||
EmbargoEvent = 18;
|
||||
}
|
||||
|
||||
enum MessageType {
|
||||
messageTypeUnspecified = 0;
|
||||
ATTACK_FAILED = 1;
|
||||
ATTACK_CANCELLED = 2;
|
||||
ATTACK_REQUEST = 3;
|
||||
CONQUERED_PLAYER = 4;
|
||||
MIRV_INBOUND = 5;
|
||||
NUKE_INBOUND = 6;
|
||||
HYDROGEN_BOMB_INBOUND = 7;
|
||||
NAVAL_INVASION_INBOUND = 8;
|
||||
SAM_MISS = 9;
|
||||
SAM_HIT = 10;
|
||||
CAPTURED_ENEMY_UNIT = 11;
|
||||
UNIT_CAPTURED_BY_ENEMY = 12;
|
||||
UNIT_DESTROYED = 13;
|
||||
ALLIANCE_ACCEPTED = 14;
|
||||
ALLIANCE_REJECTED = 15;
|
||||
ALLIANCE_REQUEST = 16;
|
||||
ALLIANCE_BROKEN = 17;
|
||||
ALLIANCE_EXPIRED = 18;
|
||||
SENT_GOLD_TO_PLAYER = 19;
|
||||
RECEIVED_GOLD_FROM_PLAYER = 20;
|
||||
RECEIVED_GOLD_FROM_TRADE = 21;
|
||||
SENT_TROOPS_TO_PLAYER = 22;
|
||||
RECEIVED_TROOPS_FROM_PLAYER = 23;
|
||||
CHAT = 24;
|
||||
RENEW_ALLIANCE = 25;
|
||||
}
|
||||
|
||||
enum MessageCategory {
|
||||
messageCategoryUnspecified = 0;
|
||||
ATTACK = 1;
|
||||
NUKE = 2;
|
||||
ALLIANCE = 3;
|
||||
TRADE = 4;
|
||||
CHAT_CATEGORY = 5;
|
||||
}
|
||||
|
||||
enum RailType {
|
||||
vertical = 0;
|
||||
horizontal = 1;
|
||||
topLeft = 2;
|
||||
topRight = 3;
|
||||
bottomLeft = 4;
|
||||
bottomRight = 5;
|
||||
}
|
||||
|
||||
// Update messages
|
||||
message BonusEventUpdate {
|
||||
string player = 1;
|
||||
int64 tile = 2; // TileRef encoded as int64
|
||||
int64 gold = 3;
|
||||
int64 troops = 4;
|
||||
}
|
||||
|
||||
message RailTile {
|
||||
int64 tile = 1; // TileRef encoded as int64
|
||||
RailType rail_type = 2;
|
||||
}
|
||||
|
||||
message RailroadUpdate {
|
||||
bool is_active = 1;
|
||||
repeated RailTile rail_tiles = 2;
|
||||
}
|
||||
|
||||
message ConquestUpdate {
|
||||
int32 conqueror_id = 1;
|
||||
int32 conquered_id = 2;
|
||||
int64 gold = 3;
|
||||
}
|
||||
|
||||
message UnitUpdate {
|
||||
GameUpdateType type = 22;
|
||||
UnitType unit_type = 1;
|
||||
int32 troops = 2;
|
||||
int32 id = 3;
|
||||
int32 owner_id = 4;
|
||||
optional int32 last_owner_id = 5;
|
||||
int64 pos = 6; // TileRef encoded as int64
|
||||
int64 last_pos = 7; // TileRef encoded as int64
|
||||
bool is_active = 8;
|
||||
bool reached_target = 9;
|
||||
bool retreating = 10;
|
||||
bool targetable = 11;
|
||||
oneof marked_for_deletion_value {
|
||||
int32 marked_for_deletion = 12;
|
||||
}
|
||||
optional int32 target_unit_id = 13; // Only for trade ships
|
||||
optional int64 target_tile = 14; // TileRef encoded as int64, only for nukes
|
||||
optional int32 health = 15;
|
||||
optional bool under_construction = 16;
|
||||
repeated int32 missile_timer_queue = 17;
|
||||
int32 level = 18;
|
||||
bool has_train_station = 19;
|
||||
optional TrainType train_type = 20; // Only for trains
|
||||
optional bool loaded = 21; // Only for trains
|
||||
}
|
||||
|
||||
message AttackUpdate {
|
||||
int32 attacker_id = 1;
|
||||
int32 target_id = 2;
|
||||
int32 troops = 3;
|
||||
string id = 4;
|
||||
bool retreating = 5;
|
||||
}
|
||||
|
||||
message AllianceView {
|
||||
int32 id = 1;
|
||||
string other = 2;
|
||||
int32 created_at = 3;
|
||||
int32 expires_at = 4;
|
||||
bool has_extension_request = 5;
|
||||
}
|
||||
|
||||
message PlayerUpdate {
|
||||
optional NameViewData name_view_data = 1;
|
||||
optional string client_id = 2;
|
||||
string name = 3;
|
||||
string display_name = 4;
|
||||
string id = 5;
|
||||
optional string team = 6;
|
||||
int32 small_id = 7;
|
||||
PlayerType player_type = 8;
|
||||
bool is_alive = 9;
|
||||
bool is_disconnected = 10;
|
||||
int32 tiles_owned = 11;
|
||||
uint64 gold = 12;
|
||||
int32 troops = 13;
|
||||
repeated int32 allies = 14;
|
||||
repeated string embargoes = 15;
|
||||
bool is_traitor = 16;
|
||||
optional int32 traitor_remaining_ticks = 17;
|
||||
repeated int32 targets = 18;
|
||||
repeated EmojiMessage outgoing_emojis = 19;
|
||||
repeated AttackUpdate outgoing_attacks = 20;
|
||||
repeated AttackUpdate incoming_attacks = 21;
|
||||
repeated string outgoing_alliance_requests = 22;
|
||||
repeated AllianceView alliances = 23;
|
||||
bool has_spawned = 24;
|
||||
int32 betrayals = 25;
|
||||
int32 last_delete_unit_tick = 26;
|
||||
}
|
||||
|
||||
message AllianceRequestUpdate {
|
||||
int32 requestor_id = 1;
|
||||
int32 recipient_id = 2;
|
||||
int32 created_at = 3;
|
||||
}
|
||||
|
||||
message AllianceRequestReplyUpdate {
|
||||
AllianceRequestUpdate request = 1;
|
||||
bool accepted = 2;
|
||||
}
|
||||
|
||||
message BrokeAllianceUpdate {
|
||||
int32 traitor_id = 1;
|
||||
int32 betrayed_id = 2;
|
||||
}
|
||||
|
||||
message AllianceExpiredUpdate {
|
||||
int32 player1_id = 1;
|
||||
int32 player2_id = 2;
|
||||
}
|
||||
|
||||
message AllianceExtensionUpdate {
|
||||
string player_id = 1;
|
||||
int32 alliance_id = 2;
|
||||
}
|
||||
|
||||
message TargetPlayerUpdate {
|
||||
int32 player_id = 1;
|
||||
int32 target_id = 2;
|
||||
}
|
||||
|
||||
message EmojiUpdate {
|
||||
EmojiMessage emoji = 1;
|
||||
}
|
||||
|
||||
message DisplayMessageUpdate {
|
||||
string message = 1;
|
||||
MessageType message_type = 2;
|
||||
optional int64 gold_amount = 3;
|
||||
optional int64 player_id = 4;
|
||||
map<string, string> params = 5;
|
||||
}
|
||||
|
||||
message DisplayChatMessageUpdate {
|
||||
string key = 1;
|
||||
string category = 2;
|
||||
optional string target = 3;
|
||||
optional int32 player_id = 4;
|
||||
bool is_from = 5;
|
||||
string recipient = 6;
|
||||
}
|
||||
|
||||
message WinUpdate {
|
||||
string winner = 1;
|
||||
string stats = 2;
|
||||
}
|
||||
|
||||
message HashUpdate {
|
||||
int32 tick = 1;
|
||||
int32 hash = 2;
|
||||
}
|
||||
|
||||
message UnitIncomingUpdate {
|
||||
int32 unit_id = 1;
|
||||
string message = 2;
|
||||
MessageType message_type = 3;
|
||||
int32 player_id = 4;
|
||||
}
|
||||
|
||||
message EmbargoUpdate {
|
||||
enum EmbargoEvent {
|
||||
start = 0;
|
||||
stop = 1;
|
||||
}
|
||||
EmbargoEvent event = 1;
|
||||
int32 player_id = 2;
|
||||
int32 embargoed_id = 3;
|
||||
}
|
||||
|
||||
// Main GameUpdate message using oneof for polymorphism
|
||||
message GameUpdate {
|
||||
GameUpdateType type = 1;
|
||||
oneof update {
|
||||
UnitUpdate unit = 3;
|
||||
PlayerUpdate player = 4;
|
||||
AllianceRequestUpdate alliance_request = 5;
|
||||
AllianceRequestReplyUpdate alliance_request_reply = 6;
|
||||
BrokeAllianceUpdate broke_alliance = 7;
|
||||
AllianceExpiredUpdate alliance_expired = 8;
|
||||
DisplayMessageUpdate display_message = 9;
|
||||
DisplayChatMessageUpdate display_chat_message = 10;
|
||||
TargetPlayerUpdate target_player = 11;
|
||||
EmojiUpdate emoji = 12;
|
||||
WinUpdate win = 13;
|
||||
HashUpdate hash = 14;
|
||||
UnitIncomingUpdate unit_incoming = 15;
|
||||
AllianceExtensionUpdate alliance_extension = 16;
|
||||
BonusEventUpdate bonus_event = 17;
|
||||
RailroadUpdate railroad = 18;
|
||||
ConquestUpdate conquest = 19;
|
||||
EmbargoUpdate embargo = 20;
|
||||
}
|
||||
}
|
||||
|
||||
message GameUpdates {
|
||||
GameUpdateType type = 1;
|
||||
repeated GameUpdate updates = 2;
|
||||
}
|
||||
|
||||
message GameUpdateViewData {
|
||||
int32 tick = 1;
|
||||
map<int32, GameUpdates> updates = 2;
|
||||
repeated int64 tile_updates = 3;
|
||||
map<string, NameViewData> player_name_view_data = 4;
|
||||
optional double tick_execution_duration = 5;
|
||||
}
|
||||
|
||||
message ErrorUpdate {
|
||||
string err_msg = 1;
|
||||
optional string stack = 2;
|
||||
}
|
||||
+5388
-161
File diff suppressed because it is too large
Load Diff
+48
-45
@@ -8,30 +8,30 @@ import { createRandomName } from "../Util";
|
||||
import { WorkerClient } from "../worker/WorkerClient";
|
||||
import {
|
||||
Cell,
|
||||
EmojiMessage,
|
||||
GameUpdates,
|
||||
Gold,
|
||||
NameViewData,
|
||||
PlayerActions,
|
||||
PlayerBorderTiles,
|
||||
PlayerID,
|
||||
PlayerProfile,
|
||||
PlayerType,
|
||||
Team,
|
||||
TerrainType,
|
||||
TerraNullius,
|
||||
Tick,
|
||||
TrainType,
|
||||
UnitInfo,
|
||||
UnitType,
|
||||
} from "./Game";
|
||||
import { GameMap, TileRef, TileUpdate } from "./GameMap";
|
||||
import {
|
||||
AllianceView,
|
||||
AttackUpdate,
|
||||
EmojiMessage,
|
||||
GameUpdates,
|
||||
GameUpdateType,
|
||||
GameUpdateViewData,
|
||||
NameViewData,
|
||||
PlayerType,
|
||||
PlayerUpdate,
|
||||
TrainType,
|
||||
UnitType,
|
||||
UnitUpdate,
|
||||
} from "./GameUpdates";
|
||||
import { TerrainMapData } from "./TerrainMapLoader";
|
||||
@@ -88,7 +88,7 @@ export class UnitView {
|
||||
}
|
||||
|
||||
markedForDeletion(): number | false {
|
||||
return this.data.markedForDeletion;
|
||||
return this.data.markedForDeletion ?? false;
|
||||
}
|
||||
|
||||
type(): UnitType {
|
||||
@@ -107,7 +107,7 @@ export class UnitView {
|
||||
return this.data.pos;
|
||||
}
|
||||
owner(): PlayerView {
|
||||
return this.gameView.playerBySmallID(this.data.ownerID)! as PlayerView;
|
||||
return this.gameView.playerBySmallID(this.data.ownerId)! as PlayerView;
|
||||
}
|
||||
isActive(): boolean {
|
||||
return this.data.isActive;
|
||||
@@ -194,7 +194,7 @@ export class PlayerView {
|
||||
public nameData: NameViewData,
|
||||
public cosmetics: PlayerCosmetics,
|
||||
) {
|
||||
if (data.clientID === game.myClientID()) {
|
||||
if (data.clientId === game.myClientID()) {
|
||||
this.anonymousName = this.data.name;
|
||||
} else {
|
||||
this.anonymousName = createRandomName(
|
||||
@@ -239,7 +239,7 @@ export class PlayerView {
|
||||
.structureColors(this._territoryColor);
|
||||
|
||||
const maybeFocusedBorderColor =
|
||||
this.game.myClientID() === this.data.clientID
|
||||
this.game.myClientID() === this.data.clientId
|
||||
? this.game.config().theme().focusedBorderColor()
|
||||
: defaultBorderColor;
|
||||
|
||||
@@ -327,7 +327,7 @@ export class PlayerView {
|
||||
}
|
||||
|
||||
smallID(): number {
|
||||
return this.data.smallID;
|
||||
return this.data.smallId;
|
||||
}
|
||||
|
||||
name(): string {
|
||||
@@ -342,7 +342,7 @@ export class PlayerView {
|
||||
}
|
||||
|
||||
clientID(): ClientID | null {
|
||||
return this.data.clientID;
|
||||
return this.data.clientId ?? null;
|
||||
}
|
||||
id(): PlayerID {
|
||||
return this.data.id;
|
||||
@@ -373,7 +373,7 @@ export class PlayerView {
|
||||
);
|
||||
}
|
||||
gold(): Gold {
|
||||
return this.data.gold;
|
||||
return BigInt(this.data.gold);
|
||||
}
|
||||
|
||||
troops(): number {
|
||||
@@ -412,7 +412,7 @@ export class PlayerView {
|
||||
}
|
||||
|
||||
hasEmbargoAgainst(other: PlayerView): boolean {
|
||||
return this.data.embargoes.has(other.id());
|
||||
return this.data.embargoes.some((id) => id === other.id());
|
||||
}
|
||||
|
||||
hasEmbargo(other: PlayerView): boolean {
|
||||
@@ -506,8 +506,8 @@ export class GameView implements GameMap {
|
||||
return this._map.isOnEdgeOfMap(ref);
|
||||
}
|
||||
|
||||
public updatesSinceLastTick(): GameUpdates | null {
|
||||
return this.lastUpdate?.updates ?? null;
|
||||
public updatesSinceLastTick(): { [key: number]: GameUpdates } {
|
||||
return this.lastUpdate!.updates;
|
||||
}
|
||||
|
||||
public update(gu: GameUpdateViewData) {
|
||||
@@ -517,34 +517,36 @@ export class GameView implements GameMap {
|
||||
this.lastUpdate = gu;
|
||||
|
||||
this.updatedTiles = [];
|
||||
this.lastUpdate.packedTileUpdates.forEach((tu) => {
|
||||
this.updatedTiles.push(this.updateTile(tu));
|
||||
this.lastUpdate.tileUpdates.forEach((tu) => {
|
||||
this.updatedTiles.push(this.updateTile(BigInt(tu)));
|
||||
});
|
||||
|
||||
if (gu.updates === null) {
|
||||
throw new Error("lastUpdate.updates not initialized");
|
||||
}
|
||||
gu.updates[GameUpdateType.Player].forEach((pu) => {
|
||||
this.smallIDToID.set(pu.smallID, pu.id);
|
||||
const player = this._players.get(pu.id);
|
||||
if (player !== undefined) {
|
||||
player.data = pu;
|
||||
player.nameData = gu.playerNameViewData[pu.id];
|
||||
} else {
|
||||
this._players.set(
|
||||
pu.id,
|
||||
new PlayerView(
|
||||
this,
|
||||
pu,
|
||||
gu.playerNameViewData[pu.id],
|
||||
// First check human by clientID, then check nation by name.
|
||||
this._cosmetics.get(pu.clientID ?? "") ??
|
||||
this._cosmetics.get(pu.name) ??
|
||||
{},
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
gu.updates[GameUpdateType.Player].updates
|
||||
.map((pu) => pu.player!)
|
||||
.forEach((pu) => {
|
||||
this.smallIDToID.set(pu.smallId, pu.id);
|
||||
const player = this._players.get(pu.id);
|
||||
if (player !== undefined) {
|
||||
player.data = pu;
|
||||
player.nameData = gu.playerNameViewData[pu.id];
|
||||
} else {
|
||||
this._players.set(
|
||||
pu.id,
|
||||
new PlayerView(
|
||||
this,
|
||||
pu,
|
||||
gu.playerNameViewData[pu.id],
|
||||
// First check human by clientID, then check nation by name.
|
||||
this._cosmetics.get(pu.clientId ?? "") ??
|
||||
this._cosmetics.get(pu.name) ??
|
||||
{},
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
this._myPlayer ??= this.playerByClientID(this._myClientID);
|
||||
|
||||
@@ -552,16 +554,17 @@ export class GameView implements GameMap {
|
||||
unit._wasUpdated = false;
|
||||
unit.lastPos = unit.lastPos.slice(-1);
|
||||
}
|
||||
gu.updates[GameUpdateType.Unit].forEach((update) => {
|
||||
let unit = this._units.get(update.id);
|
||||
gu.updates[GameUpdateType.Unit].updates.forEach((update) => {
|
||||
const ud = update.unit!;
|
||||
let unit = this._units.get(ud.id);
|
||||
if (unit !== undefined) {
|
||||
unit.update(update);
|
||||
unit.update(ud);
|
||||
} else {
|
||||
unit = new UnitView(this, update);
|
||||
this._units.set(update.id, unit);
|
||||
unit = new UnitView(this, ud);
|
||||
this._units.set(ud.id, unit);
|
||||
this.unitGrid.addUnit(unit);
|
||||
}
|
||||
if (!update.isActive) {
|
||||
if (!ud.isActive) {
|
||||
this.unitGrid.removeUnit(unit);
|
||||
} else if (unit.tile() !== unit.lastTile()) {
|
||||
this.unitGrid.updateUnitCell(unit);
|
||||
|
||||
+91
-81
@@ -14,35 +14,38 @@ import {
|
||||
Alliance,
|
||||
AllianceRequest,
|
||||
AllPlayers,
|
||||
AllUnitTypes,
|
||||
Attack,
|
||||
BuildableUnit,
|
||||
Cell,
|
||||
ColoredTeams,
|
||||
Embargo,
|
||||
EmojiMessage,
|
||||
Gold,
|
||||
MessageType,
|
||||
MutableAlliance,
|
||||
Player,
|
||||
PlayerID,
|
||||
PlayerInfo,
|
||||
PlayerProfile,
|
||||
PlayerType,
|
||||
Relation,
|
||||
Team,
|
||||
TerraNullius,
|
||||
Tick,
|
||||
Unit,
|
||||
UnitParams,
|
||||
UnitType,
|
||||
UnitParamsMap,
|
||||
} from "./Game";
|
||||
import { GameImpl } from "./GameImpl";
|
||||
import { andFN, manhattanDistFN, TileRef } from "./GameMap";
|
||||
import {
|
||||
AllianceView,
|
||||
AttackUpdate,
|
||||
EmbargoUpdate_EmbargoEvent,
|
||||
EmojiMessage,
|
||||
GameUpdate,
|
||||
GameUpdateType,
|
||||
PlayerUpdate,
|
||||
MessageType,
|
||||
PlayerType,
|
||||
UnitType,
|
||||
} from "./GameUpdates";
|
||||
import {
|
||||
bestShoreDeploymentSource,
|
||||
@@ -119,66 +122,66 @@ export class PlayerImpl implements Player {
|
||||
|
||||
largestClusterBoundingBox: { min: Cell; max: Cell } | null;
|
||||
|
||||
toUpdate(): PlayerUpdate {
|
||||
const outgoingAllianceRequests = this.outgoingAllianceRequests().map((ar) =>
|
||||
ar.recipient().id(),
|
||||
);
|
||||
|
||||
toUpdate(): GameUpdate {
|
||||
return {
|
||||
type: GameUpdateType.Player,
|
||||
clientID: this.clientID(),
|
||||
name: this.name(),
|
||||
displayName: this.displayName(),
|
||||
id: this.id(),
|
||||
team: this.team() ?? undefined,
|
||||
smallID: this.smallID(),
|
||||
playerType: this.type(),
|
||||
isAlive: this.isAlive(),
|
||||
isDisconnected: this.isDisconnected(),
|
||||
tilesOwned: this.numTilesOwned(),
|
||||
gold: this._gold,
|
||||
troops: this.troops(),
|
||||
allies: this.alliances().map((a) => a.other(this).smallID()),
|
||||
embargoes: new Set([...this.embargoes.keys()].map((p) => p.toString())),
|
||||
isTraitor: this.isTraitor(),
|
||||
traitorRemainingTicks: this.getTraitorRemainingTicks(),
|
||||
targets: this.targets().map((p) => p.smallID()),
|
||||
outgoingEmojis: this.outgoingEmojis(),
|
||||
outgoingAttacks: this._outgoingAttacks.map((a) => {
|
||||
return {
|
||||
attackerID: a.attacker().smallID(),
|
||||
targetID: a.target().smallID(),
|
||||
troops: a.troops(),
|
||||
id: a.id(),
|
||||
retreating: a.retreating(),
|
||||
} satisfies AttackUpdate;
|
||||
}),
|
||||
incomingAttacks: this._incomingAttacks.map((a) => {
|
||||
return {
|
||||
attackerID: a.attacker().smallID(),
|
||||
targetID: a.target().smallID(),
|
||||
troops: a.troops(),
|
||||
id: a.id(),
|
||||
retreating: a.retreating(),
|
||||
} satisfies AttackUpdate;
|
||||
}),
|
||||
outgoingAllianceRequests: outgoingAllianceRequests,
|
||||
alliances: this.alliances().map(
|
||||
(a) =>
|
||||
({
|
||||
player: {
|
||||
clientId: this.clientID() ?? undefined,
|
||||
name: this.name(),
|
||||
displayName: this.displayName(),
|
||||
id: this.id(),
|
||||
team: this.team() ?? undefined,
|
||||
smallId: this.smallID(),
|
||||
playerType: this.type(),
|
||||
isAlive: this.isAlive(),
|
||||
isDisconnected: this.isDisconnected(),
|
||||
tilesOwned: this.numTilesOwned(),
|
||||
gold: Number(this._gold),
|
||||
troops: this.troops(),
|
||||
allies: this.alliances().map((a) => a.other(this).smallID()),
|
||||
embargoes: [...this.embargoes.keys()].map((p) => p.toString()),
|
||||
isTraitor: this.isTraitor(),
|
||||
traitorRemainingTicks: this.getTraitorRemainingTicks(),
|
||||
targets: this.targets().map((p) => p.smallID()),
|
||||
outgoingEmojis: this.outgoingEmojis(),
|
||||
outgoingAttacks: this._outgoingAttacks.map((a) => {
|
||||
return {
|
||||
attackerId: a.attacker().smallID(),
|
||||
targetId: a.target().smallID(),
|
||||
troops: a.troops(),
|
||||
id: a.id(),
|
||||
other: a.other(this).id(),
|
||||
createdAt: a.createdAt(),
|
||||
expiresAt: a.expiresAt(),
|
||||
hasExtensionRequest:
|
||||
a.expiresAt() <=
|
||||
this.mg.ticks() +
|
||||
this.mg.config().allianceExtensionPromptOffset(),
|
||||
}) satisfies AllianceView,
|
||||
),
|
||||
hasSpawned: this.hasSpawned(),
|
||||
betrayals: this._betrayalCount,
|
||||
lastDeleteUnitTick: this.lastDeleteUnitTick,
|
||||
retreating: a.retreating(),
|
||||
} satisfies AttackUpdate;
|
||||
}),
|
||||
incomingAttacks: this._incomingAttacks.map((a) => {
|
||||
return {
|
||||
attackerId: a.attacker().smallID(),
|
||||
targetId: a.target().smallID(),
|
||||
troops: a.troops(),
|
||||
id: a.id(),
|
||||
retreating: a.retreating(),
|
||||
} satisfies AttackUpdate;
|
||||
}),
|
||||
outgoingAllianceRequests: this.outgoingAllianceRequests().map((ar) =>
|
||||
ar.recipient().id(),
|
||||
),
|
||||
alliances: this.alliances().map(
|
||||
(a) =>
|
||||
({
|
||||
id: a.id(),
|
||||
other: a.other(this).id(),
|
||||
createdAt: a.createdAt(),
|
||||
expiresAt: a.expiresAt(),
|
||||
hasExtensionRequest:
|
||||
a.expiresAt() <=
|
||||
this.mg.ticks() +
|
||||
this.mg.config().allianceExtensionPromptOffset(),
|
||||
}) satisfies AllianceView,
|
||||
),
|
||||
hasSpawned: this.hasSpawned(),
|
||||
betrayals: this._betrayalCount,
|
||||
lastDeleteUnitTick: this.lastDeleteUnitTick,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -553,9 +556,10 @@ export class PlayerImpl implements Player {
|
||||
throw Error(`Cannot send emoji to oneself: ${this}`);
|
||||
}
|
||||
const msg: EmojiMessage = {
|
||||
message: emoji,
|
||||
senderID: this.smallID(),
|
||||
recipientID: recipient === AllPlayers ? recipient : recipient.smallID(),
|
||||
emoji: emoji,
|
||||
senderId: this.smallID(),
|
||||
allPlayers: recipient === AllPlayers,
|
||||
recipientId: recipient === AllPlayers ? undefined : recipient.smallID(),
|
||||
createdAt: this.mg.ticks(),
|
||||
};
|
||||
this.outgoingEmojis_.push(msg);
|
||||
@@ -578,9 +582,9 @@ export class PlayerImpl implements Player {
|
||||
}
|
||||
const recipientID =
|
||||
recipient === AllPlayers ? AllPlayers : recipient.smallID();
|
||||
const prevMsgs = this.outgoingEmojis_.filter(
|
||||
(msg) => msg.recipientID === recipientID,
|
||||
);
|
||||
const prevMsgs = this.outgoingEmojis_.filter((msg) => {
|
||||
return msg.allPlayers ?? msg.recipientId === recipientID;
|
||||
});
|
||||
for (const msg of prevMsgs) {
|
||||
if (
|
||||
this.mg.ticks() - msg.createdAt <
|
||||
@@ -740,9 +744,11 @@ export class PlayerImpl implements Player {
|
||||
|
||||
this.mg.addUpdate({
|
||||
type: GameUpdateType.EmbargoEvent,
|
||||
event: "start",
|
||||
playerID: this.smallID(),
|
||||
embargoedID: other.smallID(),
|
||||
embargo: {
|
||||
playerId: this.smallID(),
|
||||
embargoedId: other.smallID(),
|
||||
event: EmbargoUpdate_EmbargoEvent.start,
|
||||
},
|
||||
});
|
||||
|
||||
this.embargoes.set(other.id(), {
|
||||
@@ -756,9 +762,11 @@ export class PlayerImpl implements Player {
|
||||
this.embargoes.delete(other.id());
|
||||
this.mg.addUpdate({
|
||||
type: GameUpdateType.EmbargoEvent,
|
||||
event: "stop",
|
||||
playerID: this.smallID(),
|
||||
embargoedID: other.smallID(),
|
||||
embargo: {
|
||||
playerId: this.smallID(),
|
||||
embargoedId: other.smallID(),
|
||||
event: EmbargoUpdate_EmbargoEvent.stop,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -808,10 +816,12 @@ export class PlayerImpl implements Player {
|
||||
if (tile) {
|
||||
this.mg.addUpdate({
|
||||
type: GameUpdateType.BonusEvent,
|
||||
player: this.id(),
|
||||
tile,
|
||||
gold: Number(toAdd),
|
||||
troops: 0,
|
||||
bonusEvent: {
|
||||
player: this.id(),
|
||||
tile,
|
||||
gold: Number(toAdd),
|
||||
troops: 0,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -855,7 +865,7 @@ export class PlayerImpl implements Player {
|
||||
buildUnit<T extends UnitType>(
|
||||
type: T,
|
||||
spawnTile: TileRef,
|
||||
params: UnitParams<T>,
|
||||
params: UnitParams<keyof UnitParamsMap>,
|
||||
): Unit {
|
||||
if (this.mg.config().isUnitDisabled(type)) {
|
||||
throw new Error(
|
||||
@@ -930,7 +940,7 @@ export class PlayerImpl implements Player {
|
||||
|
||||
public buildableUnits(tile: TileRef | null): BuildableUnit[] {
|
||||
const validTiles = tile !== null ? this.validStructureSpawnTiles(tile) : [];
|
||||
return Object.values(UnitType).map((u) => {
|
||||
return AllUnitTypes.map((u) => {
|
||||
let canUpgrade: number | false = false;
|
||||
if (!this.mg.inSpawnPhase()) {
|
||||
const existingUnit = tile !== null && this.findUnitToUpgrade(u, tile);
|
||||
@@ -1076,7 +1086,7 @@ export class PlayerImpl implements Player {
|
||||
}
|
||||
const searchRadius = 15;
|
||||
const searchRadiusSquared = searchRadius ** 2;
|
||||
const types = Object.values(UnitType).filter((unitTypeValue) => {
|
||||
const types = AllUnitTypes.filter((unitTypeValue) => {
|
||||
return this.mg.config().unitInfo(unitTypeValue).territoryBound;
|
||||
});
|
||||
|
||||
|
||||
@@ -2,8 +2,9 @@ import { RailroadExecution } from "../execution/RailroadExecution";
|
||||
import { PathFindResultType } from "../pathfinding/AStar";
|
||||
import { MiniAStar } from "../pathfinding/MiniAStar";
|
||||
import { SerialAStar } from "../pathfinding/SerialAStar";
|
||||
import { Game, Unit, UnitType } from "./Game";
|
||||
import { Game, Unit } from "./Game";
|
||||
import { TileRef } from "./GameMap";
|
||||
import { UnitType } from "./GameUpdates";
|
||||
import { RailNetwork } from "./RailNetwork";
|
||||
import { Railroad } from "./Railroad";
|
||||
import { Cluster, TrainStation, TrainStationMapAdapter } from "./TrainStation";
|
||||
|
||||
@@ -13,12 +13,14 @@ export class Railroad {
|
||||
delete(game: Game) {
|
||||
const railTiles: RailTile[] = this.tiles.map((tile) => ({
|
||||
tile,
|
||||
railType: RailType.VERTICAL,
|
||||
railType: RailType.vertical,
|
||||
}));
|
||||
game.addUpdate({
|
||||
type: GameUpdateType.RailroadEvent,
|
||||
isActive: false,
|
||||
railTiles,
|
||||
railroad: {
|
||||
isActive: false,
|
||||
railTiles,
|
||||
},
|
||||
});
|
||||
this.from.removeRailroad(this);
|
||||
this.to.removeRailroad(this);
|
||||
|
||||
@@ -26,7 +26,8 @@ import {
|
||||
unitTypeToBombUnit,
|
||||
unitTypeToOtherUnit,
|
||||
} from "../StatsSchemas";
|
||||
import { Player, TerraNullius, UnitType } from "./Game";
|
||||
import { Player, TerraNullius } from "./Game";
|
||||
import { UnitType } from "./GameUpdates";
|
||||
import { Stats } from "./Stats";
|
||||
|
||||
type BigIntLike = bigint | number;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { PseudoRandom } from "../PseudoRandom";
|
||||
import { simpleHash } from "../Util";
|
||||
import { PlayerInfo, PlayerType, Team } from "./Game";
|
||||
import { PlayerInfo, Team } from "./Game";
|
||||
import { PlayerType } from "./GameUpdates";
|
||||
|
||||
export function assignTeams(
|
||||
players: PlayerInfo[],
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { TrainExecution } from "../execution/TrainExecution";
|
||||
import { GraphAdapter } from "../pathfinding/SerialAStar";
|
||||
import { PseudoRandom } from "../PseudoRandom";
|
||||
import { Game, Player, Unit, UnitType } from "./Game";
|
||||
import { Game, Player, Unit } from "./Game";
|
||||
import { TileRef } from "./GameMap";
|
||||
import { GameUpdateType, RailTile, RailType } from "./GameUpdates";
|
||||
import { GameUpdateType, RailTile, RailType, UnitType } from "./GameUpdates";
|
||||
import { Railroad } from "./Railroad";
|
||||
|
||||
/**
|
||||
@@ -115,12 +115,14 @@ export class TrainStation {
|
||||
if (toRemove) {
|
||||
const railTiles: RailTile[] = toRemove.tiles.map((tile) => ({
|
||||
tile,
|
||||
railType: RailType.VERTICAL,
|
||||
railType: RailType.vertical,
|
||||
}));
|
||||
this.mg.addUpdate({
|
||||
type: GameUpdateType.RailroadEvent,
|
||||
isActive: false,
|
||||
railTiles,
|
||||
railroad: {
|
||||
isActive: false,
|
||||
railTiles,
|
||||
},
|
||||
});
|
||||
this.removeRailroad(toRemove);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { PathFindResultType } from "../pathfinding/AStar";
|
||||
import { MiniAStar } from "../pathfinding/MiniAStar";
|
||||
import { Game, Player, UnitType } from "./Game";
|
||||
import { Game, Player } from "./Game";
|
||||
import { andFN, GameMap, manhattanDistFN, TileRef } from "./GameMap";
|
||||
import { UnitType } from "./GameUpdates";
|
||||
|
||||
export function canBuildTransportShip(
|
||||
game: Game,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { PlayerID, Unit, UnitType } from "./Game";
|
||||
import { PlayerID, Unit } from "./Game";
|
||||
import { GameMap, TileRef } from "./GameMap";
|
||||
import { UnitType } from "./GameUpdates";
|
||||
import { UnitView } from "./GameView";
|
||||
|
||||
export type UnitPredicate = (value: {
|
||||
|
||||
@@ -1,18 +1,21 @@
|
||||
import { simpleHash, toInt, withinInt } from "../Util";
|
||||
import { toInt, withinInt } from "../Util";
|
||||
import {
|
||||
AllUnitParams,
|
||||
MessageType,
|
||||
Player,
|
||||
Tick,
|
||||
TrainType,
|
||||
TrajectoryTile,
|
||||
Unit,
|
||||
UnitInfo,
|
||||
UnitType,
|
||||
} from "./Game";
|
||||
import { GameImpl } from "./GameImpl";
|
||||
import { TileRef } from "./GameMap";
|
||||
import { GameUpdateType, UnitUpdate } from "./GameUpdates";
|
||||
import {
|
||||
GameUpdateType,
|
||||
MessageType,
|
||||
TrainType,
|
||||
UnitType,
|
||||
UnitUpdate,
|
||||
} from "./GameUpdates";
|
||||
import { PlayerImpl } from "./PlayerImpl";
|
||||
|
||||
export class UnitImpl implements Unit {
|
||||
@@ -123,13 +126,13 @@ export class UnitImpl implements Unit {
|
||||
unitType: this._type,
|
||||
id: this._id,
|
||||
troops: this._troops,
|
||||
ownerID: this._owner.smallID(),
|
||||
lastOwnerID: this._lastOwner?.smallID(),
|
||||
ownerId: this._owner.smallID(),
|
||||
lastOwnerId: this._lastOwner?.smallID(),
|
||||
isActive: this._active,
|
||||
reachedTarget: this._reachedTarget,
|
||||
retreating: this._retreating,
|
||||
pos: this._tile,
|
||||
markedForDeletion: this._deletionAt ?? false,
|
||||
markedForDeletion: this._deletionAt ?? undefined,
|
||||
targetable: this._targetable,
|
||||
lastPos: this._lastTile,
|
||||
health: this.hasHealth() ? Number(this._health) : undefined,
|
||||
@@ -325,7 +328,7 @@ export class UnitImpl implements Unit {
|
||||
}
|
||||
|
||||
hash(): number {
|
||||
return this.tile() + simpleHash(this.type()) * this._id;
|
||||
return this.tile() + this.type() * this._id;
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
|
||||
@@ -4,9 +4,9 @@ import {
|
||||
Game,
|
||||
Player,
|
||||
PlayerInfo,
|
||||
PlayerType,
|
||||
Tick,
|
||||
} from "../src/core/game/Game";
|
||||
import { PlayerType } from "../src/core/game/GameUpdates";
|
||||
import { PseudoRandom } from "../src/core/PseudoRandom";
|
||||
import { setup } from "./util/Setup";
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { AllianceRequestExecution } from "../src/core/execution/alliance/AllianceRequestExecution";
|
||||
import { AllianceRequestReplyExecution } from "../src/core/execution/alliance/AllianceRequestReplyExecution";
|
||||
import { DonateGoldExecution } from "../src/core/execution/DonateGoldExecution";
|
||||
import { Game, Player, PlayerType } from "../src/core/game/Game";
|
||||
import { Game, Player } from "../src/core/game/Game";
|
||||
import { PlayerType } from "../src/core/game/GameUpdates";
|
||||
import { playerInfo, setup } from "./util/Setup";
|
||||
|
||||
let game: Game;
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { AllianceExtensionExecution } from "../src/core/execution/alliance/AllianceExtensionExecution";
|
||||
import { AllianceRequestExecution } from "../src/core/execution/alliance/AllianceRequestExecution";
|
||||
import { AllianceRequestReplyExecution } from "../src/core/execution/alliance/AllianceRequestReplyExecution";
|
||||
import { Game, MessageType, Player, PlayerType } from "../src/core/game/Game";
|
||||
import { Game, Player } from "../src/core/game/Game";
|
||||
import { MessageType, PlayerType } from "../src/core/game/GameUpdates";
|
||||
import { playerInfo, setup } from "./util/Setup";
|
||||
|
||||
let game: Game;
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { AllianceRequestExecution } from "../src/core/execution/alliance/AllianceRequestExecution";
|
||||
import { AllianceRequestReplyExecution } from "../src/core/execution/alliance/AllianceRequestReplyExecution";
|
||||
import { NukeExecution } from "../src/core/execution/NukeExecution";
|
||||
import { Game, Player, PlayerType, UnitType } from "../src/core/game/Game";
|
||||
import { Game, Player } from "../src/core/game/Game";
|
||||
import { PlayerType, UnitType } from "../src/core/game/GameUpdates";
|
||||
import { playerInfo, setup } from "./util/Setup";
|
||||
import { constructionExecution } from "./util/utils";
|
||||
|
||||
|
||||
@@ -1,14 +1,9 @@
|
||||
import { AttackExecution } from "../src/core/execution/AttackExecution";
|
||||
import { SpawnExecution } from "../src/core/execution/SpawnExecution";
|
||||
import { TransportShipExecution } from "../src/core/execution/TransportShipExecution";
|
||||
import {
|
||||
Game,
|
||||
Player,
|
||||
PlayerInfo,
|
||||
PlayerType,
|
||||
UnitType,
|
||||
} from "../src/core/game/Game";
|
||||
import { Game, Player, PlayerInfo } from "../src/core/game/Game";
|
||||
import { TileRef } from "../src/core/game/GameMap";
|
||||
import { PlayerType, UnitType } from "../src/core/game/GameUpdates";
|
||||
import { setup } from "./util/Setup";
|
||||
import { TestConfig } from "./util/TestConfig";
|
||||
import { constructionExecution } from "./util/utils";
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { AttackExecution } from "../src/core/execution/AttackExecution";
|
||||
import { SpawnExecution } from "../src/core/execution/SpawnExecution";
|
||||
import { Game, Player, PlayerInfo, PlayerType } from "../src/core/game/Game";
|
||||
import { Game, Player, PlayerInfo } from "../src/core/game/Game";
|
||||
import { PlayerType } from "../src/core/game/GameUpdates";
|
||||
import { GOLD_INDEX_WAR, GOLD_INDEX_WORK } from "../src/core/StatsSchemas";
|
||||
import { setup } from "./util/Setup";
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { BotBehavior } from "../src/core/execution/utils/BotBehavior";
|
||||
import { Game, Player, PlayerInfo, PlayerType } from "../src/core/game/Game";
|
||||
import { Game, Player, PlayerInfo } from "../src/core/game/Game";
|
||||
import { PlayerType } from "../src/core/game/GameUpdates";
|
||||
import { PseudoRandom } from "../src/core/PseudoRandom";
|
||||
import { setup } from "./util/Setup";
|
||||
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
import { DeleteUnitExecution } from "../src/core/execution/DeleteUnitExecution";
|
||||
import { SpawnExecution } from "../src/core/execution/SpawnExecution";
|
||||
import {
|
||||
Game,
|
||||
Player,
|
||||
PlayerInfo,
|
||||
PlayerType,
|
||||
Unit,
|
||||
UnitType,
|
||||
} from "../src/core/game/Game";
|
||||
import { Game, Player, PlayerInfo, Unit } from "../src/core/game/Game";
|
||||
import { TileRef } from "../src/core/game/GameMap";
|
||||
import { PlayerType, UnitType } from "../src/core/game/GameUpdates";
|
||||
import { setup } from "./util/Setup";
|
||||
import { executeTicks } from "./util/utils";
|
||||
|
||||
|
||||
@@ -3,14 +3,8 @@ import { MarkDisconnectedExecution } from "../src/core/execution/MarkDisconnecte
|
||||
import { SpawnExecution } from "../src/core/execution/SpawnExecution";
|
||||
import { TransportShipExecution } from "../src/core/execution/TransportShipExecution";
|
||||
import { WarshipExecution } from "../src/core/execution/WarshipExecution";
|
||||
import {
|
||||
Game,
|
||||
GameMode,
|
||||
Player,
|
||||
PlayerInfo,
|
||||
PlayerType,
|
||||
UnitType,
|
||||
} from "../src/core/game/Game";
|
||||
import { Game, GameMode, Player, PlayerInfo } from "../src/core/game/Game";
|
||||
import { PlayerType, UnitType } from "../src/core/game/GameUpdates";
|
||||
import { toInt } from "../src/core/Util";
|
||||
import { setup } from "./util/Setup";
|
||||
import { UseRealAttackLogic } from "./util/TestConfig";
|
||||
@@ -72,7 +66,7 @@ describe("Disconnected", () => {
|
||||
test("should include disconnected state in player update", () => {
|
||||
player1.markDisconnected(true);
|
||||
const update = player1.toUpdate();
|
||||
expect(update.isDisconnected).toBe(true);
|
||||
expect(update.player!.isDisconnected).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -146,7 +140,7 @@ describe("Disconnected", () => {
|
||||
player1.markDisconnected(true);
|
||||
executeTicks(game, 3);
|
||||
const update = player1.toUpdate();
|
||||
expect(update.isDisconnected).toBe(true);
|
||||
expect(update.player!.isDisconnected).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { DonateGoldExecution } from "../src/core/execution/DonateGoldExecution";
|
||||
import { DonateTroopsExecution } from "../src/core/execution/DonateTroopExecution";
|
||||
import { SpawnExecution } from "../src/core/execution/SpawnExecution";
|
||||
import { PlayerInfo, PlayerType } from "../src/core/game/Game";
|
||||
import { PlayerInfo } from "../src/core/game/Game";
|
||||
import { PlayerType } from "../src/core/game/GameUpdates";
|
||||
import { setup } from "./util/Setup";
|
||||
|
||||
describe("Donate troops to an ally", () => {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user