Merge main into nations-nuke
@@ -0,0 +1,9 @@
|
||||
# EditorConfig is awesome: https://EditorConfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 2
|
||||
indent_style = space
|
||||
insert_final_newline = true
|
||||
@@ -0,0 +1,18 @@
|
||||
name: ESLint Check
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
eslint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "20"
|
||||
cache: "npm"
|
||||
- run: npm ci
|
||||
- run: npx eslint --format gha
|
||||
@@ -1,13 +1,33 @@
|
||||
import { includeIgnoreFile } from "@eslint/compat";
|
||||
import pluginJs from "@eslint/js";
|
||||
import eslintConfigPrettier from "eslint-config-prettier/flat";
|
||||
import globals from "globals";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import tseslint from "typescript-eslint";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
const gitignorePath = path.resolve(__dirname, ".gitignore");
|
||||
|
||||
/** @type {import('eslint').Linter.Config[]} */
|
||||
export default [
|
||||
includeIgnoreFile(gitignorePath),
|
||||
{ files: ["**/*.{js,mjs,cjs,ts}"] },
|
||||
{ languageOptions: { globals: { ...globals.browser, ...globals.node } } },
|
||||
pluginJs.configs.recommended,
|
||||
...tseslint.configs.recommended,
|
||||
eslintConfigPrettier,
|
||||
{
|
||||
rules: {
|
||||
// Disable rules that would fail. The failures should be fixed, and the entries here removed.
|
||||
"@typescript-eslint/no-empty-object-type": "off",
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"@typescript-eslint/no-require-imports": "off",
|
||||
"@typescript-eslint/no-unused-expressions": "off",
|
||||
"@typescript-eslint/no-unused-vars": "off",
|
||||
"no-case-declarations": "off",
|
||||
"no-useless-escape": "off",
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
"@babel/core": "^7.25.2",
|
||||
"@babel/preset-env": "^7.25.3",
|
||||
"@babel/preset-typescript": "^7.24.7",
|
||||
"@eslint/compat": "^1.2.7",
|
||||
"@eslint/js": "^9.21.0",
|
||||
"@types/chai": "^4.3.17",
|
||||
"@types/d3": "^7.4.3",
|
||||
@@ -85,6 +86,8 @@
|
||||
"css-loader": "^7.1.2",
|
||||
"eslint": "^9.21.0",
|
||||
"eslint-config-prettier": "^10.1.1",
|
||||
"eslint-formatter-gha": "^1.5.2",
|
||||
"eslint-webpack-plugin": "^5.0.0",
|
||||
"file-loader": "^6.2.0",
|
||||
"globals": "^16.0.0",
|
||||
"html-inline-script-webpack-plugin": "^3.2.1",
|
||||
@@ -1061,9 +1064,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/code-frame": {
|
||||
"version": "7.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.0.tgz",
|
||||
"integrity": "sha512-INCKxTtbXtcNbUZ3YXutwMpEleqttcswhAdee7dhuoVrD2cnuc3PqtERBtxkX5nziX9vnBL8WXmSGwv8CuPV6g==",
|
||||
"version": "7.26.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz",
|
||||
"integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -1413,27 +1416,27 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helpers": {
|
||||
"version": "7.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz",
|
||||
"integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==",
|
||||
"version": "7.27.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.0.tgz",
|
||||
"integrity": "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/template": "^7.25.9",
|
||||
"@babel/types": "^7.26.0"
|
||||
"@babel/template": "^7.27.0",
|
||||
"@babel/types": "^7.27.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/parser": {
|
||||
"version": "7.26.1",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.1.tgz",
|
||||
"integrity": "sha512-reoQYNiAJreZNsJzyrDNzFQ+IQ5JFiIzAHJg9bn94S3l+4++J7RsIhNMoB+lgP/9tpmiAQqspv+xfdxTSzREOw==",
|
||||
"version": "7.27.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz",
|
||||
"integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.26.0"
|
||||
"@babel/types": "^7.27.0"
|
||||
},
|
||||
"bin": {
|
||||
"parser": "bin/babel-parser.js"
|
||||
@@ -2800,9 +2803,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/runtime": {
|
||||
"version": "7.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz",
|
||||
"integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==",
|
||||
"version": "7.27.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz",
|
||||
"integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -2813,15 +2816,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/template": {
|
||||
"version": "7.25.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz",
|
||||
"integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==",
|
||||
"version": "7.27.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz",
|
||||
"integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.25.9",
|
||||
"@babel/parser": "^7.25.9",
|
||||
"@babel/types": "^7.25.9"
|
||||
"@babel/code-frame": "^7.26.2",
|
||||
"@babel/parser": "^7.27.0",
|
||||
"@babel/types": "^7.27.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
@@ -2857,9 +2860,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/types": {
|
||||
"version": "7.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz",
|
||||
"integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==",
|
||||
"version": "7.27.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz",
|
||||
"integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -2937,32 +2940,26 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@discordjs/builders": {
|
||||
"version": "1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.9.0.tgz",
|
||||
"integrity": "sha512-0zx8DePNVvQibh5ly5kCEei5wtPBIUbSoE9n+91Rlladz4tgtFbJ36PZMxxZrTEOQ7AHMZ/b0crT/0fCy6FTKg==",
|
||||
"version": "1.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.10.1.tgz",
|
||||
"integrity": "sha512-OWo1fY4ztL1/M/DUyRPShB4d/EzVfuUvPTRRHRIt/YxBrUYSz0a+JicD5F5zHFoNs2oTuWavxCOVFV1UljHTng==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@discordjs/formatters": "^0.5.0",
|
||||
"@discordjs/formatters": "^0.6.0",
|
||||
"@discordjs/util": "^1.1.1",
|
||||
"@sapphire/shapeshift": "^4.0.0",
|
||||
"discord-api-types": "0.37.97",
|
||||
"discord-api-types": "^0.37.119",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"ts-mixer": "^6.0.4",
|
||||
"tslib": "^2.6.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
"node": ">=16.11.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/discordjs/discord.js?sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@discordjs/builders/node_modules/discord-api-types": {
|
||||
"version": "0.37.97",
|
||||
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.97.tgz",
|
||||
"integrity": "sha512-No1BXPcVkyVD4ZVmbNgDKaBoqgeQ+FJpzZ8wqHkfmBnTZig1FcH3iPPersiK1TUIAzgClh2IvOuVUYfcWLQAOA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@discordjs/collection": {
|
||||
"version": "1.5.3",
|
||||
"resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.5.3.tgz",
|
||||
@@ -2973,30 +2970,24 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@discordjs/formatters": {
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@discordjs/formatters/-/formatters-0.5.0.tgz",
|
||||
"integrity": "sha512-98b3i+Y19RFq1Xke4NkVY46x8KjJQjldHUuEbCqMvp1F5Iq9HgnGpu91jOi/Ufazhty32eRsKnnzS8n4c+L93g==",
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@discordjs/formatters/-/formatters-0.6.0.tgz",
|
||||
"integrity": "sha512-YIruKw4UILt/ivO4uISmrGq2GdMY6EkoTtD0oS0GvkJFRZbTSdPhzYiUILbJ/QslsvC9H9nTgGgnarnIl4jMfw==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"discord-api-types": "0.37.97"
|
||||
"discord-api-types": "^0.37.114"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
"node": ">=16.11.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/discordjs/discord.js?sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@discordjs/formatters/node_modules/discord-api-types": {
|
||||
"version": "0.37.97",
|
||||
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.97.tgz",
|
||||
"integrity": "sha512-No1BXPcVkyVD4ZVmbNgDKaBoqgeQ+FJpzZ8wqHkfmBnTZig1FcH3iPPersiK1TUIAzgClh2IvOuVUYfcWLQAOA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@discordjs/rest": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.4.0.tgz",
|
||||
"integrity": "sha512-Xb2irDqNcq+O8F0/k/NaDp7+t091p+acb51iA4bCKfIn+WFWd6HrNvcsSbMMxIR9NjcMZS6NReTKygqiQN+ntw==",
|
||||
"version": "2.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.4.3.tgz",
|
||||
"integrity": "sha512-+SO4RKvWsM+y8uFHgYQrcTl/3+cY02uQOH7/7bKbVZsTfrfpoE62o5p+mmV+s7FVhTX82/kQUGGbu4YlV60RtA==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@discordjs/collection": "^2.1.1",
|
||||
@@ -3004,10 +2995,10 @@
|
||||
"@sapphire/async-queue": "^1.5.3",
|
||||
"@sapphire/snowflake": "^3.5.3",
|
||||
"@vladfrangu/async_event_emitter": "^2.4.6",
|
||||
"discord-api-types": "0.37.97",
|
||||
"discord-api-types": "^0.37.119",
|
||||
"magic-bytes.js": "^1.10.0",
|
||||
"tslib": "^2.6.3",
|
||||
"undici": "6.19.8"
|
||||
"undici": "6.21.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
@@ -3028,12 +3019,6 @@
|
||||
"url": "https://github.com/discordjs/discord.js?sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@discordjs/rest/node_modules/discord-api-types": {
|
||||
"version": "0.37.97",
|
||||
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.97.tgz",
|
||||
"integrity": "sha512-No1BXPcVkyVD4ZVmbNgDKaBoqgeQ+FJpzZ8wqHkfmBnTZig1FcH3iPPersiK1TUIAzgClh2IvOuVUYfcWLQAOA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@discordjs/util": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@discordjs/util/-/util-1.1.1.tgz",
|
||||
@@ -3047,20 +3032,20 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@discordjs/ws": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@discordjs/ws/-/ws-1.1.1.tgz",
|
||||
"integrity": "sha512-PZ+vLpxGCRtmr2RMkqh8Zp+BenUaJqlS6xhgWKEZcgC/vfHLEzpHtKkB0sl3nZWpwtcKk6YWy+pU3okL2I97FA==",
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@discordjs/ws/-/ws-1.2.1.tgz",
|
||||
"integrity": "sha512-PBvenhZG56a6tMWF/f4P6f4GxZKJTBG95n7aiGSPTnodmz4N5g60t79rSIAq7ywMbv8A4jFtexMruH+oe51aQQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@discordjs/collection": "^2.1.0",
|
||||
"@discordjs/rest": "^2.3.0",
|
||||
"@discordjs/rest": "^2.4.3",
|
||||
"@discordjs/util": "^1.1.0",
|
||||
"@sapphire/async-queue": "^1.5.2",
|
||||
"@types/ws": "^8.5.10",
|
||||
"@vladfrangu/async_event_emitter": "^2.2.4",
|
||||
"discord-api-types": "0.37.83",
|
||||
"discord-api-types": "^0.37.119",
|
||||
"tslib": "^2.6.2",
|
||||
"ws": "^8.16.0"
|
||||
"ws": "^8.17.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.11.0"
|
||||
@@ -3081,12 +3066,6 @@
|
||||
"url": "https://github.com/discordjs/discord.js?sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@discordjs/ws/node_modules/discord-api-types": {
|
||||
"version": "0.37.83",
|
||||
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.83.tgz",
|
||||
"integrity": "sha512-urGGYeWtWNYMKnYlZnOnDHm8fVRffQs3U0SpE8RHeiuLKb/u92APS8HoQnPTFbnXmY1vVnXjXO4dOxcAn3J+DA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@discoveryjs/json-ext": {
|
||||
"version": "0.5.7",
|
||||
"resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz",
|
||||
@@ -3106,9 +3085,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/aix-ppc64": {
|
||||
"version": "0.23.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz",
|
||||
"integrity": "sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==",
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.2.tgz",
|
||||
"integrity": "sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
@@ -3123,9 +3102,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-arm": {
|
||||
"version": "0.23.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.1.tgz",
|
||||
"integrity": "sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==",
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.2.tgz",
|
||||
"integrity": "sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@@ -3140,9 +3119,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-arm64": {
|
||||
"version": "0.23.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz",
|
||||
"integrity": "sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==",
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.2.tgz",
|
||||
"integrity": "sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -3157,9 +3136,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-x64": {
|
||||
"version": "0.23.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.1.tgz",
|
||||
"integrity": "sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==",
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.2.tgz",
|
||||
"integrity": "sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -3174,9 +3153,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/darwin-arm64": {
|
||||
"version": "0.23.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz",
|
||||
"integrity": "sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==",
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.2.tgz",
|
||||
"integrity": "sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -3191,9 +3170,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/darwin-x64": {
|
||||
"version": "0.23.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz",
|
||||
"integrity": "sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==",
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.2.tgz",
|
||||
"integrity": "sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -3208,9 +3187,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/freebsd-arm64": {
|
||||
"version": "0.23.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz",
|
||||
"integrity": "sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==",
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.2.tgz",
|
||||
"integrity": "sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -3225,9 +3204,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/freebsd-x64": {
|
||||
"version": "0.23.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz",
|
||||
"integrity": "sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==",
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.2.tgz",
|
||||
"integrity": "sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -3242,9 +3221,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-arm": {
|
||||
"version": "0.23.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz",
|
||||
"integrity": "sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==",
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.2.tgz",
|
||||
"integrity": "sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@@ -3259,9 +3238,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-arm64": {
|
||||
"version": "0.23.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz",
|
||||
"integrity": "sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==",
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.2.tgz",
|
||||
"integrity": "sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -3276,9 +3255,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-ia32": {
|
||||
"version": "0.23.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz",
|
||||
"integrity": "sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==",
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.2.tgz",
|
||||
"integrity": "sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
@@ -3293,9 +3272,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-loong64": {
|
||||
"version": "0.23.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz",
|
||||
"integrity": "sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==",
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.2.tgz",
|
||||
"integrity": "sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
@@ -3310,9 +3289,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-mips64el": {
|
||||
"version": "0.23.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz",
|
||||
"integrity": "sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==",
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.2.tgz",
|
||||
"integrity": "sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==",
|
||||
"cpu": [
|
||||
"mips64el"
|
||||
],
|
||||
@@ -3327,9 +3306,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-ppc64": {
|
||||
"version": "0.23.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz",
|
||||
"integrity": "sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==",
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.2.tgz",
|
||||
"integrity": "sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
@@ -3344,9 +3323,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-riscv64": {
|
||||
"version": "0.23.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz",
|
||||
"integrity": "sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==",
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.2.tgz",
|
||||
"integrity": "sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
@@ -3361,9 +3340,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-s390x": {
|
||||
"version": "0.23.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz",
|
||||
"integrity": "sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==",
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.2.tgz",
|
||||
"integrity": "sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
@@ -3378,9 +3357,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-x64": {
|
||||
"version": "0.23.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz",
|
||||
"integrity": "sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==",
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.2.tgz",
|
||||
"integrity": "sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -3394,10 +3373,27 @@
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/netbsd-arm64": {
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.2.tgz",
|
||||
"integrity": "sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"netbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/netbsd-x64": {
|
||||
"version": "0.23.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz",
|
||||
"integrity": "sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==",
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.2.tgz",
|
||||
"integrity": "sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -3412,9 +3408,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openbsd-arm64": {
|
||||
"version": "0.23.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz",
|
||||
"integrity": "sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==",
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.2.tgz",
|
||||
"integrity": "sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -3429,9 +3425,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openbsd-x64": {
|
||||
"version": "0.23.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz",
|
||||
"integrity": "sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==",
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.2.tgz",
|
||||
"integrity": "sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -3446,9 +3442,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/sunos-x64": {
|
||||
"version": "0.23.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz",
|
||||
"integrity": "sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==",
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.2.tgz",
|
||||
"integrity": "sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -3463,9 +3459,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-arm64": {
|
||||
"version": "0.23.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz",
|
||||
"integrity": "sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==",
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.2.tgz",
|
||||
"integrity": "sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -3480,9 +3476,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-ia32": {
|
||||
"version": "0.23.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz",
|
||||
"integrity": "sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==",
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.2.tgz",
|
||||
"integrity": "sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
@@ -3497,9 +3493,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-x64": {
|
||||
"version": "0.23.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz",
|
||||
"integrity": "sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==",
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.2.tgz",
|
||||
"integrity": "sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -3555,6 +3551,24 @@
|
||||
"node": "^12.0.0 || ^14.0.0 || >=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/compat": {
|
||||
"version": "1.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.2.7.tgz",
|
||||
"integrity": "sha512-xvv7hJE32yhegJ8xNAnb62ggiAwTYHBpUCWhRxEj/ksvgDJuSXfoDkBcRYaYNFiJ+jH0IE3K16hd+xXzhBgNbg==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": "^9.10.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"eslint": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/config-array": {
|
||||
"version": "0.19.2",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.2.tgz",
|
||||
@@ -6608,6 +6622,17 @@
|
||||
"@types/trusted-types": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/eslint": {
|
||||
"version": "9.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz",
|
||||
"integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/estree": "*",
|
||||
"@types/json-schema": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/estree": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
|
||||
@@ -9890,29 +9915,29 @@
|
||||
}
|
||||
},
|
||||
"node_modules/discord-api-types": {
|
||||
"version": "0.37.100",
|
||||
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.100.tgz",
|
||||
"integrity": "sha512-a8zvUI0GYYwDtScfRd/TtaNBDTXwP5DiDVX7K5OmE+DRT57gBqKnwtOC5Ol8z0mRW8KQfETIgiB8U0YZ9NXiCA==",
|
||||
"version": "0.37.119",
|
||||
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.119.tgz",
|
||||
"integrity": "sha512-WasbGFXEB+VQWXlo6IpW3oUv73Yuau1Ig4AZF/m13tXcTKnMpc/mHjpztIlz4+BM9FG9BHQkEXiPto3bKduQUg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/discord.js": {
|
||||
"version": "14.16.3",
|
||||
"resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.16.3.tgz",
|
||||
"integrity": "sha512-EPCWE9OkA9DnFFNrO7Kl1WHHDYFXu3CNVFJg63bfU7hVtjZGyhShwZtSBImINQRWxWP2tgo2XI+QhdXx28r0aA==",
|
||||
"version": "14.18.0",
|
||||
"resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.18.0.tgz",
|
||||
"integrity": "sha512-SvU5kVUvwunQhN2/+0t55QW/1EHfB1lp0TtLZUSXVHDmyHTrdOj5LRKdR0zLcybaA15F+NtdWuWmGOX9lE+CAw==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@discordjs/builders": "^1.9.0",
|
||||
"@discordjs/builders": "^1.10.1",
|
||||
"@discordjs/collection": "1.5.3",
|
||||
"@discordjs/formatters": "^0.5.0",
|
||||
"@discordjs/rest": "^2.4.0",
|
||||
"@discordjs/formatters": "^0.6.0",
|
||||
"@discordjs/rest": "^2.4.3",
|
||||
"@discordjs/util": "^1.1.1",
|
||||
"@discordjs/ws": "1.1.1",
|
||||
"@discordjs/ws": "^1.2.1",
|
||||
"@sapphire/snowflake": "3.5.3",
|
||||
"discord-api-types": "0.37.100",
|
||||
"discord-api-types": "^0.37.119",
|
||||
"fast-deep-equal": "3.1.3",
|
||||
"lodash.snakecase": "4.1.1",
|
||||
"tslib": "^2.6.3",
|
||||
"undici": "6.19.8"
|
||||
"undici": "6.21.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
@@ -10005,10 +10030,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/dompurify": {
|
||||
"version": "3.1.7",
|
||||
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.7.tgz",
|
||||
"integrity": "sha512-VaTstWtsneJY8xzy7DekmYWEOZcmzIe3Qb3zPd4STve1OBTa+e+WmS1ITQec1fZYXI3HCsOZZiSMpG6oxoWMWQ==",
|
||||
"license": "(MPL-2.0 OR Apache-2.0)"
|
||||
"version": "3.2.4",
|
||||
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.4.tgz",
|
||||
"integrity": "sha512-ysFSFEDVduQpyhzAob/kkuJjf5zWkZD8/A9ywSp1byueyuCfHamrCBa14/Oc2iiB0e51B+NpxSl5gmzn+Ms/mg==",
|
||||
"license": "(MPL-2.0 OR Apache-2.0)",
|
||||
"optionalDependencies": {
|
||||
"@types/trusted-types": "^2.0.7"
|
||||
}
|
||||
},
|
||||
"node_modules/domutils": {
|
||||
"version": "2.8.0",
|
||||
@@ -10305,9 +10333,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.23.1",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz",
|
||||
"integrity": "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==",
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.2.tgz",
|
||||
"integrity": "sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
@@ -10318,30 +10346,31 @@
|
||||
"node": ">=18"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@esbuild/aix-ppc64": "0.23.1",
|
||||
"@esbuild/android-arm": "0.23.1",
|
||||
"@esbuild/android-arm64": "0.23.1",
|
||||
"@esbuild/android-x64": "0.23.1",
|
||||
"@esbuild/darwin-arm64": "0.23.1",
|
||||
"@esbuild/darwin-x64": "0.23.1",
|
||||
"@esbuild/freebsd-arm64": "0.23.1",
|
||||
"@esbuild/freebsd-x64": "0.23.1",
|
||||
"@esbuild/linux-arm": "0.23.1",
|
||||
"@esbuild/linux-arm64": "0.23.1",
|
||||
"@esbuild/linux-ia32": "0.23.1",
|
||||
"@esbuild/linux-loong64": "0.23.1",
|
||||
"@esbuild/linux-mips64el": "0.23.1",
|
||||
"@esbuild/linux-ppc64": "0.23.1",
|
||||
"@esbuild/linux-riscv64": "0.23.1",
|
||||
"@esbuild/linux-s390x": "0.23.1",
|
||||
"@esbuild/linux-x64": "0.23.1",
|
||||
"@esbuild/netbsd-x64": "0.23.1",
|
||||
"@esbuild/openbsd-arm64": "0.23.1",
|
||||
"@esbuild/openbsd-x64": "0.23.1",
|
||||
"@esbuild/sunos-x64": "0.23.1",
|
||||
"@esbuild/win32-arm64": "0.23.1",
|
||||
"@esbuild/win32-ia32": "0.23.1",
|
||||
"@esbuild/win32-x64": "0.23.1"
|
||||
"@esbuild/aix-ppc64": "0.25.2",
|
||||
"@esbuild/android-arm": "0.25.2",
|
||||
"@esbuild/android-arm64": "0.25.2",
|
||||
"@esbuild/android-x64": "0.25.2",
|
||||
"@esbuild/darwin-arm64": "0.25.2",
|
||||
"@esbuild/darwin-x64": "0.25.2",
|
||||
"@esbuild/freebsd-arm64": "0.25.2",
|
||||
"@esbuild/freebsd-x64": "0.25.2",
|
||||
"@esbuild/linux-arm": "0.25.2",
|
||||
"@esbuild/linux-arm64": "0.25.2",
|
||||
"@esbuild/linux-ia32": "0.25.2",
|
||||
"@esbuild/linux-loong64": "0.25.2",
|
||||
"@esbuild/linux-mips64el": "0.25.2",
|
||||
"@esbuild/linux-ppc64": "0.25.2",
|
||||
"@esbuild/linux-riscv64": "0.25.2",
|
||||
"@esbuild/linux-s390x": "0.25.2",
|
||||
"@esbuild/linux-x64": "0.25.2",
|
||||
"@esbuild/netbsd-arm64": "0.25.2",
|
||||
"@esbuild/netbsd-x64": "0.25.2",
|
||||
"@esbuild/openbsd-arm64": "0.25.2",
|
||||
"@esbuild/openbsd-x64": "0.25.2",
|
||||
"@esbuild/sunos-x64": "0.25.2",
|
||||
"@esbuild/win32-arm64": "0.25.2",
|
||||
"@esbuild/win32-ia32": "0.25.2",
|
||||
"@esbuild/win32-x64": "0.25.2"
|
||||
}
|
||||
},
|
||||
"node_modules/escalade": {
|
||||
@@ -10446,6 +10475,42 @@
|
||||
"eslint": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-formatter-gha": {
|
||||
"version": "1.5.2",
|
||||
"resolved": "https://registry.npmjs.org/eslint-formatter-gha/-/eslint-formatter-gha-1.5.2.tgz",
|
||||
"integrity": "sha512-1TY8AYbrIP9DCcbydYW467nTP67eW79bT+oVKdUehO3WPMP8pn2oOZVkDc8yDcWf35+t2Li1elY5Dh6jTjJ3/Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"eslint-formatter-json": "^8.40.0",
|
||||
"eslint-formatter-stylish": "^8.40.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-formatter-json": {
|
||||
"version": "8.40.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-formatter-json/-/eslint-formatter-json-8.40.0.tgz",
|
||||
"integrity": "sha512-0bXo4At1EoEU23gFfN7wcDeqRXDHLJnvDOuQKD3Q6FkBlk7L2oVNPYg/sciIWdYrUnCBcKuMit3IWXkdSfzChg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-formatter-stylish": {
|
||||
"version": "8.40.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-formatter-stylish/-/eslint-formatter-stylish-8.40.0.tgz",
|
||||
"integrity": "sha512-blbD5ZSQnjNEUaG38VCO4WG9nfDQWE8/IOmt8DFRHXUIfZikaIXmsQTdWNFk0/e0j7RgIVRza86MpsJ+aHgFLg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"chalk": "^4.0.0",
|
||||
"strip-ansi": "^6.0.1",
|
||||
"text-table": "^0.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-scope": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
|
||||
@@ -10472,6 +10537,88 @@
|
||||
"url": "https://opencollective.com/eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-webpack-plugin": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-webpack-plugin/-/eslint-webpack-plugin-5.0.0.tgz",
|
||||
"integrity": "sha512-iDhXf2r55KO1UhMfpus8oGp93wdNF+934q5kEkwa7qn3BH9f51QEC11xQidt+8jfqRnEYYZa2/8lhac7U/vqWw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/eslint": "^9.6.1",
|
||||
"jest-worker": "^29.7.0",
|
||||
"micromatch": "^4.0.8",
|
||||
"normalize-path": "^3.0.0",
|
||||
"schema-utils": "^4.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18.12.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/webpack"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": "^8.0.0 || ^9.0.0",
|
||||
"webpack": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-webpack-plugin/node_modules/ajv": {
|
||||
"version": "8.17.1",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
|
||||
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"fast-uri": "^3.0.1",
|
||||
"json-schema-traverse": "^1.0.0",
|
||||
"require-from-string": "^2.0.2"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/epoberezkin"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-webpack-plugin/node_modules/ajv-keywords": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
|
||||
"integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"ajv": "^8.8.2"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-webpack-plugin/node_modules/json-schema-traverse": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
||||
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/eslint-webpack-plugin/node_modules/schema-utils": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.0.tgz",
|
||||
"integrity": "sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/json-schema": "^7.0.9",
|
||||
"ajv": "^8.9.0",
|
||||
"ajv-formats": "^2.1.1",
|
||||
"ajv-keywords": "^5.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.13.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/webpack"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint/node_modules/eslint-scope": {
|
||||
"version": "8.3.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz",
|
||||
@@ -10766,9 +10913,9 @@
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/express": {
|
||||
"version": "4.21.1",
|
||||
"resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz",
|
||||
"integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==",
|
||||
"version": "4.21.2",
|
||||
"resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz",
|
||||
"integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"accepts": "~1.3.8",
|
||||
@@ -10790,7 +10937,7 @@
|
||||
"methods": "~1.1.2",
|
||||
"on-finished": "2.4.1",
|
||||
"parseurl": "~1.3.3",
|
||||
"path-to-regexp": "0.1.10",
|
||||
"path-to-regexp": "0.1.12",
|
||||
"proxy-addr": "~2.0.7",
|
||||
"qs": "6.13.0",
|
||||
"range-parser": "~1.2.1",
|
||||
@@ -10805,6 +10952,10 @@
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.10.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/express"
|
||||
}
|
||||
},
|
||||
"node_modules/express-rate-limit": {
|
||||
@@ -14666,9 +14817,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "3.3.6",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
|
||||
"integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
|
||||
"version": "3.3.11",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
|
||||
"integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
@@ -15400,9 +15551,9 @@
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/path-to-regexp": {
|
||||
"version": "0.1.10",
|
||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz",
|
||||
"integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==",
|
||||
"version": "0.1.12",
|
||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz",
|
||||
"integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/path-type": {
|
||||
@@ -15959,25 +16110,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/postcss/node_modules/nanoid": {
|
||||
"version": "3.3.8",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz",
|
||||
"integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"nanoid": "bin/nanoid.cjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/postgres-array": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.2.tgz",
|
||||
@@ -18193,6 +18325,13 @@
|
||||
"integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/text-table": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
|
||||
"integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/thenify": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
|
||||
@@ -18560,13 +18699,13 @@
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/tsx": {
|
||||
"version": "4.19.1",
|
||||
"resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.1.tgz",
|
||||
"integrity": "sha512-0flMz1lh74BR4wOvBjuh9olbnwqCPc35OOlfyzHba0Dc+QNUeWX/Gq2YTbnwcWPO3BMd8fkzRVrHcsR+a7z7rA==",
|
||||
"version": "4.19.3",
|
||||
"resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.3.tgz",
|
||||
"integrity": "sha512-4H8vUNGNjQ4V2EOoGw005+c+dGuPSnhpPBPHBtsZdGZBk/iJb4kguGlPWaZTZ3q5nMtFOEsY0nRDlh9PJyd6SQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"esbuild": "~0.23.0",
|
||||
"esbuild": "~0.25.0",
|
||||
"get-tsconfig": "^4.7.5"
|
||||
},
|
||||
"bin": {
|
||||
@@ -18684,9 +18823,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/undici": {
|
||||
"version": "6.19.8",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-6.19.8.tgz",
|
||||
"integrity": "sha512-U8uCCl2x9TK3WANvmBavymRzxbfFYG+tAu+fgx3zxQy3qdagQqBLwJVrdyO1TBfUXvfKveMKJZhpvUYoOjM+4g==",
|
||||
"version": "6.21.1",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-6.21.1.tgz",
|
||||
"integrity": "sha512-q/1rj5D0/zayJB2FraXdaWxbhWiNKDvu8naDT2dl1yTlvJp4BLtOcp2a5BvgGNQpYYJzau7tf1WgKv3b+7mqpQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.17"
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
},
|
||||
"lint-staged": {
|
||||
"**/*": [
|
||||
"eslint --fix",
|
||||
"prettier --ignore-unknown --write"
|
||||
]
|
||||
},
|
||||
@@ -24,6 +25,7 @@
|
||||
"@babel/core": "^7.25.2",
|
||||
"@babel/preset-env": "^7.25.3",
|
||||
"@babel/preset-typescript": "^7.24.7",
|
||||
"@eslint/compat": "^1.2.7",
|
||||
"@eslint/js": "^9.21.0",
|
||||
"@types/chai": "^4.3.17",
|
||||
"@types/d3": "^7.4.3",
|
||||
@@ -45,6 +47,8 @@
|
||||
"css-loader": "^7.1.2",
|
||||
"eslint": "^9.21.0",
|
||||
"eslint-config-prettier": "^10.1.1",
|
||||
"eslint-formatter-gha": "^1.5.2",
|
||||
"eslint-webpack-plugin": "^5.0.0",
|
||||
"file-loader": "^6.2.0",
|
||||
"globals": "^16.0.0",
|
||||
"html-inline-script-webpack-plugin": "^3.2.1",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"main": {
|
||||
"title": "OpenFront (ALPHA)",
|
||||
"join_discord": "Join the Discord!",
|
||||
"create_lobby": "Create Lobby",
|
||||
"join_lobby": "Join Lobby",
|
||||
@@ -111,7 +112,9 @@
|
||||
"random": "Random",
|
||||
"iceland": "Iceland",
|
||||
"pangaea": "Pangaea",
|
||||
"japan": "Japan and Neighbors"
|
||||
"japan": "Japan and Neighbors",
|
||||
"twoseas": "Between Two Seas",
|
||||
"knownworld": "Known World"
|
||||
},
|
||||
"private_lobby": {
|
||||
"title": "Join Private Lobby",
|
||||
|
||||
@@ -1,126 +1,138 @@
|
||||
{
|
||||
"name": "Japan",
|
||||
"width": 2000,
|
||||
"height": 2000,
|
||||
"width": 1562,
|
||||
"height": 1646,
|
||||
"nations": [
|
||||
{
|
||||
"coordinates": [1340, 468],
|
||||
"coordinates": [1151, 709],
|
||||
"name": "Hokkaido",
|
||||
"strength": 3,
|
||||
"strength": 1,
|
||||
"flag": "jp"
|
||||
},
|
||||
{
|
||||
"coordinates": [1220, 830],
|
||||
"coordinates": [1005, 843],
|
||||
"name": "Tohoku",
|
||||
"strength": 3,
|
||||
"strength": 1,
|
||||
"flag": "jp"
|
||||
},
|
||||
{
|
||||
"coordinates": [1000, 1150],
|
||||
"coordinates": [858, 1045],
|
||||
"name": "Chubu",
|
||||
"strength": 3,
|
||||
"strength": 1,
|
||||
"flag": "jp"
|
||||
},
|
||||
{
|
||||
"coordinates": [1150, 1170],
|
||||
"coordinates": [948, 1037],
|
||||
"name": "Kanto",
|
||||
"strength": 3,
|
||||
"strength": 1,
|
||||
"flag": "jp"
|
||||
},
|
||||
{
|
||||
"coordinates": [860, 1260],
|
||||
"name": "Kinki",
|
||||
"strength": 3,
|
||||
"flag": "jp"
|
||||
},
|
||||
{
|
||||
"coordinates": [670, 1250],
|
||||
"name": "Chugoku",
|
||||
"strength": 3,
|
||||
"flag": "jp"
|
||||
},
|
||||
{
|
||||
"coordinates": [700, 1350],
|
||||
"name": "Shikoku",
|
||||
"strength": 3,
|
||||
"flag": "jp"
|
||||
},
|
||||
{
|
||||
"coordinates": [510, 1440],
|
||||
"name": "Kyushu",
|
||||
"strength": 3,
|
||||
"flag": "jp"
|
||||
},
|
||||
{
|
||||
"coordinates": [300, 1150],
|
||||
"name": "South Korea",
|
||||
"coordinates": [1162, 154],
|
||||
"name": "Sakhalin",
|
||||
"strength": 2,
|
||||
"flag": ""
|
||||
},
|
||||
{
|
||||
"coordinates": [571, 1116],
|
||||
"name": "Chugoku",
|
||||
"strength": 1,
|
||||
"flag": "jp"
|
||||
},
|
||||
{
|
||||
"coordinates": [8612, 1183],
|
||||
"name": "Shikoku",
|
||||
"strength": 2,
|
||||
"flag": "jp"
|
||||
},
|
||||
{
|
||||
"coordinates": [450, 1234],
|
||||
"name": "Kyushu",
|
||||
"strength": 2,
|
||||
"flag": "jp"
|
||||
},
|
||||
{
|
||||
"coordinates": [274, 1058],
|
||||
"name": "South Korea",
|
||||
"strength": 3,
|
||||
"flag": "kr"
|
||||
},
|
||||
{
|
||||
"coordinates": [220, 880],
|
||||
"coordinates": [160, 841],
|
||||
"name": "North Korea",
|
||||
"strength": 2,
|
||||
"strength": 1,
|
||||
"flag": "kp"
|
||||
},
|
||||
{
|
||||
"coordinates": [50, 50],
|
||||
"coordinates": [15, 795],
|
||||
"name": "China",
|
||||
"strength": 2,
|
||||
"strength": 3,
|
||||
"flag": "cn"
|
||||
},
|
||||
{
|
||||
"coordinates": [900, 200],
|
||||
"coordinates": [230, 75],
|
||||
"name": "Russia",
|
||||
"strength": 2,
|
||||
"strength": 3,
|
||||
"flag": "ru"
|
||||
},
|
||||
{
|
||||
"coordinates": [1030, 970],
|
||||
"coordinates": [898, 923],
|
||||
"name": "Sado Island",
|
||||
"strength": 2,
|
||||
"strength": 1,
|
||||
"flag": "jp"
|
||||
},
|
||||
{
|
||||
"coordinates": [670, 1130],
|
||||
"coordinates": [592, 1031],
|
||||
"name": "Oki Islands",
|
||||
"strength": 2,
|
||||
"strength": 1,
|
||||
"flag": "jp"
|
||||
},
|
||||
{
|
||||
"coordinates": [300, 1930],
|
||||
"name": "Okinawa",
|
||||
"coordinates": [741, 1108],
|
||||
"name": "Kyoto",
|
||||
"strength": 3,
|
||||
"flag": "jp"
|
||||
},
|
||||
{
|
||||
"coordinates": [1190, 680],
|
||||
"name": "Tsugaru Strait",
|
||||
"coordinates": [219, 972],
|
||||
"name": "Seoul",
|
||||
"strength": 3,
|
||||
"flag": "jp"
|
||||
"flag": "kr"
|
||||
},
|
||||
{
|
||||
"coordinates": [1130, 1190],
|
||||
"coordinates": [976, 1073],
|
||||
"name": "Tokyo",
|
||||
"strength": 3,
|
||||
"flag": "jp"
|
||||
},
|
||||
{
|
||||
"coordinates": [1060, 1190],
|
||||
"coordinates": [911, 1079],
|
||||
"name": "Mount Fuji",
|
||||
"strength": 3,
|
||||
"flag": "jp"
|
||||
},
|
||||
{
|
||||
"coordinates": [1500, 420],
|
||||
"coordinates": [1298, 564],
|
||||
"name": "Shiretoko Peninsula",
|
||||
"strength": 1,
|
||||
"flag": "jp"
|
||||
},
|
||||
{
|
||||
"coordinates": [435, 1311],
|
||||
"name": "Sakurajima",
|
||||
"strength": 1,
|
||||
"flag": "jp"
|
||||
},
|
||||
{
|
||||
"coordinates": [275, 1614],
|
||||
"name": "Okinawa",
|
||||
"strength": 3,
|
||||
"flag": "jp"
|
||||
},
|
||||
{
|
||||
"coordinates": [490, 1530],
|
||||
"name": "Sakurajima",
|
||||
"strength": 3,
|
||||
"coordinates": [731, 1115],
|
||||
"name": "Kinki",
|
||||
"strength": 1,
|
||||
"flag": "jp"
|
||||
}
|
||||
]
|
||||
|
||||
|
Before Width: | Height: | Size: 386 KiB After Width: | Height: | Size: 9.8 MiB |
|
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 14 KiB |
@@ -0,0 +1,362 @@
|
||||
{
|
||||
"name": "Known_World",
|
||||
"width": 2652,
|
||||
"height": 1522,
|
||||
"nations": [
|
||||
{
|
||||
"coordinates": [297, 84],
|
||||
"name": "Free Folk",
|
||||
"strength": 2
|
||||
},
|
||||
{
|
||||
"coordinates": [352, 160],
|
||||
"name": "Nights Watch",
|
||||
"strength": 2
|
||||
},
|
||||
{
|
||||
"coordinates": [174, 227],
|
||||
"name": "House Mormont",
|
||||
"strength": 1
|
||||
},
|
||||
{
|
||||
"coordinates": [504, 186],
|
||||
"name": "House Magnar",
|
||||
"strength": 1
|
||||
},
|
||||
{
|
||||
"coordinates": [381, 249],
|
||||
"name": "House Umber",
|
||||
"strength": 1
|
||||
},
|
||||
{
|
||||
"coordinates": [494, 295],
|
||||
"name": "House Karstark",
|
||||
"strength": 1
|
||||
},
|
||||
{
|
||||
"coordinates": [383, 343],
|
||||
"name": "House Bolton",
|
||||
"strength": 2
|
||||
},
|
||||
{
|
||||
"coordinates": [374, 495],
|
||||
"name": "House locke",
|
||||
"strength": 2
|
||||
},
|
||||
{
|
||||
"coordinates": [275, 377],
|
||||
"name": "House Stark",
|
||||
"strength": 3
|
||||
},
|
||||
{
|
||||
"coordinates": [113, 411],
|
||||
"name": "House Ryswell",
|
||||
"strength": 1
|
||||
},
|
||||
{
|
||||
"coordinates": [248, 546],
|
||||
"name": "House Reed",
|
||||
"strength": 1
|
||||
},
|
||||
{
|
||||
"coordinates": [116, 570],
|
||||
"name": "House Flint's Finger",
|
||||
"strength": 1
|
||||
},
|
||||
{
|
||||
"coordinates": [256, 628],
|
||||
"name": "House Frey",
|
||||
"strength": 2
|
||||
},
|
||||
{
|
||||
"coordinates": [535, 700],
|
||||
"name": "House Royce",
|
||||
"strength": 1
|
||||
},
|
||||
{
|
||||
"coordinates": [396, 687],
|
||||
"name": "House Arryn",
|
||||
"strength": 3
|
||||
},
|
||||
{
|
||||
"coordinates": [416, 623],
|
||||
"name": "House Corbray",
|
||||
"strength": 2
|
||||
},
|
||||
{
|
||||
"coordinates": [246, 746],
|
||||
"name": "Hous Tully",
|
||||
"strength": 3
|
||||
},
|
||||
{
|
||||
"coordinates": [104, 830],
|
||||
"name": "House Lannister",
|
||||
"strength": 3
|
||||
},
|
||||
{
|
||||
"coordinates": [89, 697],
|
||||
"name": "House Greyjoy",
|
||||
"strength": 2
|
||||
},
|
||||
{
|
||||
"coordinates": [128, 729],
|
||||
"name": "House Banefort",
|
||||
"strength": 1
|
||||
},
|
||||
{
|
||||
"coordinates": [325, 767],
|
||||
"name": "Harrenhall",
|
||||
"strength": 1
|
||||
},
|
||||
{
|
||||
"coordinates": [190, 927],
|
||||
"name": "House Rowan",
|
||||
"strength": 1
|
||||
},
|
||||
{
|
||||
"coordinates": [383, 864],
|
||||
"name": "Kings Landing",
|
||||
"strength": 3
|
||||
},
|
||||
{
|
||||
"coordinates": [475, 820],
|
||||
"name": "Dragonstone",
|
||||
"strength": 2
|
||||
},
|
||||
{
|
||||
"coordinates": [333, 902],
|
||||
"name": "House Meadows",
|
||||
"strength": 2
|
||||
},
|
||||
{
|
||||
"coordinates": [169, 1006],
|
||||
"name": "House Tyrell",
|
||||
"strength": 3
|
||||
},
|
||||
{
|
||||
"coordinates": [301, 1030],
|
||||
"name": "House Selmy",
|
||||
"strength": 1
|
||||
},
|
||||
{
|
||||
"coordinates": [456, 975],
|
||||
"name": "House Baratheon",
|
||||
"strength": 3
|
||||
},
|
||||
{
|
||||
"coordinates": [523, 963],
|
||||
"name": "House Tarth",
|
||||
"strength": 1
|
||||
},
|
||||
{
|
||||
"coordinates": [514, 1156],
|
||||
"name": "House Martell",
|
||||
"strength": 3
|
||||
},
|
||||
{
|
||||
"coordinates": [403, 1189],
|
||||
"name": "House Vaith",
|
||||
"strength": 1
|
||||
},
|
||||
{
|
||||
"coordinates": [330, 1122],
|
||||
"name": "House Yronwood",
|
||||
"strength": 2
|
||||
},
|
||||
{
|
||||
"coordinates": [251, 1158],
|
||||
"name": "House Qorgyle",
|
||||
"strength": 1
|
||||
},
|
||||
{
|
||||
"coordinates": [188, 1148],
|
||||
"name": "House Dayne",
|
||||
"strength": 1
|
||||
},
|
||||
{
|
||||
"coordinates": [108, 1090],
|
||||
"name": "House Hightower",
|
||||
"strength": 2
|
||||
},
|
||||
{
|
||||
"coordinates": [176, 1045],
|
||||
"name": "House Tarly",
|
||||
"strength": 1
|
||||
},
|
||||
{
|
||||
"coordinates": [80, 900],
|
||||
"name": "House Craekham",
|
||||
"strength": 1
|
||||
},
|
||||
{
|
||||
"coordinates": [183, 808],
|
||||
"name": "House Brax",
|
||||
"strength": 1
|
||||
},
|
||||
{
|
||||
"coordinates": [460, 748],
|
||||
"name": "House Redfort",
|
||||
"strength": 1
|
||||
},
|
||||
{
|
||||
"coordinates": [651, 630],
|
||||
"name": "Free City Of Bravos",
|
||||
"strength": 3
|
||||
},
|
||||
{
|
||||
"coordinates": [658, 871],
|
||||
"name": "Free City Of Pentos",
|
||||
"strength": 2
|
||||
},
|
||||
{
|
||||
"coordinates": [702, 1049],
|
||||
"name": "Free City Of Myr",
|
||||
"strength": 2
|
||||
},
|
||||
{
|
||||
"coordinates": [603, 1042],
|
||||
"name": "Free City Of Tyrosh",
|
||||
"strength": 2
|
||||
},
|
||||
{
|
||||
"coordinates": [933, 1177],
|
||||
"name": "Free City Of Volantis",
|
||||
"strength": 3
|
||||
},
|
||||
{
|
||||
"coordinates": [974, 871],
|
||||
"name": "Free City Of Qohor",
|
||||
"strength": 2
|
||||
},
|
||||
{
|
||||
"coordinates": [894, 779],
|
||||
"name": "Free City Of Norvos",
|
||||
"strength": 2
|
||||
},
|
||||
{
|
||||
"coordinates": [1157, 770],
|
||||
"name": "Samor",
|
||||
"strength": 1
|
||||
},
|
||||
{
|
||||
"coordinates": [1119, 1163],
|
||||
"name": "Mantarys",
|
||||
"strength": 2
|
||||
},
|
||||
{
|
||||
"coordinates": [1184, 1170],
|
||||
"name": "Tolos",
|
||||
"strength": 2
|
||||
},
|
||||
{
|
||||
"coordinates": [1312, 664],
|
||||
"name": "Omber",
|
||||
"strength": 1
|
||||
},
|
||||
{
|
||||
"coordinates": [1610, 779],
|
||||
"name": "Vaes Dothrak",
|
||||
"strength": 3
|
||||
},
|
||||
{
|
||||
"coordinates": [1651, 500],
|
||||
"name": "New Ibbish",
|
||||
"strength": 2
|
||||
},
|
||||
{
|
||||
"coordinates": [1381, 1093],
|
||||
"name": "Meereen",
|
||||
"strength": 2
|
||||
},
|
||||
{
|
||||
"coordinates": [1343, 1134],
|
||||
"name": "Yunkai",
|
||||
"strength": 2
|
||||
},
|
||||
{
|
||||
"coordinates": [1319, 1230],
|
||||
"name": "Astaphor",
|
||||
"strength": 2
|
||||
},
|
||||
{
|
||||
"coordinates": [1606, 1310],
|
||||
"name": "Port Yhos",
|
||||
"strength": 1
|
||||
},
|
||||
{
|
||||
"coordinates": [1555, 1110],
|
||||
"name": "Lhazar",
|
||||
"strength": 1
|
||||
},
|
||||
{
|
||||
"coordinates": [1832, 1054],
|
||||
"name": "Zabhad",
|
||||
"strength": 3
|
||||
},
|
||||
{
|
||||
"coordinates": [1796, 1300],
|
||||
"name": "Qarth",
|
||||
"strength": 3
|
||||
},
|
||||
{
|
||||
"coordinates": [1753, 1483],
|
||||
"name": "Vahar",
|
||||
"strength": 2
|
||||
},
|
||||
{
|
||||
"coordinates": [1779, 1414],
|
||||
"name": "Faros",
|
||||
"strength": 2
|
||||
},
|
||||
{
|
||||
"coordinates": [2107, 1315],
|
||||
"name": "Yi Ti",
|
||||
"strength": 3
|
||||
},
|
||||
{
|
||||
"coordinates": [2233, 1462],
|
||||
"name": "Leng",
|
||||
"strength": 2
|
||||
},
|
||||
{
|
||||
"coordinates": [2312, 1363],
|
||||
"name": "Jinqi",
|
||||
"strength": 2
|
||||
},
|
||||
{
|
||||
"coordinates": [2563, 1474],
|
||||
"name": "Shadow Lands",
|
||||
"strength": 2
|
||||
},
|
||||
{
|
||||
"coordinates": [2536, 647],
|
||||
"name": "Mossovy",
|
||||
"strength": 2
|
||||
},
|
||||
{
|
||||
"coordinates": [2151, 847],
|
||||
"name": "Jogos Nhai",
|
||||
"strength": 3
|
||||
},
|
||||
{
|
||||
"coordinates": [1415, 1348],
|
||||
"name": "Ghis",
|
||||
"strength": 2
|
||||
},
|
||||
{
|
||||
"coordinates": [1362, 1397],
|
||||
"name": "Ghaen",
|
||||
"strength": 2
|
||||
},
|
||||
{
|
||||
"coordinates": [1849, 1450],
|
||||
"name": "Great Moraq",
|
||||
"strength": 3
|
||||
},
|
||||
{
|
||||
"coordinates": [2351, 782],
|
||||
"name": "N'Ghai",
|
||||
"strength": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 15 MiB |
|
After Width: | Height: | Size: 15 KiB |
@@ -1,216 +1,216 @@
|
||||
{
|
||||
"name": "MENA",
|
||||
"width": 2000,
|
||||
"height": 1000,
|
||||
"width": 2200,
|
||||
"height": 964,
|
||||
"nations": [
|
||||
{
|
||||
"coordinates": [200, 100],
|
||||
"coordinates": [257, 82],
|
||||
"name": "Spain",
|
||||
"strength": 1,
|
||||
"strength": 3,
|
||||
"flag": "es"
|
||||
},
|
||||
{
|
||||
"coordinates": [50, 135],
|
||||
"coordinates": [142, 134],
|
||||
"name": "Portugal",
|
||||
"strength": 1,
|
||||
"strength": 2,
|
||||
"flag": "pt"
|
||||
},
|
||||
{
|
||||
"coordinates": [125, 375],
|
||||
"coordinates": [142, 348],
|
||||
"name": "Morocco",
|
||||
"strength": 1,
|
||||
"flag": "ma"
|
||||
},
|
||||
{
|
||||
"coordinates": [425, 300],
|
||||
"coordinates": [490, 296],
|
||||
"name": "Algeria",
|
||||
"strength": 1,
|
||||
"flag": "dz"
|
||||
},
|
||||
{
|
||||
"coordinates": [600, 275],
|
||||
"coordinates": [675, 225],
|
||||
"name": "Tunisia",
|
||||
"strength": 1,
|
||||
"flag": "tn"
|
||||
},
|
||||
{
|
||||
"coordinates": [750, 450],
|
||||
"coordinates": [825, 352],
|
||||
"name": "Libyan Arab Jamahiriya",
|
||||
"strength": 1,
|
||||
"flag": "ly"
|
||||
},
|
||||
{
|
||||
"coordinates": [1100, 450],
|
||||
"coordinates": [1280, 389],
|
||||
"name": "Egypt",
|
||||
"strength": 1,
|
||||
"strength": 2,
|
||||
"flag": "eg"
|
||||
},
|
||||
{
|
||||
"coordinates": [1333, 333],
|
||||
"coordinates": [1444, 341],
|
||||
"name": "Israel",
|
||||
"strength": 1,
|
||||
"strength": 3,
|
||||
"flag": "il"
|
||||
},
|
||||
{
|
||||
"coordinates": [1338, 388],
|
||||
"coordinates": [1409, 372],
|
||||
"name": "Palestinian Territory, Occupied",
|
||||
"strength": 1,
|
||||
"flag": "ps"
|
||||
},
|
||||
{
|
||||
"coordinates": [1370, 325],
|
||||
"coordinates": [1460, 294],
|
||||
"name": "Lebanon",
|
||||
"strength": 1,
|
||||
"flag": "lb"
|
||||
},
|
||||
{
|
||||
"coordinates": [1228, 728],
|
||||
"coordinates": [1259, 761],
|
||||
"name": "Sudan",
|
||||
"strength": 1,
|
||||
"flag": "sd"
|
||||
},
|
||||
{
|
||||
"coordinates": [1450, 275],
|
||||
"coordinates": [1500, 221],
|
||||
"name": "Syrian Arab Republic",
|
||||
"strength": 1,
|
||||
"flag": "sy"
|
||||
},
|
||||
{
|
||||
"coordinates": [1600, 300],
|
||||
"coordinates": [1743, 303],
|
||||
"name": "Iraq",
|
||||
"strength": 1,
|
||||
"strength": 2,
|
||||
"flag": "iq"
|
||||
},
|
||||
{
|
||||
"coordinates": [1550, 600],
|
||||
"coordinates": [1729, 534],
|
||||
"name": "Saudi Arabia",
|
||||
"strength": 1,
|
||||
"strength": 3,
|
||||
"flag": "sa"
|
||||
},
|
||||
{
|
||||
"coordinates": [1700, 850],
|
||||
"coordinates": [1726, 884],
|
||||
"name": "Yemen",
|
||||
"strength": 1,
|
||||
"flag": "ye"
|
||||
},
|
||||
{
|
||||
"coordinates": [1950, 725],
|
||||
"coordinates": [2134, 654],
|
||||
"name": "Oman",
|
||||
"strength": 1,
|
||||
"flag": "om"
|
||||
},
|
||||
{
|
||||
"coordinates": [1860, 620],
|
||||
"coordinates": [2025, 576],
|
||||
"name": "United Arab Emirates",
|
||||
"strength": 1,
|
||||
"flag": "ae"
|
||||
},
|
||||
{
|
||||
"coordinates": [1730, 580],
|
||||
"coordinates": [1924, 538],
|
||||
"name": "Qatar",
|
||||
"strength": 1,
|
||||
"flag": "qa"
|
||||
},
|
||||
{
|
||||
"coordinates": [1900, 350],
|
||||
"name": "Iran, Islamic Republic Of",
|
||||
"strength": 1,
|
||||
"coordinates": [1948, 333],
|
||||
"name": "Islamic Republic of Iran",
|
||||
"strength": 3,
|
||||
"flag": "ir"
|
||||
},
|
||||
{
|
||||
"coordinates": [1300, 150],
|
||||
"name": "Turkey",
|
||||
"strength": 1,
|
||||
"coordinates": [1313, 127],
|
||||
"name": "Turkiye",
|
||||
"strength": 3,
|
||||
"flag": "tr"
|
||||
},
|
||||
{
|
||||
"coordinates": [675, 50],
|
||||
"coordinates": [776, 39],
|
||||
"name": "Italy",
|
||||
"strength": 1,
|
||||
"strength": 2,
|
||||
"flag": "it"
|
||||
},
|
||||
{
|
||||
"coordinates": [950, 125],
|
||||
"coordinates": [1087, 145],
|
||||
"name": "Greece",
|
||||
"strength": 1,
|
||||
"strength": 2,
|
||||
"flag": "gr"
|
||||
},
|
||||
{
|
||||
"coordinates": [1000, 25],
|
||||
"coordinates": [1181, 20],
|
||||
"name": "Bulgaria",
|
||||
"strength": 1,
|
||||
"flag": "bg"
|
||||
},
|
||||
{
|
||||
"coordinates": [1980, 45],
|
||||
"coordinates": [2156, 18],
|
||||
"name": "Uzbekistan",
|
||||
"strength": 1,
|
||||
"flag": "uz"
|
||||
},
|
||||
{
|
||||
"coordinates": [1400, 400],
|
||||
"coordinates": [1480, 342],
|
||||
"name": "Jordan",
|
||||
"strength": 1,
|
||||
"flag": "jo"
|
||||
},
|
||||
{
|
||||
"coordinates": [750, 930],
|
||||
"coordinates": [1050, 725],
|
||||
"name": "Chad",
|
||||
"strength": 1,
|
||||
"strength": 2,
|
||||
"flag": "td"
|
||||
},
|
||||
{
|
||||
"coordinates": [500, 900],
|
||||
"coordinates": [767, 734],
|
||||
"name": "Niger",
|
||||
"strength": 1,
|
||||
"strength": 2,
|
||||
"flag": "ne"
|
||||
},
|
||||
{
|
||||
"coordinates": [230, 940],
|
||||
"coordinates": [408, 553],
|
||||
"name": "Mali",
|
||||
"strength": 1,
|
||||
"flag": "ml"
|
||||
},
|
||||
{
|
||||
"coordinates": [40, 830],
|
||||
"name": "Mauritania",
|
||||
"coordinates": [98, 55],
|
||||
"name": "2",
|
||||
"strength": 1,
|
||||
"flag": "mr"
|
||||
},
|
||||
{
|
||||
"coordinates": [1490, 980],
|
||||
"coordinates": [1562, 828],
|
||||
"name": "Eritrea",
|
||||
"strength": 1,
|
||||
"flag": "er"
|
||||
},
|
||||
{
|
||||
"coordinates": [1630, 460],
|
||||
"coordinates": [1811, 414],
|
||||
"name": "Kuwait",
|
||||
"strength": 1,
|
||||
"flag": "kw"
|
||||
},
|
||||
{
|
||||
"coordinates": [1550, 25],
|
||||
"coordinates": [1667, 30],
|
||||
"name": "Georgia",
|
||||
"strength": 1,
|
||||
"flag": "ge"
|
||||
},
|
||||
{
|
||||
"coordinates": [1640, 100],
|
||||
"coordinates": [1848, 116],
|
||||
"name": "Azerbaijan",
|
||||
"strength": 1,
|
||||
"flag": "az"
|
||||
},
|
||||
{
|
||||
"coordinates": [1226, 280],
|
||||
"coordinates": [1385, 248],
|
||||
"name": "Cyprus",
|
||||
"strength": 1,
|
||||
"flag": "cy"
|
||||
},
|
||||
{
|
||||
"coordinates": [1800, 40],
|
||||
"coordinates": [1994, 19],
|
||||
"name": "Kazakhstan",
|
||||
"strength": 1,
|
||||
"strength": 2,
|
||||
"flag": "kz"
|
||||
}
|
||||
]
|
||||
|
||||
|
Before Width: | Height: | Size: 1.2 MiB After Width: | Height: | Size: 6.1 MiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 16 KiB |
@@ -0,0 +1,91 @@
|
||||
{
|
||||
"name": "TwoSeas",
|
||||
"width": 1778,
|
||||
"height": 1062,
|
||||
"nations": [
|
||||
{
|
||||
"coordinates": [40, 674],
|
||||
"name": "Bulgaria",
|
||||
"strength": 2,
|
||||
"flag": "bg"
|
||||
},
|
||||
{
|
||||
"coordinates": [354, 820],
|
||||
"name": "Republic of Turkiye",
|
||||
"strength": 3,
|
||||
"flag": "tr"
|
||||
},
|
||||
{
|
||||
"coordinates": [105, 474],
|
||||
"name": "Romania",
|
||||
"strength": 2,
|
||||
"flag": "ro"
|
||||
},
|
||||
{
|
||||
"coordinates": [172, 382],
|
||||
"name": "Moldova",
|
||||
"strength": 2,
|
||||
"flag": "md"
|
||||
},
|
||||
{
|
||||
"coordinates": [465, 296],
|
||||
"name": "Ukraine",
|
||||
"strength": 3,
|
||||
"flag": "ua"
|
||||
},
|
||||
{
|
||||
"coordinates": [980, 24],
|
||||
"name": "Russian Federation",
|
||||
"strength": 3,
|
||||
"flag": "ru"
|
||||
},
|
||||
{
|
||||
"coordinates": [1003, 674],
|
||||
"name": "Georgia",
|
||||
"strength": 1,
|
||||
"flag": "ge"
|
||||
},
|
||||
{
|
||||
"coordinates": [1131, 804],
|
||||
"name": "Republic of Armenia",
|
||||
"strength": 1,
|
||||
"flag": "am"
|
||||
},
|
||||
{
|
||||
"coordinates": [856, 1044],
|
||||
"name": "Syrian Arab Republic",
|
||||
"strength": 2,
|
||||
"flag": "sy"
|
||||
},
|
||||
{
|
||||
"coordinates": [1355, 1022],
|
||||
"name": "Islamic Republic of Iran",
|
||||
"strength": 3,
|
||||
"flag": "ir"
|
||||
},
|
||||
{
|
||||
"coordinates": [1355, 18],
|
||||
"name": "Republic of Azerbaijan",
|
||||
"strength": 1,
|
||||
"flag": "az"
|
||||
},
|
||||
{
|
||||
"coordinates": [334, 18],
|
||||
"name": "Belarus",
|
||||
"strength": 1,
|
||||
"flag": "by"
|
||||
},
|
||||
{
|
||||
"coordinates": [1689, 467],
|
||||
"name": "Kazakhstan",
|
||||
"strength": 1,
|
||||
"flag": "kz"
|
||||
},
|
||||
{
|
||||
"coordinates": [1727, 831],
|
||||
"name": "Turkmenistan",
|
||||
"strength": 1,
|
||||
"flag": "tm"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 7.2 MiB |
|
After Width: | Height: | Size: 14 KiB |
@@ -25,7 +25,7 @@ import { loadTerrainMap } from "../core/game/TerrainMapLoader";
|
||||
import { UserSettings } from "../core/game/UserSettings";
|
||||
import { WorkerClient } from "../core/worker/WorkerClient";
|
||||
import { InputHandler, MouseMoveEvent, MouseUpEvent } from "./InputHandler";
|
||||
import { LocalPersistantStats } from "./LocalPersistantStats";
|
||||
import { endGame, startGame, startTime } from "./LocalPersistantStats";
|
||||
import { getPersistentIDFromCookie } from "./Main";
|
||||
import {
|
||||
SendAttackIntentEvent,
|
||||
@@ -36,6 +36,7 @@ import {
|
||||
import { createCanvas } from "./Utils";
|
||||
import { createRenderer, GameRenderer } from "./graphics/GameRenderer";
|
||||
|
||||
export // Is this function needed?
|
||||
function distSortUnitWorld(tile: TileRef, game: GameView) {
|
||||
return (a: Unit | UnitView, b: Unit | UnitView) => {
|
||||
return (
|
||||
@@ -69,10 +70,7 @@ export function joinLobby(
|
||||
);
|
||||
|
||||
const userSettings: UserSettings = new UserSettings();
|
||||
LocalPersistantStats.startGame(
|
||||
lobbyConfig.gameID,
|
||||
lobbyConfig.gameStartInfo?.config,
|
||||
);
|
||||
startGame(lobbyConfig.gameID, lobbyConfig.gameStartInfo?.config);
|
||||
|
||||
const transport = new Transport(lobbyConfig, eventBus);
|
||||
|
||||
@@ -158,8 +156,9 @@ export class ClientGameRunner {
|
||||
private hasJoined = false;
|
||||
|
||||
private lastMousePosition: { x: number; y: number } | null = null;
|
||||
private mouseHoverTimer: number | null = null;
|
||||
private readonly HOVER_DELAY = 200;
|
||||
|
||||
private lastMessageTime: number = 0;
|
||||
private connectionCheckInterval: NodeJS.Timeout | null = null;
|
||||
|
||||
constructor(
|
||||
private lobby: LobbyConfig,
|
||||
@@ -169,7 +168,9 @@ export class ClientGameRunner {
|
||||
private transport: Transport,
|
||||
private worker: WorkerClient,
|
||||
private gameView: GameView,
|
||||
) {}
|
||||
) {
|
||||
this.lastMessageTime = Date.now();
|
||||
}
|
||||
|
||||
private saveGame(update: WinUpdate) {
|
||||
const players: PlayerRecord[] = [
|
||||
@@ -195,18 +196,25 @@ export class ClientGameRunner {
|
||||
players,
|
||||
// Not saving turns locally
|
||||
[],
|
||||
LocalPersistantStats.startTime(),
|
||||
startTime(),
|
||||
Date.now(),
|
||||
winner,
|
||||
update.winnerType,
|
||||
update.allPlayersStats,
|
||||
);
|
||||
LocalPersistantStats.endGame(record);
|
||||
endGame(record);
|
||||
}
|
||||
|
||||
public start() {
|
||||
consolex.log("starting client game");
|
||||
this.isActive = true;
|
||||
this.lastMessageTime = Date.now();
|
||||
setTimeout(() => {
|
||||
this.connectionCheckInterval = setInterval(
|
||||
() => this.onConnectionCheck(),
|
||||
1000,
|
||||
);
|
||||
}, 20000);
|
||||
this.eventBus.on(MouseUpEvent, (e) => this.inputEvent(e));
|
||||
this.eventBus.on(MouseMoveEvent, (e) => this.onMouseMove(e));
|
||||
|
||||
@@ -245,6 +253,7 @@ export class ClientGameRunner {
|
||||
this.transport.joinGame(this.turnsSeen);
|
||||
};
|
||||
const onmessage = (message: ServerMessage) => {
|
||||
this.lastMessageTime = Date.now();
|
||||
if (message.type == "start") {
|
||||
this.hasJoined = true;
|
||||
consolex.log("starting game!");
|
||||
@@ -296,6 +305,10 @@ export class ClientGameRunner {
|
||||
this.worker.cleanup();
|
||||
this.isActive = false;
|
||||
this.transport.leaveGame(saveFullGame);
|
||||
if (this.connectionCheckInterval) {
|
||||
clearInterval(this.connectionCheckInterval);
|
||||
this.connectionCheckInterval = null;
|
||||
}
|
||||
}
|
||||
|
||||
private inputEvent(event: MouseUpEvent) {
|
||||
@@ -391,6 +404,20 @@ export class ClientGameRunner {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private onConnectionCheck() {
|
||||
if (this.transport.isLocal) {
|
||||
return;
|
||||
}
|
||||
const timeSinceLastMessage = Date.now() - this.lastMessageTime;
|
||||
if (timeSinceLastMessage > 5000) {
|
||||
console.log(
|
||||
`No message from server for ${timeSinceLastMessage} ms, reconnecting`,
|
||||
);
|
||||
this.lastMessageTime = Date.now();
|
||||
this.transport.reconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function showErrorModal(
|
||||
|
||||
@@ -3,7 +3,7 @@ import { customElement, property } from "lit/decorators.js";
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
adsbygoogle: any[];
|
||||
adsbygoogle: unknown[];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ const isElectron = () => {
|
||||
if (
|
||||
typeof window !== "undefined" &&
|
||||
typeof window.process === "object" &&
|
||||
// @ts-ignore
|
||||
// @ts-expect-error hidden
|
||||
window.process.type === "renderer"
|
||||
) {
|
||||
return true;
|
||||
|
||||
@@ -432,6 +432,7 @@ export class HostLobbyModal extends LitElement {
|
||||
} as GameConfig),
|
||||
},
|
||||
);
|
||||
return response;
|
||||
}
|
||||
|
||||
private getRandomMap(): GameMapType {
|
||||
@@ -460,6 +461,7 @@ export class HostLobbyModal extends LitElement {
|
||||
},
|
||||
},
|
||||
);
|
||||
return response;
|
||||
}
|
||||
|
||||
private async copyToClipboard() {
|
||||
|
||||
@@ -93,7 +93,7 @@ export class InputHandler {
|
||||
|
||||
private alternateView = false;
|
||||
|
||||
private moveInterval: any = null;
|
||||
private moveInterval: NodeJS.Timeout = null;
|
||||
private activeKeys = new Set<string>();
|
||||
|
||||
private readonly PAN_SPEED = 5;
|
||||
|
||||
@@ -20,10 +20,12 @@ const translations = {
|
||||
es: esTranslations,
|
||||
};
|
||||
|
||||
type Translation = Partial<(typeof translations)[keyof typeof translations]>;
|
||||
|
||||
@customElement("lang-selector")
|
||||
export class LangSelector extends LitElement {
|
||||
@state() public translations: any = {};
|
||||
@state() private defaultTranslations: any = {};
|
||||
@state() public translations: Translation = {};
|
||||
@state() private defaultTranslations = {};
|
||||
@state() private currentLang: string = "en";
|
||||
|
||||
createRenderRoot() {
|
||||
@@ -44,10 +46,10 @@ export class LangSelector extends LitElement {
|
||||
this.translations = await this.loadLanguage(userLang);
|
||||
this.currentLang = userLang;
|
||||
|
||||
this.applyTranslation(this.translations);
|
||||
this.applyTranslation();
|
||||
}
|
||||
|
||||
private async loadLanguage(lang: string): Promise<any> {
|
||||
private async loadLanguage(lang: string): Promise<Translation> {
|
||||
try {
|
||||
const translation = translations[lang as keyof typeof translations];
|
||||
if (!translation) throw new Error(`Language file not found: ${lang}`);
|
||||
@@ -58,7 +60,7 @@ export class LangSelector extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
private applyTranslation(translations: any) {
|
||||
private applyTranslation() {
|
||||
const components = [
|
||||
"single-player-modal",
|
||||
"host-lobby-modal",
|
||||
@@ -75,24 +77,14 @@ export class LangSelector extends LitElement {
|
||||
"public-lobby",
|
||||
];
|
||||
|
||||
document.title = translations.main?.title || document.title;
|
||||
const main = this.translations.main;
|
||||
if (main && "title" in main) {
|
||||
document.title = main.title;
|
||||
}
|
||||
|
||||
document.querySelectorAll("[data-i18n]").forEach((element) => {
|
||||
const key = element.getAttribute("data-i18n");
|
||||
const keys = key.split(".");
|
||||
let text = translations;
|
||||
for (const k of keys) {
|
||||
text = text?.[k];
|
||||
if (!text) break;
|
||||
}
|
||||
if (!text && this.defaultTranslations) {
|
||||
let fallback = this.defaultTranslations;
|
||||
for (const k of keys) {
|
||||
fallback = fallback?.[k];
|
||||
if (!fallback) break;
|
||||
}
|
||||
text = fallback;
|
||||
}
|
||||
const text = this.translateText(key);
|
||||
if (text) {
|
||||
element.innerHTML = text;
|
||||
} else {
|
||||
@@ -101,7 +93,7 @@ export class LangSelector extends LitElement {
|
||||
});
|
||||
|
||||
components.forEach((tagName) => {
|
||||
const el = document.querySelector(tagName) as any;
|
||||
const el = document.querySelector(tagName) as LitElement;
|
||||
if (el && typeof el.requestUpdate === "function") {
|
||||
el.requestUpdate();
|
||||
} else {
|
||||
@@ -117,19 +109,13 @@ export class LangSelector extends LitElement {
|
||||
params: Record<string, string | number> = {},
|
||||
): string {
|
||||
const keys = key.split(".");
|
||||
let text: any = this.translations;
|
||||
|
||||
for (const k of keys) {
|
||||
text = text?.[k];
|
||||
if (!text) break;
|
||||
let text = findTranslation(keys, this.translations);
|
||||
if (!text && this.defaultTranslations) {
|
||||
text = findTranslation(keys, this.defaultTranslations);
|
||||
}
|
||||
|
||||
if (!text && this.defaultTranslations) {
|
||||
text = this.defaultTranslations;
|
||||
for (const k of keys) {
|
||||
text = text?.[k];
|
||||
if (!text) return key;
|
||||
}
|
||||
if (text == null || typeof text !== "string") {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (const [param, value] of Object.entries(params)) {
|
||||
@@ -143,7 +129,7 @@ export class LangSelector extends LitElement {
|
||||
localStorage.setItem("lang", lang);
|
||||
this.translations = await this.loadLanguage(lang);
|
||||
this.currentLang = lang;
|
||||
this.applyTranslation(this.translations);
|
||||
this.applyTranslation();
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -178,3 +164,19 @@ export class LangSelector extends LitElement {
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
function findTranslation(
|
||||
keys: string[],
|
||||
translations: Translation,
|
||||
): string | null {
|
||||
let ptr: unknown = translations;
|
||||
for (const k of keys) {
|
||||
ptr = ptr?.[k];
|
||||
if (!ptr) break;
|
||||
}
|
||||
if (ptr && typeof ptr === "string") {
|
||||
return ptr;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,53 +9,51 @@ export interface LocalStatsData {
|
||||
};
|
||||
}
|
||||
|
||||
export namespace LocalPersistantStats {
|
||||
let _startTime: number;
|
||||
let _startTime: number;
|
||||
|
||||
function getStats(): LocalStatsData {
|
||||
const statsStr = localStorage.getItem("game-records");
|
||||
return statsStr ? JSON.parse(statsStr) : {};
|
||||
}
|
||||
|
||||
function save(stats: LocalStatsData) {
|
||||
// To execute asynchronously
|
||||
setTimeout(
|
||||
() => localStorage.setItem("game-records", JSON.stringify(stats)),
|
||||
0,
|
||||
);
|
||||
}
|
||||
|
||||
// The user can quit the game anytime so better save the lobby as soon as the
|
||||
// game starts.
|
||||
export function startGame(id: GameID, lobby: GameConfig) {
|
||||
if (typeof localStorage === "undefined") {
|
||||
return;
|
||||
}
|
||||
|
||||
_startTime = Date.now();
|
||||
const stats = getStats();
|
||||
stats[id] = { lobby };
|
||||
save(stats);
|
||||
}
|
||||
|
||||
export function startTime() {
|
||||
return _startTime;
|
||||
}
|
||||
|
||||
export function endGame(gameRecord: GameRecord) {
|
||||
if (typeof localStorage === "undefined") {
|
||||
return;
|
||||
}
|
||||
|
||||
const stats = getStats();
|
||||
const gameStat = stats[gameRecord.id];
|
||||
|
||||
if (!gameStat) {
|
||||
consolex.log("LocalPersistantStats: game not found");
|
||||
return;
|
||||
}
|
||||
|
||||
gameStat.gameRecord = gameRecord;
|
||||
save(stats);
|
||||
}
|
||||
function getStats(): LocalStatsData {
|
||||
const statsStr = localStorage.getItem("game-records");
|
||||
return statsStr ? JSON.parse(statsStr) : {};
|
||||
}
|
||||
|
||||
function save(stats: LocalStatsData) {
|
||||
// To execute asynchronously
|
||||
setTimeout(
|
||||
() => localStorage.setItem("game-records", JSON.stringify(stats)),
|
||||
0,
|
||||
);
|
||||
}
|
||||
|
||||
// The user can quit the game anytime so better save the lobby as soon as the
|
||||
// game starts.
|
||||
export function startGame(id: GameID, lobby: GameConfig) {
|
||||
if (typeof localStorage === "undefined") {
|
||||
return;
|
||||
}
|
||||
|
||||
_startTime = Date.now();
|
||||
const stats = getStats();
|
||||
stats[id] = { lobby };
|
||||
save(stats);
|
||||
}
|
||||
|
||||
export function startTime() {
|
||||
return _startTime;
|
||||
}
|
||||
|
||||
export function endGame(gameRecord: GameRecord) {
|
||||
if (typeof localStorage === "undefined") {
|
||||
return;
|
||||
}
|
||||
|
||||
const stats = getStats();
|
||||
const gameStat = stats[gameRecord.id];
|
||||
|
||||
if (!gameStat) {
|
||||
consolex.log("LocalPersistantStats: game not found");
|
||||
return;
|
||||
}
|
||||
|
||||
gameStat.gameRecord = gameRecord;
|
||||
save(stats);
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ class Client {
|
||||
"google-ad",
|
||||
) as NodeListOf<GoogleAdElement>;
|
||||
|
||||
window.addEventListener("beforeunload", (event) => {
|
||||
window.addEventListener("beforeunload", () => {
|
||||
consolex.log("Browser is closing");
|
||||
if (this.gameStop != null) {
|
||||
this.gameStop();
|
||||
@@ -213,7 +213,7 @@ class Client {
|
||||
);
|
||||
}
|
||||
|
||||
private async handleLeaveLobby(event: CustomEvent) {
|
||||
private async handleLeaveLobby(/* event: CustomEvent */) {
|
||||
if (this.gameStop == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { LitElement, html } from "lit";
|
||||
import { customElement, state } from "lit/decorators.js";
|
||||
import { translateText } from "../client/Utils";
|
||||
import { consolex } from "../core/Consolex";
|
||||
import { GameMode } from "../core/game/Game";
|
||||
import { GameID, GameInfo } from "../core/Schemas";
|
||||
import { generateID } from "../core/Util";
|
||||
import { JoinLobbyEvent } from "./Main";
|
||||
@@ -115,26 +116,26 @@ export class PublicLobby extends LitElement {
|
||||
style="border: 1px solid rgba(255, 255, 255, 0.5)"
|
||||
/>
|
||||
<div
|
||||
class="w-full flex flex-col md:flex-row items-center justify-center gap-4"
|
||||
class="w-full flex flex-col md:flex-row items-center justify-center md:justify-evenly"
|
||||
>
|
||||
<div class="flex flex-col items-start">
|
||||
<div class="text-md font-medium text-blue-100">
|
||||
<div class="flex flex-col items-center">
|
||||
<div class="text-md font-medium text-blue-100 mb-4">
|
||||
<!-- ${lobby.gameConfig.gameMap} -->
|
||||
${translateText(
|
||||
`map.${lobby.gameConfig.gameMap.toLowerCase().replace(/\s+/g, "")}`,
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col items-start">
|
||||
<div class="text-md font-medium text-blue-100">
|
||||
${lobby.numClients} / ${lobby.gameConfig.maxPlayers}
|
||||
${translateText("public_lobby.waiting")}
|
||||
${lobby.gameConfig.gameMode == GameMode.Team
|
||||
? translateText("game_mode.teams")
|
||||
: translateText("game_mode.ffa")}
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div
|
||||
class="min-w-20 text-sm font-medium px-2 py-1 bg-white/10 rounded-xl text-blue-100 text-center"
|
||||
>
|
||||
<div class="flex flex-col items-center">
|
||||
<div class="text-md font-medium text-blue-100 mb-2">
|
||||
${lobby.numClients} / ${lobby.gameConfig.maxPlayers}
|
||||
</div>
|
||||
<div class="text-md font-medium text-blue-100">
|
||||
${timeDisplay}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -158,8 +158,7 @@ export class Transport {
|
||||
private onmessage: (msg: ServerMessage) => void;
|
||||
|
||||
private pingInterval: number | null = null;
|
||||
private isLocal: boolean;
|
||||
|
||||
public readonly isLocal: boolean;
|
||||
constructor(
|
||||
private lobbyConfig: LobbyConfig,
|
||||
private eventBus: EventBus,
|
||||
@@ -267,7 +266,7 @@ export class Transport {
|
||||
onmessage: (message: ServerMessage) => void,
|
||||
) {
|
||||
this.startPing();
|
||||
this.maybeKillSocket();
|
||||
this.killExistingSocket();
|
||||
const wsHost = window.location.host;
|
||||
const wsProtocol = window.location.protocol === "https:" ? "wss:" : "ws:";
|
||||
const workerPath = this.lobbyConfig.serverConfig.workerPath(
|
||||
@@ -304,11 +303,15 @@ export class Transport {
|
||||
);
|
||||
if (event.code != 1000) {
|
||||
console.log(`reconnecting`);
|
||||
this.connect(onconnect, onmessage);
|
||||
this.reconnect();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public reconnect() {
|
||||
this.connect(this.onconnect, this.onmessage);
|
||||
}
|
||||
|
||||
private onSendLogEvent(event: SendLogEvent) {
|
||||
this.sendMsg(
|
||||
JSON.stringify(
|
||||
@@ -586,7 +589,7 @@ export class Transport {
|
||||
}
|
||||
}
|
||||
|
||||
private maybeKillSocket(): void {
|
||||
private killExistingSocket(): void {
|
||||
if (this.socket == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@ export const MapDescription: Record<keyof typeof GameMapType, string> = {
|
||||
Australia: "Australia",
|
||||
Iceland: "Iceland",
|
||||
Japan: "Japan",
|
||||
TwoSeas: "Between Two Seas",
|
||||
KnownWorld: "Known World",
|
||||
};
|
||||
|
||||
@customElement("map-display")
|
||||
|
||||
@@ -40,7 +40,6 @@ export function createRenderer(
|
||||
const startingModal = document.querySelector(
|
||||
"game-starting-modal",
|
||||
) as GameStartingModal;
|
||||
startingModal instanceof GameStartingModal;
|
||||
startingModal.hide();
|
||||
|
||||
// TODO maybe append this to dcoument instead of querying for them?
|
||||
|
||||
@@ -2,16 +2,17 @@ import { LitElement, css, html } from "lit";
|
||||
import { customElement, state } from "lit/decorators.js";
|
||||
|
||||
const emojiTable: string[][] = [
|
||||
["😀", "😱", "🤡", "😡", "🥺"],
|
||||
["😈", "👏", "🥉", "🥈", "🥇"],
|
||||
["🤙", "🥰", "😇", "😊", "🔥"],
|
||||
["💪", "🏳️", "💀", "😭", "🫡"],
|
||||
["🤦♂️", "👎", "👍", "🥱", "💔"],
|
||||
["😎", "❤️", "💰", "🤝", "🖕"],
|
||||
["💥", "🆘", "🕊️", "➡️", "⬅️"],
|
||||
["↙️", "↖️", "↗️", "⬆️", "↘️"],
|
||||
["⬇️", "❓", "⏳", "☢️", "⚠️"],
|
||||
["😭", "😞", "👋", "🐀", "❌"],
|
||||
["😀", "😊", "🥰", "😇", "😎"],
|
||||
["😞", "🥺", "😭", "😱", "😡"],
|
||||
["😈", "🤡", "🖕", "🥱", "🤦♂️"],
|
||||
["👋", "👏", "🤌", "💪", "🫡"],
|
||||
["👍", "👎", "❓", "🐔", "🐀"],
|
||||
["🤝", "🆘", "🕊️", "🏳️", "⏳"],
|
||||
["🔥", "💥", "💀", "☢️", "⚠️"],
|
||||
["↖️", "⬆️", "↗️", "👑", "🥇"],
|
||||
["⬅️", "🎯", "➡️", "🥈", "🥉"],
|
||||
["↙️", "⬇️", "↘️", "❤️", "💔"],
|
||||
["💰", "⚓", "⛵", "🏡", "🛡️"],
|
||||
];
|
||||
|
||||
@customElement("emoji-table")
|
||||
|
||||
@@ -61,6 +61,7 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
private events: Event[] = [];
|
||||
@state() private incomingAttacks: AttackUpdate[] = [];
|
||||
@state() private outgoingAttacks: AttackUpdate[] = [];
|
||||
@state() private outgoingLandAttacks: AttackUpdate[] = [];
|
||||
@state() private outgoingBoats: UnitView[] = [];
|
||||
@state() private _hidden: boolean = false;
|
||||
@state() private newEvents: number = 0;
|
||||
@@ -134,6 +135,10 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
.outgoingAttacks()
|
||||
.filter((a) => a.targetID != 0);
|
||||
|
||||
this.outgoingLandAttacks = myPlayer
|
||||
.outgoingAttacks()
|
||||
.filter((a) => a.targetID == 0);
|
||||
|
||||
this.outgoingBoats = myPlayer
|
||||
.units()
|
||||
.filter((u) => u.type() === UnitType.TransportShip);
|
||||
@@ -396,14 +401,7 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
: event.description;
|
||||
}
|
||||
|
||||
private renderAttacks() {
|
||||
if (
|
||||
this.incomingAttacks.length === 0 &&
|
||||
this.outgoingAttacks.length === 0
|
||||
) {
|
||||
return html``;
|
||||
}
|
||||
|
||||
private renderIncomingAttacks() {
|
||||
return html`
|
||||
${this.incomingAttacks.length > 0
|
||||
? html`
|
||||
@@ -431,6 +429,11 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
</tr>
|
||||
`
|
||||
: ""}
|
||||
`;
|
||||
}
|
||||
|
||||
private renderOutgoingAttacks() {
|
||||
return html`
|
||||
${this.outgoingAttacks.length > 0
|
||||
? html`
|
||||
<tr class="border-t border-gray-700">
|
||||
@@ -467,6 +470,37 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
`;
|
||||
}
|
||||
|
||||
private renderOutgoingLandAttacks() {
|
||||
return html`
|
||||
${this.outgoingLandAttacks.length > 0
|
||||
? html`
|
||||
<tr class="border-t border-gray-700">
|
||||
<td class="lg:p-3 p-1 text-left text-gray-400">
|
||||
${this.outgoingLandAttacks.map(
|
||||
(landAttack) => html`
|
||||
<button translate="no" class="ml-2">
|
||||
${renderTroops(landAttack.troops)} Wilderness
|
||||
</button>
|
||||
|
||||
${!landAttack.retreating
|
||||
? html`<button
|
||||
${landAttack.retreating ? "disabled" : ""}
|
||||
@click=${() => {
|
||||
this.emitCancelAttackIntent(landAttack.id);
|
||||
}}
|
||||
>
|
||||
❌
|
||||
</button>`
|
||||
: "(retreating...)"}
|
||||
`,
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
`
|
||||
: ""}
|
||||
`;
|
||||
}
|
||||
|
||||
private renderBoats() {
|
||||
if (this.outgoingBoats.length === 0) {
|
||||
return html``;
|
||||
@@ -497,14 +531,6 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
}
|
||||
|
||||
render() {
|
||||
if (
|
||||
this.events.length === 0 &&
|
||||
this.incomingAttacks.length === 0 &&
|
||||
this.outgoingAttacks.length === 0 &&
|
||||
this.outgoingBoats.length === 0
|
||||
) {
|
||||
return html``;
|
||||
}
|
||||
this.events.sort((a, b) => {
|
||||
const aPrior = a.priority ?? 100000;
|
||||
const bPrior = b.priority ?? 100000;
|
||||
@@ -602,7 +628,8 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
</tr>
|
||||
`,
|
||||
)}
|
||||
${this.renderAttacks()} ${this.renderBoats()}
|
||||
${this.renderIncomingAttacks()} ${this.renderOutgoingAttacks()}
|
||||
${this.renderOutgoingLandAttacks()} ${this.renderBoats()}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@@ -106,6 +106,11 @@ export class OptionsMenu extends LitElement implements Layer {
|
||||
this.eventBus.emit(new RefreshGraphicsEvent());
|
||||
}
|
||||
|
||||
private onToggleFocusLockedButtonClick() {
|
||||
this.userSettings.toggleFocusLocked();
|
||||
this.requestUpdate();
|
||||
}
|
||||
|
||||
private onToggleLeftClickOpensMenu() {
|
||||
this.userSettings.toggleLeftClickOpenMenu();
|
||||
}
|
||||
@@ -200,6 +205,15 @@ export class OptionsMenu extends LitElement implements Layer {
|
||||
? "Opens menu"
|
||||
: "Attack"),
|
||||
})}
|
||||
${button({
|
||||
onClick: this.onToggleFocusLockedButtonClick,
|
||||
title: "Lock Focus",
|
||||
children:
|
||||
"🗺: " +
|
||||
(this.userSettings.focusLocked()
|
||||
? "Focus locked"
|
||||
: "Hover focus"),
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@@ -1,34 +1,63 @@
|
||||
import { blue, red } from "../../../core/configuration/Colors";
|
||||
import { GameMode, TeamName } from "../../../core/game/Game";
|
||||
import { GameView } from "../../../core/game/GameView";
|
||||
import { TransformHandler } from "../TransformHandler";
|
||||
import { Layer } from "./Layer";
|
||||
|
||||
export class SpawnTimer implements Layer {
|
||||
private ratio = 0;
|
||||
private leftColor = "rgba(0, 128, 255, 0.7)";
|
||||
private rightColor = "rgba(0, 0, 0, 0.5)";
|
||||
|
||||
constructor(
|
||||
private game: GameView,
|
||||
private transformHandler: TransformHandler,
|
||||
) {}
|
||||
|
||||
init() {}
|
||||
tick() {}
|
||||
|
||||
tick() {
|
||||
if (this.game.inSpawnPhase()) {
|
||||
this.ratio = this.game.ticks() / this.game.config().numSpawnPhaseTurns();
|
||||
return;
|
||||
}
|
||||
if (this.game.config().gameConfig().gameMode != GameMode.Team) {
|
||||
this.ratio = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
const numBlueTiles = this.game
|
||||
.players()
|
||||
.filter((p) => p.teamName() == TeamName.Blue)
|
||||
.reduce((acc, p) => acc + p.numTilesOwned(), 0);
|
||||
|
||||
const numRedTiles = this.game
|
||||
.players()
|
||||
.filter((p) => p.teamName() == TeamName.Red)
|
||||
.reduce((acc, p) => acc + p.numTilesOwned(), 0);
|
||||
|
||||
this.ratio = numBlueTiles / (numBlueTiles + numRedTiles);
|
||||
this.leftColor = blue.toRgbString();
|
||||
this.rightColor = red.toRgbString();
|
||||
}
|
||||
|
||||
shouldTransform(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
renderLayer(context: CanvasRenderingContext2D) {
|
||||
if (!this.game.inSpawnPhase()) {
|
||||
if (this.ratio == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const barHeight = 15;
|
||||
const barHeight = 10;
|
||||
const barBackgroundWidth = this.transformHandler.width();
|
||||
|
||||
const ratio = this.game.ticks() / this.game.config().numSpawnPhaseTurns();
|
||||
|
||||
// Draw bar background
|
||||
context.fillStyle = "rgba(0, 0, 0, 0.5)";
|
||||
context.fillStyle = this.rightColor;
|
||||
context.fillRect(0, 0, barBackgroundWidth, barHeight);
|
||||
|
||||
context.fillStyle = "rgba(0, 128, 255, 0.7)";
|
||||
context.fillRect(0, 0, barBackgroundWidth * ratio, barHeight);
|
||||
context.fillStyle = this.leftColor;
|
||||
context.fillRect(0, 0, barBackgroundWidth * this.ratio, barHeight);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,7 +216,7 @@ export class StructureLayer implements Layer {
|
||||
|
||||
private handleUnitRendering(unit: UnitView) {
|
||||
const unitType = unit.constructionType() ?? unit.type();
|
||||
let iconType = unitType;
|
||||
const iconType = unitType;
|
||||
if (!this.isUnitTypeSupported(unitType)) return;
|
||||
|
||||
const config = this.unitConfigs[unitType];
|
||||
|
||||
@@ -12,11 +12,12 @@ import { Layer } from "./Layer";
|
||||
// Add this at the top of your file
|
||||
declare global {
|
||||
interface Window {
|
||||
adsbygoogle: any[];
|
||||
adsbygoogle: unknown[];
|
||||
}
|
||||
}
|
||||
|
||||
// Add this at the top of your file
|
||||
declare let adsbygoogle: any[];
|
||||
declare let adsbygoogle: unknown[];
|
||||
|
||||
@customElement("win-modal")
|
||||
export class WinModal extends LitElement implements Layer {
|
||||
@@ -257,7 +258,7 @@ export class WinModal extends LitElement implements Layer {
|
||||
});
|
||||
}
|
||||
|
||||
renderLayer(context: CanvasRenderingContext2D) {}
|
||||
renderLayer(/* context: CanvasRenderingContext2D */) {}
|
||||
|
||||
shouldTransform(): boolean {
|
||||
return false;
|
||||
|
||||
@@ -327,6 +327,11 @@ label.option-card:hover {
|
||||
center / cover;
|
||||
}
|
||||
|
||||
#helpModal .sam-launcher-icon {
|
||||
mask: url("../../resources/images/SamLauncherIconWhite.svg") no-repeat
|
||||
center / cover;
|
||||
}
|
||||
|
||||
#helpModal .atom-bomb-icon {
|
||||
mask: url("../../resources/images/NukeIconWhite.svg") no-repeat center / cover;
|
||||
}
|
||||
|
||||
@@ -7,12 +7,14 @@ import europe from "../../../resources/maps/EuropeThumb.webp";
|
||||
import gatewayToTheAtlantic from "../../../resources/maps/GatewayToTheAtlanticThumb.webp";
|
||||
import iceland from "../../../resources/maps/IcelandThumb.webp";
|
||||
import japan from "../../../resources/maps/JapanThumb.webp";
|
||||
import knownworld from "../../../resources/maps/KnownWorldThumb.webp";
|
||||
import mars from "../../../resources/maps/MarsThumb.webp";
|
||||
import mena from "../../../resources/maps/MenaThumb.webp";
|
||||
import northAmerica from "../../../resources/maps/NorthAmericaThumb.webp";
|
||||
import oceania from "../../../resources/maps/OceaniaThumb.webp";
|
||||
import pangaea from "../../../resources/maps/PangaeaThumb.webp";
|
||||
import southAmerica from "../../../resources/maps/SouthAmericaThumb.webp";
|
||||
import twoSeas from "../../../resources/maps/TwoSeasThumb.webp";
|
||||
import world from "../../../resources/maps/WorldMapThumb.webp";
|
||||
|
||||
import { GameMapType } from "../../core/game/Game";
|
||||
@@ -51,6 +53,10 @@ export function getMapsImage(map: GameMapType): string {
|
||||
return iceland;
|
||||
case GameMapType.Japan:
|
||||
return japan;
|
||||
case GameMapType.TwoSeas:
|
||||
return twoSeas;
|
||||
case GameMapType.KnownWorld:
|
||||
return knownworld;
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import {
|
||||
Difficulty,
|
||||
Game,
|
||||
GameMapType,
|
||||
GameMode,
|
||||
GameType,
|
||||
Gold,
|
||||
Player,
|
||||
@@ -58,15 +59,54 @@ export abstract class DefaultServerConfig implements ServerConfig {
|
||||
return 60 * 1000;
|
||||
}
|
||||
lobbyMaxPlayers(map: GameMapType): number {
|
||||
if (map == GameMapType.World) {
|
||||
return Math.random() < 0.3 ? 150 : 60;
|
||||
}
|
||||
// Maps with ~4 mil pixels
|
||||
if (
|
||||
[GameMapType.Mars, GameMapType.Africa, GameMapType.BlackSea].includes(map)
|
||||
[
|
||||
GameMapType.GatewayToTheAtlantic,
|
||||
GameMapType.SouthAmerica,
|
||||
GameMapType.NorthAmerica,
|
||||
GameMapType.Africa,
|
||||
GameMapType.Europe,
|
||||
].includes(map)
|
||||
) {
|
||||
return Math.random() < 0.3 ? 70 : 50;
|
||||
return Math.random() < 0.2 ? 150 : 70;
|
||||
}
|
||||
return Math.random() < 0.3 ? 60 : 40;
|
||||
// Maps with ~2.5 - ~3.5 mil pixels
|
||||
if (
|
||||
[
|
||||
GameMapType.Australia,
|
||||
GameMapType.Iceland,
|
||||
GameMapType.Britannia,
|
||||
GameMapType.Asia,
|
||||
].includes(map)
|
||||
) {
|
||||
return Math.random() < 0.2 ? 100 : 50;
|
||||
}
|
||||
// Maps with ~2 mil pixels
|
||||
if (
|
||||
[
|
||||
GameMapType.Mena,
|
||||
GameMapType.Mars,
|
||||
GameMapType.Oceania,
|
||||
GameMapType.Japan, // Japan at this level because its 2/3 water
|
||||
].includes(map)
|
||||
) {
|
||||
return Math.random() < 0.2 ? 70 : 40;
|
||||
}
|
||||
// Maps smaller than ~2 mil pixels
|
||||
if (
|
||||
[GameMapType.TwoSeas, GameMapType.BlackSea, GameMapType.Pangaea].includes(
|
||||
map,
|
||||
)
|
||||
) {
|
||||
return Math.random() < 0.2 ? 60 : 35;
|
||||
}
|
||||
// world belongs with the ~2 mils, but these amounts never made sense so I assume the insanity is intended.
|
||||
if (map == GameMapType.World) {
|
||||
return Math.random() < 0.2 ? 150 : 60;
|
||||
}
|
||||
// default return for non specified map
|
||||
return Math.random() < 0.2 ? 85 : 45;
|
||||
}
|
||||
workerIndex(gameID: GameID): number {
|
||||
return simpleHash(gameID) % this.numWorkers();
|
||||
@@ -337,6 +377,9 @@ export class DefaultConfig implements Config {
|
||||
return 600 * 10; // 10 minutes.
|
||||
}
|
||||
percentageTilesOwnedToWin(): number {
|
||||
if (this._gameConfig.gameMode == GameMode.Team) {
|
||||
return 95;
|
||||
}
|
||||
return 80;
|
||||
}
|
||||
boatMaxNumber(): number {
|
||||
|
||||
@@ -190,7 +190,11 @@ export class AttackExecution implements Execution {
|
||||
|
||||
tick(ticks: number) {
|
||||
if (this.attack.retreated()) {
|
||||
this.retreat(malusForRetreat);
|
||||
if (this.attack.target().isPlayer()) {
|
||||
this.retreat(malusForRetreat);
|
||||
} else {
|
||||
this.retreat();
|
||||
}
|
||||
this.active = false;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -60,6 +60,8 @@ export enum GameMapType {
|
||||
Australia = "Australia",
|
||||
Iceland = "Iceland",
|
||||
Japan = "Japan",
|
||||
TwoSeas = "Between Two Seas",
|
||||
KnownWorld = "Known World",
|
||||
}
|
||||
|
||||
export enum GameType {
|
||||
@@ -135,8 +137,8 @@ export class Cell {
|
||||
private strRepr: string;
|
||||
|
||||
constructor(
|
||||
public readonly x,
|
||||
public readonly y,
|
||||
public readonly x: number,
|
||||
public readonly y: number,
|
||||
) {
|
||||
this.strRepr = `Cell[${this.x},${this.y}]`;
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@ export class GameImpl implements Game {
|
||||
}
|
||||
|
||||
addUpdate(update: GameUpdate) {
|
||||
(this.updates[update.type] as any[]).push(update);
|
||||
(this.updates[update.type] as GameUpdate[]).push(update);
|
||||
}
|
||||
|
||||
nextUnitID(): number {
|
||||
@@ -383,7 +383,7 @@ export class GameImpl implements Game {
|
||||
}
|
||||
|
||||
playerByClientID(id: ClientID): Player | null {
|
||||
for (const [pID, player] of this._players) {
|
||||
for (const [, player] of this._players) {
|
||||
if (player.clientID() == id) {
|
||||
return player;
|
||||
}
|
||||
|
||||
@@ -32,6 +32,9 @@ import {
|
||||
} from "./GameUpdates";
|
||||
import { TerraNulliusImpl } from "./TerraNulliusImpl";
|
||||
import { UnitGrid } from "./UnitGrid";
|
||||
import { UserSettings } from "./UserSettings";
|
||||
|
||||
const userSettings: UserSettings = new UserSettings();
|
||||
|
||||
export class UnitView {
|
||||
public _wasUpdated = true;
|
||||
@@ -384,6 +387,10 @@ export class GameView implements GameMap {
|
||||
throw Error(`player id ${id} not found`);
|
||||
}
|
||||
|
||||
players(): PlayerView[] {
|
||||
return Array.from(this._players.values());
|
||||
}
|
||||
|
||||
playerBySmallID(id: number): PlayerView | TerraNullius {
|
||||
if (id == 0) {
|
||||
return new TerraNulliusImpl();
|
||||
@@ -542,6 +549,7 @@ export class GameView implements GameMap {
|
||||
}
|
||||
|
||||
focusedPlayer(): PlayerView | null {
|
||||
if (userSettings.focusLocked()) return this.myPlayer();
|
||||
return this._focusedPlayer;
|
||||
}
|
||||
setFocusedPlayer(player: PlayerView | null): void {
|
||||
|
||||
@@ -92,6 +92,7 @@ export class PlayerImpl implements Player {
|
||||
|
||||
public _incomingAttacks: Attack[] = [];
|
||||
public _outgoingAttacks: Attack[] = [];
|
||||
public _outgoingLandAttacks: Attack[] = [];
|
||||
|
||||
constructor(
|
||||
private mg: GameImpl,
|
||||
@@ -1003,7 +1004,7 @@ export class PlayerImpl implements Player {
|
||||
// It's a probability list, so if an element appears twice it's because it's
|
||||
// twice more likely to be picked later.
|
||||
tradingPorts(port: Unit): Unit[] {
|
||||
let ports = this.mg
|
||||
const ports = this.mg
|
||||
.players()
|
||||
.filter((p) => p != port.owner() && p.canTrade(port.owner()))
|
||||
.flatMap((p) => p.units(UnitType.Port))
|
||||
|
||||
@@ -39,6 +39,8 @@ const MAP_FILE_NAMES: Record<GameMapType, string> = {
|
||||
[GameMapType.Australia]: "Australia",
|
||||
[GameMapType.Iceland]: "Iceland",
|
||||
[GameMapType.Japan]: "Japan",
|
||||
[GameMapType.TwoSeas]: "TwoSeas",
|
||||
[GameMapType.KnownWorld]: "KnownWorld",
|
||||
};
|
||||
|
||||
class GameMapLoader {
|
||||
|
||||
@@ -24,10 +24,18 @@ export class UserSettings {
|
||||
return this.get("settings.leftClickOpensMenu", false);
|
||||
}
|
||||
|
||||
focusLocked() {
|
||||
return this.get("settings.focusLocked", false);
|
||||
}
|
||||
|
||||
toggleLeftClickOpenMenu() {
|
||||
this.set("settings.leftClickOpensMenu", !this.leftClickOpensMenu());
|
||||
}
|
||||
|
||||
toggleFocusLocked() {
|
||||
this.set("settings.focusLocked", !this.focusLocked());
|
||||
}
|
||||
|
||||
toggleEmojis() {
|
||||
this.set("settings.emojis", !this.emojis());
|
||||
}
|
||||
|
||||
@@ -32,7 +32,3 @@ declare module "*.html" {
|
||||
const content: string;
|
||||
export default content;
|
||||
}
|
||||
declare module "*.json" {
|
||||
const value: any;
|
||||
export default value;
|
||||
}
|
||||
|
||||
@@ -120,19 +120,49 @@ function processShore(map: Terrain[][]): Coord[] {
|
||||
}
|
||||
|
||||
function processDistToLand(shorelineWaters: Coord[], map: Terrain[][]) {
|
||||
console.log("Setting Water tiles magnitude = distance from land");
|
||||
for (let x = 0; x < map.length; x++) {
|
||||
for (let y = 0; y < map[0].length; y++) {
|
||||
const tile = map[x][y];
|
||||
if (tile.type == TerrainType.Water) {
|
||||
if (shorelineWaters.some((coord) => coord.x == x && coord.y == y)) {
|
||||
tile.magnitude = 0;
|
||||
} else {
|
||||
const dist = shorelineWaters.map(
|
||||
(coord) => Math.abs(x - coord.x) + Math.abs(y - coord.y),
|
||||
);
|
||||
tile.magnitude = Math.min(...dist);
|
||||
}
|
||||
console.log(
|
||||
"Setting Water tiles magnitude = Manhattan distance from nearest land",
|
||||
);
|
||||
|
||||
const width = map.length;
|
||||
const height = map[0].length;
|
||||
|
||||
const visited = Array.from({ length: width }, () =>
|
||||
Array(height).fill(false),
|
||||
);
|
||||
const queue: { x: number; y: number; dist: number }[] = [];
|
||||
|
||||
for (const { x, y } of shorelineWaters) {
|
||||
queue.push({ x, y, dist: 0 });
|
||||
visited[x][y] = true;
|
||||
map[x][y].magnitude = 0;
|
||||
}
|
||||
|
||||
const directions = [
|
||||
{ dx: 0, dy: 1 },
|
||||
{ dx: 1, dy: 0 },
|
||||
{ dx: 0, dy: -1 },
|
||||
{ dx: -1, dy: 0 },
|
||||
];
|
||||
|
||||
while (queue.length > 0) {
|
||||
const { x, y, dist } = queue.shift()!;
|
||||
|
||||
for (const { dx, dy } of directions) {
|
||||
const nx = x + dx;
|
||||
const ny = y + dy;
|
||||
|
||||
if (
|
||||
nx >= 0 &&
|
||||
ny >= 0 &&
|
||||
nx < width &&
|
||||
ny < height &&
|
||||
!visited[nx][ny] &&
|
||||
map[nx][ny].type === TerrainType.Water
|
||||
) {
|
||||
visited[nx][ny] = true;
|
||||
map[nx][ny].magnitude = dist + 1;
|
||||
queue.push({ x: nx, y: ny, dist: dist + 1 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,9 @@ const maps = [
|
||||
"Australia",
|
||||
"Pangaea",
|
||||
"Iceland",
|
||||
"TwoSeas",
|
||||
"Japan",
|
||||
"KnownWorld",
|
||||
];
|
||||
|
||||
const removeSmall = true;
|
||||
|
||||
@@ -456,7 +456,7 @@ export class GameServer {
|
||||
|
||||
const lastHashTurn = this.turns.length - 10;
|
||||
|
||||
let { mostCommonHash, outOfSyncClients } =
|
||||
const { mostCommonHash, outOfSyncClients } =
|
||||
this.findOutOfSyncClients(lastHashTurn);
|
||||
|
||||
if (outOfSyncClients.length == 0) {
|
||||
@@ -464,11 +464,6 @@ export class GameServer {
|
||||
return;
|
||||
}
|
||||
|
||||
if (outOfSyncClients.length >= Math.floor(this.activeClients.length / 2)) {
|
||||
// If half clients out of sync assume all are out of sync.
|
||||
outOfSyncClients = this.activeClients;
|
||||
}
|
||||
|
||||
const serverDesync = ServerDesyncSchema.safeParse({
|
||||
type: "desync",
|
||||
turn: lastHashTurn,
|
||||
@@ -519,7 +514,7 @@ export class GameServer {
|
||||
}
|
||||
|
||||
// Create a list of clients whose hash doesn't match the most common one
|
||||
const outOfSyncClients: Client[] = [];
|
||||
let outOfSyncClients: Client[] = [];
|
||||
|
||||
for (const client of this.activeClients) {
|
||||
if (client.hashes.has(turnNumber)) {
|
||||
@@ -530,6 +525,11 @@ export class GameServer {
|
||||
}
|
||||
}
|
||||
|
||||
// If half clients out of sync assume all are out of sync.
|
||||
if (outOfSyncClients.length >= Math.floor(this.activeClients.length / 2)) {
|
||||
outOfSyncClients = this.activeClients;
|
||||
}
|
||||
|
||||
return {
|
||||
mostCommonHash,
|
||||
outOfSyncClients,
|
||||
|
||||
@@ -16,7 +16,7 @@ export interface Gatekeeper {
|
||||
// The wrapper for request handlers with optional rate limiting
|
||||
httpHandler: (
|
||||
limiterType: LimiterType,
|
||||
fn: (req: Request, res: Response, next: NextFunction) => Promise<any>,
|
||||
fn: (req: Request, res: Response, next: NextFunction) => Promise<unknown>,
|
||||
) => (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
||||
|
||||
// The wrapper for WebSocket message handlers with rate limiting
|
||||
@@ -67,8 +67,8 @@ async function getGatekeeper(): Promise<Gatekeeper> {
|
||||
// Use dynamic import for ES modules
|
||||
// Using a type assertion to avoid TypeScript errors for optional modules
|
||||
const module = await import(
|
||||
"./gatekeeper/RealGatekeeper.js" as any
|
||||
).catch(() => import("./gatekeeper/RealGatekeeper.js" as any));
|
||||
"./gatekeeper/RealGatekeeper.js" as string
|
||||
).catch(() => import("./gatekeeper/RealGatekeeper.js" as string));
|
||||
|
||||
if (!module || !module.RealGatekeeper) {
|
||||
console.log(
|
||||
@@ -95,7 +95,7 @@ export class GatekeeperWrapper implements Gatekeeper {
|
||||
|
||||
httpHandler(
|
||||
limiterType: LimiterType,
|
||||
fn: (req: Request, res: Response, next: NextFunction) => Promise<any>,
|
||||
fn: (req: Request, res: Response, next: NextFunction) => Promise<unknown>,
|
||||
) {
|
||||
return async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
@@ -129,7 +129,7 @@ export class NoOpGatekeeper implements Gatekeeper {
|
||||
// Simple pass-through with no rate limiting
|
||||
httpHandler(
|
||||
limiterType: LimiterType,
|
||||
fn: (req: Request, res: Response, next: NextFunction) => Promise<any>,
|
||||
fn: (req: Request, res: Response, next: NextFunction) => Promise<unknown>,
|
||||
) {
|
||||
return async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
|
||||
@@ -5,7 +5,7 @@ import http from "http";
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
import { getServerConfigFromServer } from "../core/configuration/ConfigLoader";
|
||||
import { Difficulty, GameMapType, GameType } from "../core/game/Game";
|
||||
import { Difficulty, GameMapType, GameMode, GameType } from "../core/game/Game";
|
||||
import { PseudoRandom } from "../core/PseudoRandom";
|
||||
import { GameConfig, GameInfo } from "../core/Schemas";
|
||||
import { generateID } from "../core/Util";
|
||||
@@ -237,6 +237,7 @@ async function schedulePublicGame() {
|
||||
instantBuild: false,
|
||||
disableNPCs: false,
|
||||
disableNukes: false,
|
||||
gameMode: Math.random() < 0.7 ? GameMode.FFA : GameMode.Team,
|
||||
bots: 400,
|
||||
} as GameConfig;
|
||||
|
||||
@@ -280,20 +281,22 @@ function getNextMap(): GameMapType {
|
||||
}
|
||||
|
||||
const frequency = {
|
||||
World: 2,
|
||||
World: 1,
|
||||
Europe: 3,
|
||||
Mena: 2,
|
||||
NorthAmerica: 3,
|
||||
BlackSea: 2,
|
||||
Pangaea: 2,
|
||||
NorthAmerica: 2,
|
||||
BlackSea: 1,
|
||||
Pangaea: 1,
|
||||
Africa: 2,
|
||||
Asia: 1,
|
||||
Mars: 1,
|
||||
Britannia: 2,
|
||||
GatewayToTheAtlantic: 3,
|
||||
GatewayToTheAtlantic: 2,
|
||||
Australia: 2,
|
||||
Iceland: 2,
|
||||
SouthAmerica: 3,
|
||||
Japan: 3,
|
||||
TwoSeas: 3,
|
||||
};
|
||||
|
||||
Object.keys(GameMapType).forEach((key) => {
|
||||
|
||||
@@ -50,7 +50,7 @@ export function setupMetricsServer() {
|
||||
} else if (line.trim() && !line.startsWith("#")) {
|
||||
// Add worker label to each metric line and collect for later
|
||||
const processedLine = line.replace(
|
||||
/^([a-z][a-z0-9_]*)(?:{([^}]*)})?(\s+[0-9\.e+-]+.*)/,
|
||||
/^([a-z][a-z0-9_]*)(?:{([^}]*)})?(\s+[0-9.e+-]+.*)/,
|
||||
(match, metricName, existingLabels, valueAndRest) => {
|
||||
if (existingLabels) {
|
||||
return `${metricName}{${existingLabels},worker="master"}${valueAndRest}`;
|
||||
@@ -108,7 +108,7 @@ export function setupMetricsServer() {
|
||||
// Process and collect actual metric values
|
||||
try {
|
||||
const processedLine = line.replace(
|
||||
/^([a-z][a-z0-9_]*)(?:{([^}]*)})?(\s+[0-9\.e+-]+.*)/,
|
||||
/^([a-z][a-z0-9_]*)(?:{([^}]*)})?(\s+[0-9.e+-]+.*)/,
|
||||
(match, metricName, existingLabels, valueAndRest) => {
|
||||
if (existingLabels) {
|
||||
return `${metricName}{${existingLabels},worker="worker-${i}"}${valueAndRest}`;
|
||||
@@ -122,7 +122,7 @@ export function setupMetricsServer() {
|
||||
if (processedLine !== line) {
|
||||
allMetricValues.push(processedLine);
|
||||
} else if (
|
||||
line.match(/^[a-z][a-z0-9_]*(?:{[^}]*})?\s+[0-9\.e+-]+.*/)
|
||||
line.match(/^[a-z][a-z0-9_]*(?:{[^}]*})?\s+[0-9.e+-]+.*/)
|
||||
) {
|
||||
// This looks like a metric line but didn't match our regex, try a more general approach
|
||||
const parts = line.split(/({|\s+)/);
|
||||
|
||||
@@ -3,7 +3,13 @@ import { ClientID, GameID, LogSeverity } from "../core/Schemas";
|
||||
export interface slogMsg {
|
||||
logKey: string;
|
||||
msg: string;
|
||||
data?: any;
|
||||
data?: {
|
||||
stack?: unknown;
|
||||
clientID?: unknown;
|
||||
clientIP?: unknown;
|
||||
gameID?: unknown;
|
||||
isRejoin?: unknown;
|
||||
};
|
||||
severity?: LogSeverity;
|
||||
gameID?: GameID;
|
||||
clientID?: ClientID;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"esModuleInterop": true,
|
||||
"experimentalDecorators": true,
|
||||
"resolveJsonModule": true,
|
||||
"useDefineForClassFields": false
|
||||
},
|
||||
"include": [
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import CopyPlugin from "copy-webpack-plugin";
|
||||
import ESLintPlugin from "eslint-webpack-plugin";
|
||||
import HtmlWebpackPlugin from "html-webpack-plugin";
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
@@ -129,6 +130,9 @@ export default async (env, argv) => {
|
||||
],
|
||||
options: { concurrency: 100 },
|
||||
}),
|
||||
new ESLintPlugin({
|
||||
context: __dirname,
|
||||
}),
|
||||
],
|
||||
optimization: {
|
||||
// Add optimization configuration for better caching
|
||||
|
||||