Compare commits
No commits in common. "dev" and "main" have entirely different histories.
11
.gitignore
vendored
|
|
@ -1,14 +1,3 @@
|
||||||
node_modules/
|
|
||||||
dist/
|
|
||||||
/common/cjs/
|
|
||||||
/common/esm/
|
|
||||||
.vscode/
|
|
||||||
.DS_Store
|
|
||||||
*.toml
|
|
||||||
!*.template.toml
|
|
||||||
/web-*
|
|
||||||
!/web-svelte
|
|
||||||
|
|
||||||
# Logs
|
# Logs
|
||||||
logs
|
logs
|
||||||
*.log
|
*.log
|
||||||
|
|
|
||||||
18
README.md
|
|
@ -1,17 +1 @@
|
||||||
# Gravwell-Online
|
# Gravwell-Online
|
||||||
|
|
||||||
## Development:
|
|
||||||
Below are the steps required to run the code in development mode:
|
|
||||||
|
|
||||||
1. Clone the git repository
|
|
||||||
2. Go into the common code module: `cd common`
|
|
||||||
3. Build the code for commonjs and ES module distribution with: `make`
|
|
||||||
4. In a new terminal: `cd web-svelte`
|
|
||||||
5. Install the required dependencies: `pnpm install`
|
|
||||||
- If the `common` module fails to import, link it with `pnpm link ../common/esm`
|
|
||||||
6. Run Vite: `pnpm dev`
|
|
||||||
7. In a new terminal: `cd server`
|
|
||||||
8. Install the required dependencies: `pnpm install`
|
|
||||||
- If the `common` modules fails to import, link it with `pnpm link ../common/cjs`
|
|
||||||
9. Compile the server code with `tsc`
|
|
||||||
10. Run the server code with `pnpm start`
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
.PHONY: all esm cjs test watch watch-esm watch-cjs
|
|
||||||
|
|
||||||
ESM_LOCATION=./esm
|
|
||||||
CJS_LOCATION=./cjs
|
|
||||||
|
|
||||||
all: esm cjs
|
|
||||||
|
|
||||||
esm:
|
|
||||||
@mkdir $(ESM_LOCATION) --parents
|
|
||||||
tsc --module es6 --outDir $(ESM_LOCATION)
|
|
||||||
cp ./package.json $(ESM_LOCATION)/package.json
|
|
||||||
|
|
||||||
cjs:
|
|
||||||
@mkdir $(CJS_LOCATION) --parents
|
|
||||||
tsc --module commonjs --outDir $(CJS_LOCATION)
|
|
||||||
cp ./package.json $(CJS_LOCATION)/package.json
|
|
||||||
|
|
||||||
watch:
|
|
||||||
@echo To have Typescript auto-rebuild, run the following commands in new terminals
|
|
||||||
@echo "\tmake watch-esm"
|
|
||||||
@echo "\tmake watch-cjs"
|
|
||||||
@echo These processes will not terminate, which is why they cannot be run in the same rule
|
|
||||||
|
|
||||||
watch-esm: esm
|
|
||||||
tsc --module es6 --outDir $(ESM_LOCATION) --watch
|
|
||||||
|
|
||||||
watch-cjs: cjs
|
|
||||||
tsc --module commonjs --outDir $(CJS_LOCATION) --watch
|
|
||||||
|
|
||||||
test:
|
|
||||||
node_modules/mocha/bin/_mocha -r ts-node/register src/**/*.spec.ts
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
{
|
|
||||||
"name": "common",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "",
|
|
||||||
"module": "index.js",
|
|
||||||
"main": "index.js",
|
|
||||||
"scripts": {
|
|
||||||
"test": "echo \"To run the tests use: make test\" && exit 1"
|
|
||||||
},
|
|
||||||
"author": "Oliver Akins",
|
|
||||||
"license": "UNLICENSED",
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/chai": "^4.3.1",
|
|
||||||
"@types/mocha": "^9.1.1",
|
|
||||||
"@types/node": "^18.0.6",
|
|
||||||
"chai": "^4.3.6",
|
|
||||||
"mocha": "^10.0.0",
|
|
||||||
"ts-node": "^10.9.1",
|
|
||||||
"typescript": "^4.7.4"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
705
common/pnpm-lock.yaml
generated
|
|
@ -1,705 +0,0 @@
|
||||||
lockfileVersion: 5.4
|
|
||||||
|
|
||||||
specifiers:
|
|
||||||
'@types/chai': ^4.3.1
|
|
||||||
'@types/mocha': ^9.1.1
|
|
||||||
'@types/node': ^18.0.6
|
|
||||||
chai: ^4.3.6
|
|
||||||
mocha: ^10.0.0
|
|
||||||
ts-node: ^10.9.1
|
|
||||||
typescript: ^4.7.4
|
|
||||||
|
|
||||||
devDependencies:
|
|
||||||
'@types/chai': 4.3.1
|
|
||||||
'@types/mocha': 9.1.1
|
|
||||||
'@types/node': 18.0.6
|
|
||||||
chai: 4.3.6
|
|
||||||
mocha: 10.0.0
|
|
||||||
ts-node: 10.9.1_tdn3ypgnfy6bmey2q4hu5jonwi
|
|
||||||
typescript: 4.7.4
|
|
||||||
|
|
||||||
packages:
|
|
||||||
|
|
||||||
/@cspotcode/source-map-support/0.8.1:
|
|
||||||
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
|
|
||||||
engines: {node: '>=12'}
|
|
||||||
dependencies:
|
|
||||||
'@jridgewell/trace-mapping': 0.3.9
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@jridgewell/resolve-uri/3.1.0:
|
|
||||||
resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==}
|
|
||||||
engines: {node: '>=6.0.0'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@jridgewell/sourcemap-codec/1.4.14:
|
|
||||||
resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@jridgewell/trace-mapping/0.3.9:
|
|
||||||
resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==}
|
|
||||||
dependencies:
|
|
||||||
'@jridgewell/resolve-uri': 3.1.0
|
|
||||||
'@jridgewell/sourcemap-codec': 1.4.14
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@tsconfig/node10/1.0.9:
|
|
||||||
resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@tsconfig/node12/1.0.11:
|
|
||||||
resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@tsconfig/node14/1.0.3:
|
|
||||||
resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@tsconfig/node16/1.0.3:
|
|
||||||
resolution: {integrity: sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@types/chai/4.3.1:
|
|
||||||
resolution: {integrity: sha512-/zPMqDkzSZ8t3VtxOa4KPq7uzzW978M9Tvh+j7GHKuo6k6GTLxPJ4J5gE5cjfJ26pnXst0N5Hax8Sr0T2Mi9zQ==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@types/mocha/9.1.1:
|
|
||||||
resolution: {integrity: sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@types/node/18.0.6:
|
|
||||||
resolution: {integrity: sha512-/xUq6H2aQm261exT6iZTMifUySEt4GR5KX8eYyY+C4MSNPqSh9oNIP7tz2GLKTlFaiBbgZNxffoR3CVRG+cljw==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@ungap/promise-all-settled/1.1.2:
|
|
||||||
resolution: {integrity: sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/acorn-walk/8.2.0:
|
|
||||||
resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==}
|
|
||||||
engines: {node: '>=0.4.0'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/acorn/8.7.1:
|
|
||||||
resolution: {integrity: sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==}
|
|
||||||
engines: {node: '>=0.4.0'}
|
|
||||||
hasBin: true
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/ansi-colors/4.1.1:
|
|
||||||
resolution: {integrity: sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==}
|
|
||||||
engines: {node: '>=6'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/ansi-regex/5.0.1:
|
|
||||||
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/ansi-styles/4.3.0:
|
|
||||||
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
dependencies:
|
|
||||||
color-convert: 2.0.1
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/anymatch/3.1.2:
|
|
||||||
resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==}
|
|
||||||
engines: {node: '>= 8'}
|
|
||||||
dependencies:
|
|
||||||
normalize-path: 3.0.0
|
|
||||||
picomatch: 2.3.1
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/arg/4.1.3:
|
|
||||||
resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/argparse/2.0.1:
|
|
||||||
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/assertion-error/1.1.0:
|
|
||||||
resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/balanced-match/1.0.2:
|
|
||||||
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/binary-extensions/2.2.0:
|
|
||||||
resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/brace-expansion/1.1.11:
|
|
||||||
resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
|
|
||||||
dependencies:
|
|
||||||
balanced-match: 1.0.2
|
|
||||||
concat-map: 0.0.1
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/brace-expansion/2.0.1:
|
|
||||||
resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
|
|
||||||
dependencies:
|
|
||||||
balanced-match: 1.0.2
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/braces/3.0.2:
|
|
||||||
resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
dependencies:
|
|
||||||
fill-range: 7.0.1
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/browser-stdout/1.3.1:
|
|
||||||
resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/camelcase/6.3.0:
|
|
||||||
resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/chai/4.3.6:
|
|
||||||
resolution: {integrity: sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==}
|
|
||||||
engines: {node: '>=4'}
|
|
||||||
dependencies:
|
|
||||||
assertion-error: 1.1.0
|
|
||||||
check-error: 1.0.2
|
|
||||||
deep-eql: 3.0.1
|
|
||||||
get-func-name: 2.0.0
|
|
||||||
loupe: 2.3.4
|
|
||||||
pathval: 1.1.1
|
|
||||||
type-detect: 4.0.8
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/chalk/4.1.2:
|
|
||||||
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dependencies:
|
|
||||||
ansi-styles: 4.3.0
|
|
||||||
supports-color: 7.2.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/check-error/1.0.2:
|
|
||||||
resolution: {integrity: sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/chokidar/3.5.3:
|
|
||||||
resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
|
|
||||||
engines: {node: '>= 8.10.0'}
|
|
||||||
dependencies:
|
|
||||||
anymatch: 3.1.2
|
|
||||||
braces: 3.0.2
|
|
||||||
glob-parent: 5.1.2
|
|
||||||
is-binary-path: 2.1.0
|
|
||||||
is-glob: 4.0.3
|
|
||||||
normalize-path: 3.0.0
|
|
||||||
readdirp: 3.6.0
|
|
||||||
optionalDependencies:
|
|
||||||
fsevents: 2.3.2
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/cliui/7.0.4:
|
|
||||||
resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==}
|
|
||||||
dependencies:
|
|
||||||
string-width: 4.2.3
|
|
||||||
strip-ansi: 6.0.1
|
|
||||||
wrap-ansi: 7.0.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/color-convert/2.0.1:
|
|
||||||
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
|
|
||||||
engines: {node: '>=7.0.0'}
|
|
||||||
dependencies:
|
|
||||||
color-name: 1.1.4
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/color-name/1.1.4:
|
|
||||||
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/concat-map/0.0.1:
|
|
||||||
resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/create-require/1.1.1:
|
|
||||||
resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/debug/4.3.4_supports-color@8.1.1:
|
|
||||||
resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
|
|
||||||
engines: {node: '>=6.0'}
|
|
||||||
peerDependencies:
|
|
||||||
supports-color: '*'
|
|
||||||
peerDependenciesMeta:
|
|
||||||
supports-color:
|
|
||||||
optional: true
|
|
||||||
dependencies:
|
|
||||||
ms: 2.1.2
|
|
||||||
supports-color: 8.1.1
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/decamelize/4.0.0:
|
|
||||||
resolution: {integrity: sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/deep-eql/3.0.1:
|
|
||||||
resolution: {integrity: sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==}
|
|
||||||
engines: {node: '>=0.12'}
|
|
||||||
dependencies:
|
|
||||||
type-detect: 4.0.8
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/diff/4.0.2:
|
|
||||||
resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==}
|
|
||||||
engines: {node: '>=0.3.1'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/diff/5.0.0:
|
|
||||||
resolution: {integrity: sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==}
|
|
||||||
engines: {node: '>=0.3.1'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/emoji-regex/8.0.0:
|
|
||||||
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/escalade/3.1.1:
|
|
||||||
resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==}
|
|
||||||
engines: {node: '>=6'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/escape-string-regexp/4.0.0:
|
|
||||||
resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/fill-range/7.0.1:
|
|
||||||
resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
dependencies:
|
|
||||||
to-regex-range: 5.0.1
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/find-up/5.0.0:
|
|
||||||
resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dependencies:
|
|
||||||
locate-path: 6.0.0
|
|
||||||
path-exists: 4.0.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/flat/5.0.2:
|
|
||||||
resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==}
|
|
||||||
hasBin: true
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/fs.realpath/1.0.0:
|
|
||||||
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/fsevents/2.3.2:
|
|
||||||
resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
|
|
||||||
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
|
|
||||||
os: [darwin]
|
|
||||||
requiresBuild: true
|
|
||||||
dev: true
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
/get-caller-file/2.0.5:
|
|
||||||
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
|
|
||||||
engines: {node: 6.* || 8.* || >= 10.*}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/get-func-name/2.0.0:
|
|
||||||
resolution: {integrity: sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/glob-parent/5.1.2:
|
|
||||||
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
|
|
||||||
engines: {node: '>= 6'}
|
|
||||||
dependencies:
|
|
||||||
is-glob: 4.0.3
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/glob/7.2.0:
|
|
||||||
resolution: {integrity: sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==}
|
|
||||||
dependencies:
|
|
||||||
fs.realpath: 1.0.0
|
|
||||||
inflight: 1.0.6
|
|
||||||
inherits: 2.0.4
|
|
||||||
minimatch: 3.1.2
|
|
||||||
once: 1.4.0
|
|
||||||
path-is-absolute: 1.0.1
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/has-flag/4.0.0:
|
|
||||||
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/he/1.2.0:
|
|
||||||
resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==}
|
|
||||||
hasBin: true
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/inflight/1.0.6:
|
|
||||||
resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
|
|
||||||
dependencies:
|
|
||||||
once: 1.4.0
|
|
||||||
wrappy: 1.0.2
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/inherits/2.0.4:
|
|
||||||
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/is-binary-path/2.1.0:
|
|
||||||
resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
dependencies:
|
|
||||||
binary-extensions: 2.2.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/is-extglob/2.1.1:
|
|
||||||
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
|
|
||||||
engines: {node: '>=0.10.0'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/is-fullwidth-code-point/3.0.0:
|
|
||||||
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/is-glob/4.0.3:
|
|
||||||
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
|
|
||||||
engines: {node: '>=0.10.0'}
|
|
||||||
dependencies:
|
|
||||||
is-extglob: 2.1.1
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/is-number/7.0.0:
|
|
||||||
resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
|
|
||||||
engines: {node: '>=0.12.0'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/is-plain-obj/2.1.0:
|
|
||||||
resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/is-unicode-supported/0.1.0:
|
|
||||||
resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/js-yaml/4.1.0:
|
|
||||||
resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
|
|
||||||
hasBin: true
|
|
||||||
dependencies:
|
|
||||||
argparse: 2.0.1
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/locate-path/6.0.0:
|
|
||||||
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dependencies:
|
|
||||||
p-locate: 5.0.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/log-symbols/4.1.0:
|
|
||||||
resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dependencies:
|
|
||||||
chalk: 4.1.2
|
|
||||||
is-unicode-supported: 0.1.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/loupe/2.3.4:
|
|
||||||
resolution: {integrity: sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==}
|
|
||||||
dependencies:
|
|
||||||
get-func-name: 2.0.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/make-error/1.3.6:
|
|
||||||
resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/minimatch/3.1.2:
|
|
||||||
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
|
|
||||||
dependencies:
|
|
||||||
brace-expansion: 1.1.11
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/minimatch/5.0.1:
|
|
||||||
resolution: {integrity: sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dependencies:
|
|
||||||
brace-expansion: 2.0.1
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/mocha/10.0.0:
|
|
||||||
resolution: {integrity: sha512-0Wl+elVUD43Y0BqPZBzZt8Tnkw9CMUdNYnUsTfOM1vuhJVZL+kiesFYsqwBkEEuEixaiPe5ZQdqDgX2jddhmoA==}
|
|
||||||
engines: {node: '>= 14.0.0'}
|
|
||||||
hasBin: true
|
|
||||||
dependencies:
|
|
||||||
'@ungap/promise-all-settled': 1.1.2
|
|
||||||
ansi-colors: 4.1.1
|
|
||||||
browser-stdout: 1.3.1
|
|
||||||
chokidar: 3.5.3
|
|
||||||
debug: 4.3.4_supports-color@8.1.1
|
|
||||||
diff: 5.0.0
|
|
||||||
escape-string-regexp: 4.0.0
|
|
||||||
find-up: 5.0.0
|
|
||||||
glob: 7.2.0
|
|
||||||
he: 1.2.0
|
|
||||||
js-yaml: 4.1.0
|
|
||||||
log-symbols: 4.1.0
|
|
||||||
minimatch: 5.0.1
|
|
||||||
ms: 2.1.3
|
|
||||||
nanoid: 3.3.3
|
|
||||||
serialize-javascript: 6.0.0
|
|
||||||
strip-json-comments: 3.1.1
|
|
||||||
supports-color: 8.1.1
|
|
||||||
workerpool: 6.2.1
|
|
||||||
yargs: 16.2.0
|
|
||||||
yargs-parser: 20.2.4
|
|
||||||
yargs-unparser: 2.0.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/ms/2.1.2:
|
|
||||||
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/ms/2.1.3:
|
|
||||||
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/nanoid/3.3.3:
|
|
||||||
resolution: {integrity: sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==}
|
|
||||||
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
|
|
||||||
hasBin: true
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/normalize-path/3.0.0:
|
|
||||||
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
|
|
||||||
engines: {node: '>=0.10.0'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/once/1.4.0:
|
|
||||||
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
|
|
||||||
dependencies:
|
|
||||||
wrappy: 1.0.2
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/p-limit/3.1.0:
|
|
||||||
resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dependencies:
|
|
||||||
yocto-queue: 0.1.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/p-locate/5.0.0:
|
|
||||||
resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dependencies:
|
|
||||||
p-limit: 3.1.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/path-exists/4.0.0:
|
|
||||||
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/path-is-absolute/1.0.1:
|
|
||||||
resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
|
|
||||||
engines: {node: '>=0.10.0'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/pathval/1.1.1:
|
|
||||||
resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/picomatch/2.3.1:
|
|
||||||
resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
|
|
||||||
engines: {node: '>=8.6'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/randombytes/2.1.0:
|
|
||||||
resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==}
|
|
||||||
dependencies:
|
|
||||||
safe-buffer: 5.2.1
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/readdirp/3.6.0:
|
|
||||||
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
|
|
||||||
engines: {node: '>=8.10.0'}
|
|
||||||
dependencies:
|
|
||||||
picomatch: 2.3.1
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/require-directory/2.1.1:
|
|
||||||
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
|
|
||||||
engines: {node: '>=0.10.0'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/safe-buffer/5.2.1:
|
|
||||||
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/serialize-javascript/6.0.0:
|
|
||||||
resolution: {integrity: sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==}
|
|
||||||
dependencies:
|
|
||||||
randombytes: 2.1.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/string-width/4.2.3:
|
|
||||||
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
dependencies:
|
|
||||||
emoji-regex: 8.0.0
|
|
||||||
is-fullwidth-code-point: 3.0.0
|
|
||||||
strip-ansi: 6.0.1
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/strip-ansi/6.0.1:
|
|
||||||
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
dependencies:
|
|
||||||
ansi-regex: 5.0.1
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/strip-json-comments/3.1.1:
|
|
||||||
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/supports-color/7.2.0:
|
|
||||||
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
dependencies:
|
|
||||||
has-flag: 4.0.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/supports-color/8.1.1:
|
|
||||||
resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dependencies:
|
|
||||||
has-flag: 4.0.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/to-regex-range/5.0.1:
|
|
||||||
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
|
|
||||||
engines: {node: '>=8.0'}
|
|
||||||
dependencies:
|
|
||||||
is-number: 7.0.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/ts-node/10.9.1_tdn3ypgnfy6bmey2q4hu5jonwi:
|
|
||||||
resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==}
|
|
||||||
hasBin: true
|
|
||||||
peerDependencies:
|
|
||||||
'@swc/core': '>=1.2.50'
|
|
||||||
'@swc/wasm': '>=1.2.50'
|
|
||||||
'@types/node': '*'
|
|
||||||
typescript: '>=2.7'
|
|
||||||
peerDependenciesMeta:
|
|
||||||
'@swc/core':
|
|
||||||
optional: true
|
|
||||||
'@swc/wasm':
|
|
||||||
optional: true
|
|
||||||
dependencies:
|
|
||||||
'@cspotcode/source-map-support': 0.8.1
|
|
||||||
'@tsconfig/node10': 1.0.9
|
|
||||||
'@tsconfig/node12': 1.0.11
|
|
||||||
'@tsconfig/node14': 1.0.3
|
|
||||||
'@tsconfig/node16': 1.0.3
|
|
||||||
'@types/node': 18.0.6
|
|
||||||
acorn: 8.7.1
|
|
||||||
acorn-walk: 8.2.0
|
|
||||||
arg: 4.1.3
|
|
||||||
create-require: 1.1.1
|
|
||||||
diff: 4.0.2
|
|
||||||
make-error: 1.3.6
|
|
||||||
typescript: 4.7.4
|
|
||||||
v8-compile-cache-lib: 3.0.1
|
|
||||||
yn: 3.1.1
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/type-detect/4.0.8:
|
|
||||||
resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==}
|
|
||||||
engines: {node: '>=4'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/typescript/4.7.4:
|
|
||||||
resolution: {integrity: sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==}
|
|
||||||
engines: {node: '>=4.2.0'}
|
|
||||||
hasBin: true
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/v8-compile-cache-lib/3.0.1:
|
|
||||||
resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/workerpool/6.2.1:
|
|
||||||
resolution: {integrity: sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/wrap-ansi/7.0.0:
|
|
||||||
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dependencies:
|
|
||||||
ansi-styles: 4.3.0
|
|
||||||
string-width: 4.2.3
|
|
||||||
strip-ansi: 6.0.1
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/wrappy/1.0.2:
|
|
||||||
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/y18n/5.0.8:
|
|
||||||
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/yargs-parser/20.2.4:
|
|
||||||
resolution: {integrity: sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/yargs-unparser/2.0.0:
|
|
||||||
resolution: {integrity: sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dependencies:
|
|
||||||
camelcase: 6.3.0
|
|
||||||
decamelize: 4.0.0
|
|
||||||
flat: 5.0.2
|
|
||||||
is-plain-obj: 2.1.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/yargs/16.2.0:
|
|
||||||
resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dependencies:
|
|
||||||
cliui: 7.0.4
|
|
||||||
escalade: 3.1.1
|
|
||||||
get-caller-file: 2.0.5
|
|
||||||
require-directory: 2.1.1
|
|
||||||
string-width: 4.2.3
|
|
||||||
y18n: 5.0.8
|
|
||||||
yargs-parser: 20.2.4
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/yn/3.1.1:
|
|
||||||
resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==}
|
|
||||||
engines: {node: '>=6'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/yocto-queue/0.1.0:
|
|
||||||
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dev: true
|
|
||||||
|
|
@ -1,157 +0,0 @@
|
||||||
import { Board } from "../types/GameBoard";
|
|
||||||
import { expect } from "chai";
|
|
||||||
import "mocha";
|
|
||||||
|
|
||||||
import { countShips, shipLocation } from "./movement";
|
|
||||||
|
|
||||||
function stringifyBoard(b: Board) {
|
|
||||||
return (
|
|
||||||
b.singularity.join(`\t`)
|
|
||||||
+ ` > `
|
|
||||||
+ [...b.path].map(x => x != null ? x : `-`).join(`\t`)
|
|
||||||
+ ` > `
|
|
||||||
+ b.warpgate.join(`\t`)
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
describe("The shipLocation function", () => {
|
|
||||||
|
|
||||||
const tests = [
|
|
||||||
{
|
|
||||||
name: `Should correctly identify the singularity location`,
|
|
||||||
args: ["a"],
|
|
||||||
input: {
|
|
||||||
singularity: ["a"],
|
|
||||||
path: [],
|
|
||||||
warpgate: [],
|
|
||||||
},
|
|
||||||
expect: "singularity",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `Should correctly identify the path location`,
|
|
||||||
args: ["a"],
|
|
||||||
input: {
|
|
||||||
singularity: [],
|
|
||||||
path: ["a"],
|
|
||||||
warpgate: [],
|
|
||||||
},
|
|
||||||
expect: "path",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `Should correctly identify the warpgate location`,
|
|
||||||
args: ["a"],
|
|
||||||
input: {
|
|
||||||
singularity: [],
|
|
||||||
path: [],
|
|
||||||
warpgate: ["a"],
|
|
||||||
},
|
|
||||||
expect: "warpgate",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `Should correctly identify the ship doesn't exist`,
|
|
||||||
args: ["a"],
|
|
||||||
input: {
|
|
||||||
singularity: [],
|
|
||||||
path: [],
|
|
||||||
warpgate: [],
|
|
||||||
},
|
|
||||||
expect: null,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const test of tests) {
|
|
||||||
it(test.name, () => {
|
|
||||||
let b = JSON.parse(JSON.stringify(test.input));
|
|
||||||
|
|
||||||
let location = shipLocation(b, test.args[0]);
|
|
||||||
expect(location).to.equal(test.expect);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
describe("The countShips function", () => {
|
|
||||||
|
|
||||||
const tests = [
|
|
||||||
{
|
|
||||||
name: `shouldn't could ships in the singularity or warpgate`,
|
|
||||||
args: [3],
|
|
||||||
input: {
|
|
||||||
singularity: ["a"],
|
|
||||||
path: [null, null, null, "b", null, null, null],
|
|
||||||
warpgate: ["c"],
|
|
||||||
},
|
|
||||||
shouldError: false,
|
|
||||||
expect: { left: 0, right: 0 },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `should count the ships in the path correctly when location is in the middle`,
|
|
||||||
args: [3],
|
|
||||||
input: {
|
|
||||||
singularity: ["a"],
|
|
||||||
path: ["d", null, "c", "b", null, null, "e"],
|
|
||||||
warpgate: [],
|
|
||||||
},
|
|
||||||
shouldError: false,
|
|
||||||
expect: { left: 2, right: 1 },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `should count the ships in the path correctly when location is on the low edge`,
|
|
||||||
args: [0],
|
|
||||||
input: {
|
|
||||||
singularity: ["a"],
|
|
||||||
path: ["d", null, "c", "b", null, null, "e"],
|
|
||||||
warpgate: [],
|
|
||||||
},
|
|
||||||
shouldError: false,
|
|
||||||
expect: { left: 0, right: 3 },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `should count the ships in the path correctly when location is on the high edge`,
|
|
||||||
args: [6],
|
|
||||||
input: {
|
|
||||||
singularity: ["a"],
|
|
||||||
path: ["d", null, "c", "b", null, null, "e"],
|
|
||||||
warpgate: [],
|
|
||||||
},
|
|
||||||
shouldError: false,
|
|
||||||
expect: { left: 3, right: 0 },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `should error when location is negative`,
|
|
||||||
args: [-1],
|
|
||||||
input: {
|
|
||||||
singularity: [],
|
|
||||||
path: ["d", null, "c", "b", null, null, "e"],
|
|
||||||
warpgate: [],
|
|
||||||
},
|
|
||||||
expect: new Error("location can't be negative"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `should error when location is too high`,
|
|
||||||
args: [100],
|
|
||||||
input: {
|
|
||||||
singularity: [],
|
|
||||||
path: ["d", null, "c", "b", null, null, "e"],
|
|
||||||
warpgate: [],
|
|
||||||
},
|
|
||||||
expect: new Error("location can't be larger than the path"),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const test of tests) {
|
|
||||||
it(test.name, () => {
|
|
||||||
let b = JSON.parse(JSON.stringify(test.input));
|
|
||||||
if (test.expect instanceof Error) {
|
|
||||||
expect(countShips(b, test.args[0])).to.throw(test.expect);
|
|
||||||
} else {
|
|
||||||
|
|
||||||
let count = countShips(b, test.args[0]);
|
|
||||||
expect(count).to.have.all.keys(Object.keys(test.expect));
|
|
||||||
expect(count.left).to.equal(test.expect.left);
|
|
||||||
expect(count.right).to.equal(test.expect.right);
|
|
||||||
};
|
|
||||||
});
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
@ -1,201 +0,0 @@
|
||||||
import { FuelCard } from "../index";
|
|
||||||
import { GamePiece, Board } from "../index";
|
|
||||||
|
|
||||||
|
|
||||||
/** @internal */
|
|
||||||
export function shipLocation(board: Board, ship: GamePiece) {
|
|
||||||
if (board.path.includes(ship)) {
|
|
||||||
return "path";
|
|
||||||
};
|
|
||||||
if (board.singularity.includes(ship)) {
|
|
||||||
return "singularity";
|
|
||||||
};
|
|
||||||
if (board.warpgate.includes(ship)) {
|
|
||||||
return "warpgate";
|
|
||||||
};
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/** @internal */
|
|
||||||
export function countShips(board: Board, location: number) {
|
|
||||||
|
|
||||||
if (location < 0) {
|
|
||||||
throw new Error("location can't be negative");
|
|
||||||
};
|
|
||||||
if (location > board.path.length) {
|
|
||||||
throw new Error("location can't be larger than the path");
|
|
||||||
};
|
|
||||||
|
|
||||||
let left = 0;
|
|
||||||
if (location > 0) {
|
|
||||||
left = board.path.slice(0, location - 1).filter(x => x != null).length;
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
left,
|
|
||||||
right: board.path.slice(location + 1).filter(x => x != null).length,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/** @internal */
|
|
||||||
export function determineDirection(board: Board, location: number): number {
|
|
||||||
|
|
||||||
/*
|
|
||||||
Edge-Case check for when the board only has a single ship on it because any
|
|
||||||
ships that hit the warp gate get removed from the game, and ships in the
|
|
||||||
singularity don't create gravity wells, not affecting other ships.
|
|
||||||
*/
|
|
||||||
let shipCount = 0;
|
|
||||||
for (const location of board.path) {
|
|
||||||
if (location != null) {
|
|
||||||
shipCount++;
|
|
||||||
if (shipCount >= 2) {
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
if (shipCount <= 1) {
|
|
||||||
return 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
let delta = 1;
|
|
||||||
while (true) {
|
|
||||||
if (location - delta < 0) {
|
|
||||||
return 1;
|
|
||||||
} else if (location + delta >= board.path.length) {
|
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
let left = board.path[location - delta];
|
|
||||||
let right = board.path[location + delta];
|
|
||||||
|
|
||||||
if (left != null && right != null) {
|
|
||||||
let sum = countShips(board, location)
|
|
||||||
return Math.sign(sum.right - sum.left);
|
|
||||||
} else if (left != null) {
|
|
||||||
return -1;
|
|
||||||
} else if (right != null) {
|
|
||||||
return 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
delta++;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/** @internal */
|
|
||||||
export function tractorBeam(board: Board, ship: GamePiece, card: FuelCard) {
|
|
||||||
let delta = 0;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
delta++;
|
|
||||||
|
|
||||||
let behind = origin - delta;
|
|
||||||
let ahead = origin + delta;
|
|
||||||
|
|
||||||
let negativeNewPosition = behind;
|
|
||||||
let positiveNewPosition = ahead;
|
|
||||||
let behindShip = board[behind];
|
|
||||||
let aheadShip = board[ahead];
|
|
||||||
|
|
||||||
/*
|
|
||||||
Check for a ship behind the origin, if there is a ship there then pull
|
|
||||||
it towards the origin (forwards). If it were to collide with another
|
|
||||||
ship, then drift until it no longer collides.
|
|
||||||
*/
|
|
||||||
if (
|
|
||||||
behind >= 0
|
|
||||||
&& behindShip != null
|
|
||||||
) {
|
|
||||||
let localMagnitude = magnitude;
|
|
||||||
while (board[behind + localMagnitude] != null) {
|
|
||||||
localMagnitude++;
|
|
||||||
};
|
|
||||||
negativeNewPosition = behind + localMagnitude;
|
|
||||||
board[behind] = null;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
Check for a ship ahead of the origin, if there is a ship there then
|
|
||||||
pull it towards the origin (backwards). If it were to collide with
|
|
||||||
another ship, then drift until it no longer collides.
|
|
||||||
*/
|
|
||||||
if (
|
|
||||||
ahead < board.length
|
|
||||||
&& aheadShip
|
|
||||||
) {
|
|
||||||
let localMagnitude = magnitude;
|
|
||||||
while (board[ahead - localMagnitude] != null) {
|
|
||||||
localMagnitude++;
|
|
||||||
};
|
|
||||||
positiveNewPosition = ahead - localMagnitude;
|
|
||||||
board[ahead] = null;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Simultaneous movement
|
|
||||||
if (aheadShip) {
|
|
||||||
board[positiveNewPosition] = aheadShip;
|
|
||||||
};
|
|
||||||
if (behindShip) {
|
|
||||||
board[negativeNewPosition] = behindShip;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
if (behind < 0 && ahead >= board.length) {
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/** @internal */
|
|
||||||
export function moveShip(board: Board, ship: GamePiece, card: FuelCard) {
|
|
||||||
let locale = shipLocation(board, ship);
|
|
||||||
if (locale == "singularity") {
|
|
||||||
let newPos = card.magnitude;
|
|
||||||
|
|
||||||
// Used a purple card for some reason...
|
|
||||||
if (newPos < 0) { return };
|
|
||||||
board.path[card.magnitude] = ship;
|
|
||||||
}
|
|
||||||
else if (locale == "path") {
|
|
||||||
let oldPos = board.path.indexOf(ship);
|
|
||||||
let direction = determineDirection(board, oldPos)
|
|
||||||
let newPos = oldPos * direction * card.magnitude;
|
|
||||||
|
|
||||||
if (newPos < 0) {
|
|
||||||
board.singularity.push(ship);
|
|
||||||
board.path[oldPos] = null;
|
|
||||||
} else if (newPos >= board.path.length) {
|
|
||||||
board.warpgate.push(ship);
|
|
||||||
board.path[oldPos] = null;
|
|
||||||
} else {
|
|
||||||
// Drift the ship
|
|
||||||
while (board.path[newPos] != null) {
|
|
||||||
newPos += direction;
|
|
||||||
};
|
|
||||||
board.path[oldPos] = null;
|
|
||||||
board.path[newPos] = ship;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Applies a card to the board as it was played by the ship. This modifies the
|
|
||||||
* board in-place, if wanting to not modify the board in place, pass a deep-copy
|
|
||||||
* of the board into the function.
|
|
||||||
*
|
|
||||||
* @param board The game board
|
|
||||||
* @param ship The ship that is playing the card
|
|
||||||
* @param card The card that is being played
|
|
||||||
*/
|
|
||||||
export function processCard(board: Board, ship: GamePiece, card: FuelCard) {
|
|
||||||
if (card.type == "movement") {
|
|
||||||
moveShip(board, ship, card);
|
|
||||||
} else {
|
|
||||||
tractorBeam(board, ship, card);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
@ -1,193 +0,0 @@
|
||||||
import { countShips, determineDirection } from "./movementDirection"
|
|
||||||
import { expect } from "chai";
|
|
||||||
import "mocha";
|
|
||||||
|
|
||||||
describe("The countShips function", () => {
|
|
||||||
it("should count the ships correctly when unbalanced", () => {
|
|
||||||
let r = countShips(["p3", null, "p1", "p2", null, "p4"], 2);
|
|
||||||
expect(r).to.have.keys(`left`, `right`);
|
|
||||||
expect(r.left).to.equal(1);
|
|
||||||
expect(r.right).to.equal(2);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should count the ships correctly when balanced", () => {
|
|
||||||
let r = countShips(["p3", null, "p1", "p2", null], 2);
|
|
||||||
expect(r).to.have.keys(`left`, `right`);
|
|
||||||
expect(r.left).to.equal(1);
|
|
||||||
expect(r.right).to.equal(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should count the ships correctly when shipLocation is at the start of the array", () => {
|
|
||||||
let r = countShips(["p3", null, "p1", "p2", null], 0);
|
|
||||||
expect(r).to.have.keys(`left`, `right`);
|
|
||||||
expect(r.left).to.equal(0);
|
|
||||||
expect(r.right).to.equal(2);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should count the ships correctly when shipLocation is at the end of the array", () => {
|
|
||||||
let r = countShips(["p3", null, "p1", "p2", null, "p4"], 5);
|
|
||||||
expect(r).to.have.keys(`left`, `right`);
|
|
||||||
expect(r.left).to.equal(3);
|
|
||||||
expect(r.right).to.equal(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should throw an error when shipLocation is larger than length", () => {
|
|
||||||
try {
|
|
||||||
countShips(["p3", null, "p1", "p2", null, "p4"], 8);
|
|
||||||
throw "Function didn't throw an error";
|
|
||||||
} catch (_) {}
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should throw an error when shipLocation is less than 0", () => {
|
|
||||||
try {
|
|
||||||
countShips(["p3", null, "p1", "p2", null, "p4"], -3);
|
|
||||||
throw "Function didn't throw an error";
|
|
||||||
} catch (_) {}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("The determineDirection function", () => {
|
|
||||||
|
|
||||||
it("should return positive when no other ships present (0-index)", () => {
|
|
||||||
let b = [
|
|
||||||
"p1", null, null, null, null,
|
|
||||||
null, null, null, null, null,
|
|
||||||
null, null, null, null, null,
|
|
||||||
];
|
|
||||||
let p = b.findIndex(x => x == "p1");
|
|
||||||
expect(determineDirection(b, p)).to.be.greaterThan(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return positive when no other ships present (low-index)", () => {
|
|
||||||
let b = [
|
|
||||||
null, null, "p1", null, null,
|
|
||||||
null, null, null, null, null,
|
|
||||||
null, null, null, null, null,
|
|
||||||
];
|
|
||||||
let p = b.findIndex(x => x == "p1");
|
|
||||||
expect(determineDirection(b, p)).to.be.greaterThan(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return positive when no other ships present (mid-index)", () => {
|
|
||||||
let b = [
|
|
||||||
null, null, null, null, null,
|
|
||||||
null, null, "p1", null, null,
|
|
||||||
null, null, null, null, null,
|
|
||||||
];
|
|
||||||
let p = b.findIndex(x => x == "p1");
|
|
||||||
expect(determineDirection(b, p)).to.be.greaterThan(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return positive when no other ships present (high-index)", () => {
|
|
||||||
let b = [
|
|
||||||
null, null, null, null, null,
|
|
||||||
null, null, null, null, null,
|
|
||||||
null, null, "p1", null, null,
|
|
||||||
];
|
|
||||||
let p = b.findIndex(x => x == "p1");
|
|
||||||
expect(determineDirection(b, p)).to.be.greaterThan(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return positive when no other ships present (max-index)", () => {
|
|
||||||
let b = [
|
|
||||||
null, null, null, null, null,
|
|
||||||
null, null, null, null, null,
|
|
||||||
null, null, null, null, "p1",
|
|
||||||
];
|
|
||||||
let p = b.findIndex(x => x == "p1");
|
|
||||||
expect(determineDirection(b, p)).to.be.greaterThan(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return negative when the only other ship is at a lower index", () => {
|
|
||||||
let b = [
|
|
||||||
null, "p2", null, null, null,
|
|
||||||
null, null, "p1", null, null,
|
|
||||||
null, null, null, null, null,
|
|
||||||
];
|
|
||||||
let p = b.findIndex(x => x == "p1");
|
|
||||||
expect(determineDirection(b, p)).to.be.lessThan(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return negative when the closest ship is on the 0th index", () => {
|
|
||||||
let b = [ "p2", null, "p1", null, null, "p3", null ];
|
|
||||||
let p = b.findIndex(x => x == "p1");
|
|
||||||
expect(determineDirection(b, p)).to.be.lessThan(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return negative when the closest ship is on the highest index", () => {
|
|
||||||
let b = [ null, "p2", null, null, "p1", null, "p3" ];
|
|
||||||
let p = b.findIndex(x => x == "p1");
|
|
||||||
expect(determineDirection(b, p)).to.be.greaterThan(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return positive when the only other ship is at a higher index", () => {
|
|
||||||
let b = [
|
|
||||||
null, null, null, null, null,
|
|
||||||
null, null, "p1", null, null,
|
|
||||||
null, null, null, "p2", null,
|
|
||||||
];
|
|
||||||
let p = b.findIndex(x => x == "p1");
|
|
||||||
expect(determineDirection(b, p)).to.be.greaterThan(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
it("should return positive when the closest ship is at a higher index", () => {
|
|
||||||
let b = [
|
|
||||||
null, "p3", null, null, null,
|
|
||||||
null, null, "p1", null, null,
|
|
||||||
null, null, "p2", null, null,
|
|
||||||
];
|
|
||||||
let p = b.findIndex(x => x == "p1");
|
|
||||||
expect(determineDirection(b, p)).to.be.greaterThan(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return negative when the closest ship is at a lower index", () => {
|
|
||||||
let b = [
|
|
||||||
null, null, "p3", null, null,
|
|
||||||
null, null, "p1", null, null,
|
|
||||||
null, null, null, "p2", null,
|
|
||||||
];
|
|
||||||
let p = b.findIndex(x => x == "p1");
|
|
||||||
expect(determineDirection(b, p)).to.be.lessThan(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return 0 when there is a tie between the closest ships (no extra ships)", () => {
|
|
||||||
let b = [
|
|
||||||
null, null, "p3", null, null,
|
|
||||||
null, null, "p1", null, null,
|
|
||||||
null, null, "p2", null, null,
|
|
||||||
];
|
|
||||||
let p = b.findIndex(x => x == "p1");
|
|
||||||
expect(determineDirection(b, p)).to.equal(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return negative when there is a tie between the closest ships (extra ships in negative direction)", () => {
|
|
||||||
let b = [
|
|
||||||
null, "p4", "p3", null, null,
|
|
||||||
null, null, "p1", null, null,
|
|
||||||
null, null, "p2", null, null,
|
|
||||||
];
|
|
||||||
let p = b.findIndex(x => x == "p1");
|
|
||||||
expect(determineDirection(b, p)).to.be.lessThan(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return positive when there is a tie between the closest ships (extra ships in positive direction)", () => {
|
|
||||||
let b = [
|
|
||||||
null, null, "p3", null, null,
|
|
||||||
null, null, "p1", null, null,
|
|
||||||
null, null, "p2", "p4", null,
|
|
||||||
];
|
|
||||||
let p = b.findIndex(x => x == "p1");
|
|
||||||
expect(determineDirection(b, p)).to.be.greaterThan(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return positive when there is a tie between the closest ships (extra ships tied)", () => {
|
|
||||||
let b = [
|
|
||||||
null, "p5", "p3", null, null,
|
|
||||||
null, null, "p1", null, null,
|
|
||||||
null, null, "p2", "p4", null,
|
|
||||||
];
|
|
||||||
let p = b.findIndex(x => x == "p1");
|
|
||||||
expect(determineDirection(b, p)).to.equal(0);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
@ -1,115 +0,0 @@
|
||||||
/**
|
|
||||||
* @internal
|
|
||||||
* A helper method for counting how many ships are on each side of a specific
|
|
||||||
* ship on the board.
|
|
||||||
*
|
|
||||||
* @param board The array of spaces that represents the Gravwell board
|
|
||||||
* @param shipLocation The index of the ship that we are counting the number of
|
|
||||||
* ships on each side for.
|
|
||||||
* @returns An object containing the number of ships that are on each side of
|
|
||||||
* the target ship
|
|
||||||
*/
|
|
||||||
export function countShips(board: any[], shipLocation: number) {
|
|
||||||
if (shipLocation < 0) {
|
|
||||||
throw new Error("shipLocation must be >= 0");
|
|
||||||
};
|
|
||||||
|
|
||||||
// Ensure that when shipLocation we don't assume all ships are to the left
|
|
||||||
// of it due to negative indexing in .slice() being supported
|
|
||||||
let left = 0;
|
|
||||||
if (shipLocation > 0) {
|
|
||||||
left = board.slice(0, shipLocation - 1).filter(x => x != null).length;
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
left,
|
|
||||||
right: board.slice(shipLocation + 1).filter(x => x != null).length
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The algorithm to determine which direction the closest ship is, this uses an
|
|
||||||
* integer that can be multiplied by the player's fuel card magnitude in order
|
|
||||||
* to determine the delta for the board index.
|
|
||||||
*
|
|
||||||
* ---
|
|
||||||
*
|
|
||||||
* Possible Return Values:
|
|
||||||
* - `-1` = Away from the Warp Gate
|
|
||||||
* - `0` = Not moving
|
|
||||||
* - `1` = Towards the Warp Gate
|
|
||||||
*/
|
|
||||||
export function determineDirection(board: any[], shipLocation: number) {
|
|
||||||
|
|
||||||
/*
|
|
||||||
Edge-Case check for when the board only has a single ship on it because any
|
|
||||||
ships that hit the warp gate get removed from the game, and ships in the
|
|
||||||
singularity don't create gravity wells, not affecting other ships.
|
|
||||||
*/
|
|
||||||
let shipCount = 0;
|
|
||||||
for (const location of board) {
|
|
||||||
if (location != null) {
|
|
||||||
shipCount++;
|
|
||||||
if (shipCount >= 2) {
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
if (shipCount <= 1) {
|
|
||||||
return 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
let delta = 1;
|
|
||||||
while (true) {
|
|
||||||
// The left side of the board is out of range, nearest ship is always
|
|
||||||
// right
|
|
||||||
if (shipLocation - delta < 0) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The right side of the board is out of range, nearest ship is always
|
|
||||||
// left
|
|
||||||
else if (shipLocation + delta >= board.length) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Both sides are still in range, continue
|
|
||||||
else {
|
|
||||||
|
|
||||||
let left = board[shipLocation - delta];
|
|
||||||
let right = board[shipLocation + delta];
|
|
||||||
|
|
||||||
// Nearest ships are equidistant, fallback to sum
|
|
||||||
if (left != null && right != null) {
|
|
||||||
let sum = countShips(board, shipLocation);
|
|
||||||
|
|
||||||
// More ships on the left, going backwards
|
|
||||||
if (sum.left > sum.right) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// more ships on the right, going forward
|
|
||||||
else if (sum.left < sum.right) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Equal number of ships, staying still
|
|
||||||
else {
|
|
||||||
return 0;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Left side of ship is closer
|
|
||||||
else if (left != null) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Right side of ship is closer
|
|
||||||
else if (right != null) {
|
|
||||||
return 1;
|
|
||||||
};
|
|
||||||
delta++;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
@ -1,233 +0,0 @@
|
||||||
import { tractorBeam, moveShip } from "./processCard";
|
|
||||||
import { Board } from "../types/GameBoard";
|
|
||||||
import { expect } from "chai";
|
|
||||||
import "mocha";
|
|
||||||
import { FuelCard } from "../types/FuelCard";
|
|
||||||
|
|
||||||
function stringifyBoard(b: Board) {
|
|
||||||
return [...b].map(x => x != null ? x : `-`).join(`\t`);
|
|
||||||
};
|
|
||||||
|
|
||||||
interface BaseTest {
|
|
||||||
name: string;
|
|
||||||
input: Board;
|
|
||||||
expect: Board;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface tractorTest extends BaseTest {
|
|
||||||
args: [number, number];
|
|
||||||
}
|
|
||||||
|
|
||||||
interface moveTest extends BaseTest {
|
|
||||||
args: [number, FuelCard] | [number];
|
|
||||||
}
|
|
||||||
|
|
||||||
describe("The tractorBeam function", () => {
|
|
||||||
|
|
||||||
const tests: tractorTest[] = [
|
|
||||||
{
|
|
||||||
name: `should move the ships closer when equidistant`,
|
|
||||||
args: [4, 1],
|
|
||||||
input: [ null, "p1", null, null, "p2", null, null, "p3", null ],
|
|
||||||
expect: [ null, null, "p1", null, "p2", null, "p3", null, null ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `should move the ships closer when not equidistant`,
|
|
||||||
args: [4, 1],
|
|
||||||
input: [ null, "p1", null, null, "p2", null, null, null, "p3" ],
|
|
||||||
expect: [ null, null, "p1", null, "p2", null, null, "p3", null ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `should move the ships closer when only on the left side`,
|
|
||||||
args: [4, 1],
|
|
||||||
input: [ null, "p1", null, null, "p2", null, null, null, null ],
|
|
||||||
expect: [ null, null, "p1", null, "p2", null, null, null, null ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `should move the ships closer when only on the right side`,
|
|
||||||
args: [4, 1],
|
|
||||||
input: [ null, null, null, null, "p2", null, null, "p3", null ],
|
|
||||||
expect: [ null, null, null, null, "p2", null, "p3", null, null ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `should move the ships closer when pulling the ship from the left edge`,
|
|
||||||
args: [4, 1],
|
|
||||||
input: [ "p1", null, null, null, "p2", null, null, null, null ],
|
|
||||||
expect: [ null, "p1", null, null, "p2", null, null, null, null ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `should move the ships closer when pulling the ship from the right edge`,
|
|
||||||
args: [4, 1],
|
|
||||||
input: [ null, null, null, null, "p2", null, null, null, "p3" ],
|
|
||||||
expect: [ null, null, null, null, "p2", null, null, "p3", null ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `should move the ship closer when the origin is on the left edge`,
|
|
||||||
args: [0, 1],
|
|
||||||
input: [ "p1", null, null, null, "p2", null, null, null, null ],
|
|
||||||
expect: [ "p1", null, null, "p2", null, null, null, null, null ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `should move the ship closer when the origin is on the right edge`,
|
|
||||||
args: [8, 1],
|
|
||||||
input: [ null, null, null, null, "p2", null, null, null, "p1" ],
|
|
||||||
expect: [ null, null, null, null, null, "p2", null, null, "p1" ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `should move the ship correctly when it needs to drift (single ship drift)`,
|
|
||||||
args: [4, 1],
|
|
||||||
input: [ null, null, null, "p1", "p2", null, null, null, null ],
|
|
||||||
expect: [ null, null, null, null, "p2", "p1", null, null, null ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `should move the ship correctly when it needs to drift (multi-ship drift)`,
|
|
||||||
args: [4, 1],
|
|
||||||
input: [ null, null, null, "p1", "p2", null, "p3", null, null ],
|
|
||||||
expect: [ null, null, null, "p3", "p2", "p1", null, null, null ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `should move the ship correctly when it needs to drift (multi-ship drift unbalanced)`,
|
|
||||||
args: [4, 1],
|
|
||||||
input: [ null, null, null, "p1", "p2", null, "p3", "p4", null ],
|
|
||||||
expect: [ null, null, null, "p3", "p2", "p1", "p4", null, null ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `should move the ship correctly when it needs to cross-over`,
|
|
||||||
args: [4, 1],
|
|
||||||
input: [ null, null, null, "p1", "p2", "p3", null, null, null ],
|
|
||||||
expect: [ null, null, null, "p3", "p2", "p1", null, null, null ]
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const test of tests) {
|
|
||||||
it(test.name, () => {
|
|
||||||
let b = [...test.input];
|
|
||||||
tractorBeam(b, ...test.args);
|
|
||||||
expect(b).to.have.length(test.expect.length);
|
|
||||||
expect(stringifyBoard(b)).to.equal(stringifyBoard(test.expect));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
describe.only("The moveShip function [non-repulsor tests]", () => {
|
|
||||||
const tests: moveTest[] = [
|
|
||||||
{
|
|
||||||
name: `should move forward when no other ships present`,
|
|
||||||
args: [2],
|
|
||||||
input: [ null, null, "p1", null, null, null, null ],
|
|
||||||
expect: [ null, null, null, "p1", null, null, null ],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `should move forwards when closest is ahead of the ship`,
|
|
||||||
args: [0],
|
|
||||||
input: [ "p1", null, "p2" ],
|
|
||||||
expect: [ null, "p1", "p2" ],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `should move backwards when closest is behind the ship`,
|
|
||||||
args: [2],
|
|
||||||
input: [ "p2", null, "p1" ],
|
|
||||||
expect: [ "p2", "p1", null ],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `should drift forwards over a single ship`,
|
|
||||||
args: [2],
|
|
||||||
input: [ null, null, "p1", "p2", null, null, null, ],
|
|
||||||
expect: [ null, null, null, "p2", "p1", null, null, ],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `should drift backwards over a single ship`,
|
|
||||||
args: [4],
|
|
||||||
input: [ null, null, null, "p2", "p1", null, null, ],
|
|
||||||
expect: [ null, null, "p1", "p2", null, null, null, ],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `should drift forwards over multiple ships`,
|
|
||||||
args: [2],
|
|
||||||
input: [ null, null, "p1", "p2", "p3", null, null, ],
|
|
||||||
expect: [ null, null, null, "p2", "p3", "p1", null, ],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `should drift backwards over multiple ships`,
|
|
||||||
args: [4],
|
|
||||||
input: [ null, null, "p3", "p2", "p1", null, null, ],
|
|
||||||
expect: [ null, "p1", "p3", "p2", null, null, null, ],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `shouldn't affect other ships`,
|
|
||||||
args: [4],
|
|
||||||
expect: [ null, "p2", null, null, "p1", null, "p3" ],
|
|
||||||
input: [ null, "p2", null, null, null, "p1", "p3" ],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `should move away from lower the edge going forwards`,
|
|
||||||
args: [0],
|
|
||||||
input: [ "p1", null, "p2", null ],
|
|
||||||
expect: [ null, "p1", "p2", null ],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `should move away from upper the edge going backwards`,
|
|
||||||
args: [3],
|
|
||||||
input: [ null, "p2", null, "p1" ],
|
|
||||||
expect: [ null, "p2", "p1", null ],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const test of tests) {
|
|
||||||
it(test.name, () => {
|
|
||||||
let b = [...test.input];
|
|
||||||
|
|
||||||
if (test.args.length == 1) {
|
|
||||||
moveShip(
|
|
||||||
b,
|
|
||||||
test.args[0],
|
|
||||||
{
|
|
||||||
"magnitude": 1,
|
|
||||||
"symbol": "Ar",
|
|
||||||
"name": "Argon",
|
|
||||||
"type": "movement"
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
moveShip(b, ...test.args);
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(b).to.have.length(test.expect.length);
|
|
||||||
expect(stringifyBoard(b)).to.equal(stringifyBoard(test.expect));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
describe.only("The moveShip function [repulsor tests]", () => {
|
|
||||||
const tests: moveTest[] = [
|
|
||||||
{
|
|
||||||
name: `should move backwards when no other ships present`,
|
|
||||||
args: [3],
|
|
||||||
input: [ null, null, null, "p1", null, null, null ],
|
|
||||||
expect: [ null, null, "p1", null, null, null, null ],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const test of tests) {
|
|
||||||
it(test.name, () => {
|
|
||||||
let b = [...test.input];
|
|
||||||
if (test.args.length == 1) {
|
|
||||||
moveShip(
|
|
||||||
b,
|
|
||||||
test.args[0],
|
|
||||||
{
|
|
||||||
"magnitude": -1,
|
|
||||||
"symbol": "Ol",
|
|
||||||
"name": "Oliverium",
|
|
||||||
"type": "movement"
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
moveShip(b, ...test.args);
|
|
||||||
};
|
|
||||||
expect(b).to.have.length(test.expect.length);
|
|
||||||
expect(stringifyBoard(b)).to.equal(stringifyBoard(test.expect));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
})
|
|
||||||
|
|
@ -1,83 +0,0 @@
|
||||||
import { determineDirection } from "./movementDirection";
|
|
||||||
import { Board, GamePiece } from "../types/GameBoard";
|
|
||||||
import { FuelCard } from "../types/FuelCard";
|
|
||||||
|
|
||||||
/** @internal */
|
|
||||||
export function tractorBeam(board: Board, origin: number, magnitude: number) {
|
|
||||||
let delta = 0;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
delta++;
|
|
||||||
|
|
||||||
let behind = origin - delta;
|
|
||||||
let ahead = origin + delta;
|
|
||||||
|
|
||||||
let negativeNewPosition = behind;
|
|
||||||
let positiveNewPosition = ahead;
|
|
||||||
let behindShip = board[behind];
|
|
||||||
let aheadShip = board[ahead];
|
|
||||||
|
|
||||||
/*
|
|
||||||
Check for a ship behind the origin, if there is a ship there then pull
|
|
||||||
it towards the origin (forwards). If it were to collide with another
|
|
||||||
ship, then drift until it no longer collides.
|
|
||||||
*/
|
|
||||||
if (
|
|
||||||
behind >= 0
|
|
||||||
&& behindShip != null
|
|
||||||
) {
|
|
||||||
let localMagnitude = magnitude;
|
|
||||||
while (board[behind + localMagnitude] != null) {
|
|
||||||
localMagnitude++;
|
|
||||||
};
|
|
||||||
negativeNewPosition = behind + localMagnitude;
|
|
||||||
board[behind] = null;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
Check for a ship ahead of the origin, if there is a ship there then
|
|
||||||
pull it towards the origin (backwards). If it were to collide with
|
|
||||||
another ship, then drift until it no longer collides.
|
|
||||||
*/
|
|
||||||
if (
|
|
||||||
ahead < board.length
|
|
||||||
&& aheadShip
|
|
||||||
) {
|
|
||||||
let localMagnitude = magnitude;
|
|
||||||
while (board[ahead - localMagnitude] != null) {
|
|
||||||
localMagnitude++;
|
|
||||||
};
|
|
||||||
positiveNewPosition = ahead - localMagnitude;
|
|
||||||
board[ahead] = null;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Simultaneous movement
|
|
||||||
if (aheadShip) {
|
|
||||||
board[positiveNewPosition] = aheadShip;
|
|
||||||
};
|
|
||||||
if (behindShip) {
|
|
||||||
board[negativeNewPosition] = behindShip;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
if (behind < 0 && ahead >= board.length) {
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/** @internal */
|
|
||||||
export function moveShip(board: Board, origin: number, fuel: FuelCard) {
|
|
||||||
let direction = determineDirection(board, origin);
|
|
||||||
if (direction == 0) { return };
|
|
||||||
|
|
||||||
let newIndex = origin + ( fuel.magnitude * direction );
|
|
||||||
while (board[newIndex] != null) {
|
|
||||||
newIndex += direction;
|
|
||||||
};
|
|
||||||
|
|
||||||
board[newIndex] = board[origin];
|
|
||||||
board[origin] = null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function processCard(board: Board, shipLocation: number, fuel: FuelCard) {};
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
import { IColour } from "../types/Colour";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The colours that can be used by the user to make their ship unique. Each
|
|
||||||
* player is assigned a random, unused, colour when they join the lobby.
|
|
||||||
*/
|
|
||||||
export const colours: IColour[] = [
|
|
||||||
{ name: "Green", hex: "#00aa00" },
|
|
||||||
{ name: "Blue", hex: "#0077b6" },
|
|
||||||
{ name: "Red", hex: "#cb0b0a" },
|
|
||||||
{ name: "Purple", hex: "#7400b8" },
|
|
||||||
{ name: "Orange", hex: "#faa307" },
|
|
||||||
{ name: "Light Green", hex: "#9ef01a" },
|
|
||||||
{ name: "Magenta", hex: "#b7094c" },
|
|
||||||
{ name: "Pink", hex: "#f72585" },
|
|
||||||
{ name: "Yellow", hex: "#f9c80e" },
|
|
||||||
];
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
import { IGameOption } from "../types/GameOption";
|
|
||||||
|
|
||||||
/** The options that games can support. */
|
|
||||||
export const gameOptions: IGameOption[] = [
|
|
||||||
{
|
|
||||||
name: `No Secrets`,
|
|
||||||
id: `no-secrets`,
|
|
||||||
active: false,
|
|
||||||
hidden: true,
|
|
||||||
description: `During the mining phase of each round, all cards remain face up, including the piles that are available for choosing from and the cards each player has chosen, stay visible until the Movement Phase begins.`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `Warp Gate Activated`,
|
|
||||||
id: `warp-gate-activated`,
|
|
||||||
active: false,
|
|
||||||
hidden: false,
|
|
||||||
description: `With this option enabled, when a spaceship enters the Warp Gate space (#54), it is immediately removed from the game, but the Warp Gate remains open. This allows more spaceships to enter the gate before the end of the round, any additional spaceships that enter the Warp Gate before the round ends share in the victory because they escaped from the black hole.`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `Chaos Theory`,
|
|
||||||
id: `chaos-theory`,
|
|
||||||
active: false,
|
|
||||||
hidden: false,
|
|
||||||
description: `The first card played during each movement phase is chosen randomly. You still have the opportunity to use your Emergency Stop if you have it available.`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `Hardcore`,
|
|
||||||
id: `hardcore`,
|
|
||||||
active: false,
|
|
||||||
hidden: false,
|
|
||||||
description: `When Hardcore Mode is enabled, you can only use the Emergency Stop <b>one time</b> for the entire game!`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `Fate`,
|
|
||||||
id: `fate`,
|
|
||||||
active: false,
|
|
||||||
hidden: true,
|
|
||||||
description: `Every player must decide on the order that their cards will be played in prior to the first movement happening in the round. Then the cards will be resolved as normal, but with the player not being able to dynamically react. The Emergency Stop is able to be used as normal.`,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
import { ISpaceship } from "../types/Spaceship";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The spaceships that are supported in the system, the "id" property **must**
|
|
||||||
* exist in the spaceship.svelte file as an icon. The first icon in this list
|
|
||||||
* will be used by the server to assign new players' ship icon.
|
|
||||||
*/
|
|
||||||
export const spaceships: ISpaceship[] = [
|
|
||||||
{
|
|
||||||
name: "Space Shuttle",
|
|
||||||
id: "space-shuttle"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Rocket",
|
|
||||||
id: "rocket"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Sailboat",
|
|
||||||
id: "sailboat"
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
export enum Status {
|
|
||||||
/** The request was successful */
|
|
||||||
Success = 200,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The request contains malformed data and cannot be processed.
|
|
||||||
*/
|
|
||||||
BadRequest = 400,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Some data is out of date and needs to be updated before another request
|
|
||||||
* can be made. Check the "message" for additional information.
|
|
||||||
*/
|
|
||||||
OutOfDate = 401,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The resource that is being requested cannot be accessed at the current
|
|
||||||
* point in time for some reason. Check the "message" for additional details.
|
|
||||||
*/
|
|
||||||
Forbidden = 403,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Something in the request couldn't be found. Check the "message" for
|
|
||||||
* additional information.
|
|
||||||
*/
|
|
||||||
NotFound = 404,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Something went wrong in the server that we don't have a more specific
|
|
||||||
* error for. Check the "message" for additional details. This may be
|
|
||||||
* fixable by the client who made the request, it may not be.
|
|
||||||
*/
|
|
||||||
UnknownError = 500,
|
|
||||||
}
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
// Enums
|
|
||||||
export { Status } from "./enums/Status";
|
|
||||||
|
|
||||||
// Algorithms
|
|
||||||
export * from "./algorithms/processCard";
|
|
||||||
export * from "./algorithms/movementDirection";
|
|
||||||
|
|
||||||
// Data
|
|
||||||
export * from "./data/colours";
|
|
||||||
export * from "./data/spaceships";
|
|
||||||
export * from "./data/game_options";
|
|
||||||
|
|
||||||
// Data Structures
|
|
||||||
export * from "./types/Colour";
|
|
||||||
export * from "./types/FuelCard";
|
|
||||||
export * from "./types/GameBoard";
|
|
||||||
export * from "./types/Spaceship";
|
|
||||||
export * from "./types/PlayerData";
|
|
||||||
export * from "./types/GameOption";
|
|
||||||
|
|
||||||
// Server-Client Communications
|
|
||||||
export * from "./types/ServerResponse";
|
|
||||||
export * from "./types/events/server_info";
|
|
||||||
|
|
||||||
// Lobby events
|
|
||||||
export * from "./types/events/lobby/info";
|
|
||||||
export * from "./types/events/lobby/create";
|
|
||||||
export * from "./types/events/lobby/delete";
|
|
||||||
export * from "./types/events/lobby/players/join";
|
|
||||||
export * from "./types/events/lobby/players/leave";
|
|
||||||
export * from "./types/events/lobby/players/update";
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
export interface IColour {
|
|
||||||
name: string;
|
|
||||||
hex: string;
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
export interface FuelCard {
|
|
||||||
magnitude: number;
|
|
||||||
symbol: string;
|
|
||||||
name: string;
|
|
||||||
type: "movement" | "stationary";
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
export type GamePiece = string | null;
|
|
||||||
|
|
||||||
export interface Board {
|
|
||||||
singularity: GamePiece[];
|
|
||||||
path: GamePiece[];
|
|
||||||
warpgate: GamePiece[];
|
|
||||||
}
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
/**
|
|
||||||
* The object structure that represents an option that can be applied to the
|
|
||||||
* game's logic
|
|
||||||
*/
|
|
||||||
export interface IGameOption {
|
|
||||||
|
|
||||||
/** The user-friendly name of the option */
|
|
||||||
name: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The ID that is used in the code to change what options are active in the
|
|
||||||
* game
|
|
||||||
*/
|
|
||||||
id: string;
|
|
||||||
|
|
||||||
/** Whether or not the host has activated this option */
|
|
||||||
active: boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether or not the option should be displayed to the users in the lobby
|
|
||||||
*/
|
|
||||||
hidden: boolean;
|
|
||||||
|
|
||||||
/** The description of the option that is put into the info modal. */
|
|
||||||
description: string;
|
|
||||||
}
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
import { IColour } from "./Colour";
|
|
||||||
import { FuelCard } from "./FuelCard";
|
|
||||||
import { ISpaceship } from "./Spaceship";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The data structure that represents a Player in the game
|
|
||||||
*/
|
|
||||||
export interface PlayerData {
|
|
||||||
|
|
||||||
/** The name the player chose while joining the lobby */
|
|
||||||
name: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The colour that the player's spaceship will be in the game. This must be
|
|
||||||
* unique among all players, this uniqueness is enforced by the server.
|
|
||||||
*/
|
|
||||||
colour: IColour;
|
|
||||||
|
|
||||||
/** The spaceship icon that the player will appear as in-game. */
|
|
||||||
ship: ISpaceship;
|
|
||||||
|
|
||||||
/** Whether or not the player is the host of the game. */
|
|
||||||
host: boolean;
|
|
||||||
|
|
||||||
/** The unique ID of the player */
|
|
||||||
id: string;
|
|
||||||
|
|
||||||
/** The fuel that the player is going to be playing this turn */
|
|
||||||
fuel?: FuelCard
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
/** The data that is common to most requests to the server. */
|
|
||||||
export interface ServerRequest {
|
|
||||||
|
|
||||||
/** The ID for the game that the action is being taken on. */
|
|
||||||
game_code: string;
|
|
||||||
}
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
import { Status } from "../enums/Status";
|
|
||||||
|
|
||||||
export interface ServerResponse {
|
|
||||||
|
|
||||||
/** The state indicator for responses from the server */
|
|
||||||
status: Status;
|
|
||||||
|
|
||||||
/** Additional information that is provided by the server */
|
|
||||||
message?: string;
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
export interface ISpaceship {
|
|
||||||
name: string;
|
|
||||||
id: string;
|
|
||||||
}
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
/** The data required for the `lobby.create` event to function correctly. */
|
|
||||||
export interface ICreateLobby {
|
|
||||||
/** The name of the user who is creating the lobby */
|
|
||||||
name: string;
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
import { ServerRequest } from "../../ServerRequest";
|
|
||||||
|
|
||||||
/** The data required by the server in order to delete the lobby */
|
|
||||||
export interface IDeleteLobby extends ServerRequest {}
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
import { PlayerData } from "../../PlayerData";
|
|
||||||
import { ServerResponse } from "../../ServerResponse";
|
|
||||||
|
|
||||||
/** The data sent as a response to `lobby.info`. */
|
|
||||||
export interface ILobbyInfo extends ServerResponse {
|
|
||||||
/**
|
|
||||||
* The lobby ID that can be used by clients to connect to the server with.
|
|
||||||
*/
|
|
||||||
game_code?: string;
|
|
||||||
|
|
||||||
/** The data associated with each player in the game. */
|
|
||||||
players?: PlayerData[];
|
|
||||||
}
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
import { ServerRequest } from "../../../ServerRequest";
|
|
||||||
|
|
||||||
/** The data required for a player to join a game lobby */
|
|
||||||
export interface IJoinLobby extends ServerRequest {
|
|
||||||
|
|
||||||
/** The name that the user wants to go by in the game */
|
|
||||||
name: string;
|
|
||||||
}
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
import { ServerRequest } from "../../../ServerRequest";
|
|
||||||
|
|
||||||
/** The required data for leaving a game, or kicking a player from a game. */
|
|
||||||
export interface ILeaveLobby extends ServerRequest {
|
|
||||||
|
|
||||||
/** The name of the player being removed from the lobby */
|
|
||||||
name: string;
|
|
||||||
}
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
import { IColour } from "../../../Colour";
|
|
||||||
import { ServerRequest } from "../../../ServerRequest";
|
|
||||||
import { ISpaceship } from "../../../Spaceship";
|
|
||||||
|
|
||||||
/** The required data for updating a player's information */
|
|
||||||
export interface IUpdatePlayer extends ServerRequest {
|
|
||||||
|
|
||||||
/** The name of the player that is being updated. */
|
|
||||||
name: string;
|
|
||||||
|
|
||||||
/** The player's spaceship design */
|
|
||||||
design: {
|
|
||||||
/**
|
|
||||||
* The icon used for the player's space ship. This can be the same for
|
|
||||||
* multiple players.
|
|
||||||
*/
|
|
||||||
ship: ISpaceship;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The colour of the user's ship. This is unique across all players,
|
|
||||||
* meaning all players must have a different colour.
|
|
||||||
*/
|
|
||||||
colour: IColour;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
import { ServerResponse } from "../ServerResponse";
|
|
||||||
|
|
||||||
/** The data sent as a response to `server.info`. */
|
|
||||||
export interface IServerInfo extends ServerResponse {
|
|
||||||
/** The version that the server is currently running. */
|
|
||||||
version?: string;
|
|
||||||
|
|
||||||
/** The count of how many games are currently stored as active in the Database */
|
|
||||||
game_count?: number;
|
|
||||||
}
|
|
||||||
|
|
@ -1,80 +0,0 @@
|
||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
/* Visit https://aka.ms/tsconfig.json to read more about this file */
|
|
||||||
|
|
||||||
/* Basic Options */
|
|
||||||
// "incremental": true, /* Enable incremental compilation */
|
|
||||||
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', 'ES2021', or 'ESNEXT'. */
|
|
||||||
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
|
|
||||||
// "lib": [], /* Specify library files to be included in the compilation. */
|
|
||||||
// "allowJs": true, /* Allow javascript files to be compiled. */
|
|
||||||
// "checkJs": true, /* Report errors in .js files. */
|
|
||||||
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */
|
|
||||||
"declaration": true, /* Generates corresponding '.d.ts' file. */
|
|
||||||
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
|
||||||
// "sourceMap": true, /* Generates corresponding '.map' file. */
|
|
||||||
// "outFile": "./", /* Concatenate and emit output to single file. */
|
|
||||||
"outDir": "./dist", /* Redirect output structure to the directory. */
|
|
||||||
"rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
|
||||||
// "composite": true, /* Enable project compilation */
|
|
||||||
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
|
|
||||||
// "removeComments": true, /* Do not emit comments to output. */
|
|
||||||
// "noEmit": true, /* Do not emit outputs. */
|
|
||||||
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
|
|
||||||
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
|
||||||
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
|
||||||
|
|
||||||
/* Strict Type-Checking Options */
|
|
||||||
"strict": true, /* Enable all strict type-checking options. */
|
|
||||||
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
|
|
||||||
// "strictNullChecks": true, /* Enable strict null checks. */
|
|
||||||
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
|
|
||||||
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
|
|
||||||
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
|
|
||||||
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
|
|
||||||
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
|
|
||||||
|
|
||||||
/* Additional Checks */
|
|
||||||
// "noUnusedLocals": true, /* Report errors on unused locals. */
|
|
||||||
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
|
||||||
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
|
||||||
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
|
||||||
// "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
|
|
||||||
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an 'override' modifier. */
|
|
||||||
// "noPropertyAccessFromIndexSignature": true, /* Require undeclared properties from index signatures to use element accesses. */
|
|
||||||
|
|
||||||
/* Module Resolution Options */
|
|
||||||
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
|
||||||
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
|
|
||||||
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
|
||||||
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
|
||||||
// "typeRoots": [], /* List of folders to include type definitions from. */
|
|
||||||
// "types": [], /* Type declaration files to be included in compilation. */
|
|
||||||
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
|
||||||
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
|
||||||
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
|
||||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
|
||||||
|
|
||||||
/* Source Map Options */
|
|
||||||
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
|
|
||||||
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
|
||||||
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
|
|
||||||
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
|
|
||||||
|
|
||||||
/* Experimental Options */
|
|
||||||
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
|
||||||
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
|
|
||||||
|
|
||||||
/* Advanced Options */
|
|
||||||
"skipLibCheck": true, /* Skip type checking of declaration files. */
|
|
||||||
"forceConsistentCasingInFileNames": true, /* Disallow inconsistently-cased references to the same file. */
|
|
||||||
|
|
||||||
"stripInternal": true
|
|
||||||
},
|
|
||||||
"exclude": [
|
|
||||||
"src/**/*.spec.ts",
|
|
||||||
"esm/**/*",
|
|
||||||
"cjs/**/*",
|
|
||||||
"node_modules/**/*"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
161
docs/events.md
|
|
@ -1,161 +0,0 @@
|
||||||
# Events
|
|
||||||
Every event in this document has two forms, a request and a response, the event
|
|
||||||
type can be differentiated by the event prefix, `req` is an event going to the
|
|
||||||
server, and `res` is a response coming from the server to the client. Some events
|
|
||||||
may only have one of these types, if this is the case, it will be denoted in the
|
|
||||||
relevant section.
|
|
||||||
|
|
||||||
**Important**: Events with the `Broadcasted` event type, must be listened to
|
|
||||||
even if you don't send any `Request` events of that type. This is because other
|
|
||||||
clients connected to the server may trigger the server in such a way that the
|
|
||||||
event response gets sent to multiple clients. **Broadcasted events will use the**
|
|
||||||
`res` **event type prefix.**
|
|
||||||
|
|
||||||
Most request payload types inherit from `ServerRequest`, and all response
|
|
||||||
payloads inherit from the `ServerResponse` type.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## `error`
|
|
||||||
The event that is sent to clients when they cause a significant error to happen
|
|
||||||
in the server. When this is sent, the status property will never be set to a
|
|
||||||
value in the success range.
|
|
||||||
|
|
||||||
### Supported Event Types
|
|
||||||
| Request | Response | Broadcasted
|
|
||||||
| ------- | -------- | -----------
|
|
||||||
| No | Yes | No
|
|
||||||
|
|
||||||
### Payloads
|
|
||||||
Request Payload: N/A
|
|
||||||
|
|
||||||
Response Payload: `ServerResponse`
|
|
||||||
---
|
|
||||||
|
|
||||||
## `server.info`
|
|
||||||
Retrieves information about the server that the client is currently connected
|
|
||||||
to.
|
|
||||||
|
|
||||||
### Supported Event Types
|
|
||||||
| Request | Response | Broadcasted
|
|
||||||
| ------- | -------- | -----------
|
|
||||||
| Yes | Yes | No
|
|
||||||
|
|
||||||
### Payloads
|
|
||||||
Request Payload: N/A
|
|
||||||
|
|
||||||
Response Payload: `IServerInfo`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## `lobby.info`
|
|
||||||
Retrieves information about the lobby. In order for this event to return without
|
|
||||||
error, the client requesting the information **must** be in the lobby already.
|
|
||||||
This event is broadcasted to clients who are already in the lobby when the
|
|
||||||
player list or a player's design gets updated.
|
|
||||||
|
|
||||||
### Supported Event Types
|
|
||||||
| Request | Response | Broadcasted
|
|
||||||
| ------- | -------- | -----------
|
|
||||||
| Yes | Yes | Yes
|
|
||||||
|
|
||||||
### Payloads
|
|
||||||
Request Payload: `IGetLobbyInfo`
|
|
||||||
|
|
||||||
Response Payload: `ILobbyInfo`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## `lobby.create`
|
|
||||||
Creates a game lobby that allows for online play.
|
|
||||||
|
|
||||||
### Supported Event Types
|
|
||||||
| Request | Response | Broadcasted
|
|
||||||
| ------- | -------- | -----------
|
|
||||||
| Yes | Yes | No
|
|
||||||
|
|
||||||
### Payloads
|
|
||||||
Request Payload: `ICreateLobby`
|
|
||||||
|
|
||||||
Response Payload: `ILobbyInfo`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## `lobby.delete`
|
|
||||||
Deletes the game lobby, clearing all players from the lobby and preventing
|
|
||||||
others from joining the lobby. This endpoint errors whenever a client that isn't
|
|
||||||
the host tries to call the endpoint.
|
|
||||||
|
|
||||||
### Supported Event Types
|
|
||||||
| Request | Response | Broadcasted
|
|
||||||
| ------- | -------- | -----------
|
|
||||||
| Yes | Yes | Yes
|
|
||||||
|
|
||||||
### Payloads
|
|
||||||
Request Payload: `IDeleteLobby`
|
|
||||||
|
|
||||||
Response Payload: `ServerResponse`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## `lobby.players.join`
|
|
||||||
Allows a player to join a lobby based on the lobby identifier.
|
|
||||||
|
|
||||||
### Supported Event Types
|
|
||||||
| Request | Response | Broadcasted
|
|
||||||
| ------- | -------- | -----------
|
|
||||||
| Yes | Yes | No, causes `lobby.info` broadcast
|
|
||||||
|
|
||||||
### Payloads
|
|
||||||
Request Payload: `IJoinLobby`
|
|
||||||
|
|
||||||
Response Payload: `ILobbyInfo` (or `IGameState` if the game is in progress)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## `lobby.players.leave`
|
|
||||||
This allows non-host players to leave the lobby without destroying it entirely.
|
|
||||||
This endpoint errors when the client that created the lobby attempts to use the
|
|
||||||
endpoint.
|
|
||||||
|
|
||||||
### Supported Event Types
|
|
||||||
| Request | Response | Broadcasted
|
|
||||||
| ------- | -------- | -----------
|
|
||||||
| Yes | Yes | No, causes `lobby.info` broadcast
|
|
||||||
|
|
||||||
### Payloads
|
|
||||||
Request Payload: `ILeaveLobby`
|
|
||||||
|
|
||||||
Response Payload: `ServerResponse`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## `lobby.players.update`
|
|
||||||
Allows the player to update their own information, this is primarily used for
|
|
||||||
updating the ship design.
|
|
||||||
|
|
||||||
### Supported Event Types
|
|
||||||
| Request | Response | Broadcasted
|
|
||||||
| ------- | -------- | -----------
|
|
||||||
| Yes | Yes | No, causes `lobby.info` broadcast
|
|
||||||
|
|
||||||
### Payloads
|
|
||||||
Request Payload: `IUpdatePlayer`
|
|
||||||
|
|
||||||
Response Payload: `ServerResponse`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## `game.state`
|
|
||||||
Provides information about the current game state, used to help keep clients in
|
|
||||||
the correct state.
|
|
||||||
|
|
||||||
### Supported Event Types
|
|
||||||
| Request | Response | Broadcasted
|
|
||||||
| ------- | -------- | -----------
|
|
||||||
| No | Yes | Yes
|
|
||||||
|
|
||||||
### Payloads
|
|
||||||
Request Payload: N/A
|
|
||||||
|
|
||||||
Response Payload: `IGameState`
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
# Lobby management
|
|
||||||
Lobby info: `lobby.info`
|
|
||||||
Create lobby: `lobby.create`
|
|
||||||
Delete lobby: `lobby.delete`
|
|
||||||
Join lobby: `lobby.players.join`
|
|
||||||
leave lobby: `lobby.players.leave`
|
|
||||||
kick player from lobby: `lobby.players.leave`
|
|
||||||
change lobby option(s): `lobby.options`
|
|
||||||
update player data (including ship design): `lobby.players.update`
|
|
||||||
|
|
||||||
|
|
||||||
# Informational
|
|
||||||
server info: `server.info`
|
|
||||||
|
|
||||||
|
|
||||||
# In-Game
|
|
||||||
current game state: `game.state`
|
|
||||||
alerting the players who's turn it is: `game.turn`
|
|
||||||
distributing card piles: `game.mining.piles`
|
|
||||||
picking a card pile: `game.mining.choose`
|
|
||||||
|
|
||||||
asking if player wants to e-stop & response: `game.movement.use-estop`
|
|
||||||
|
|
||||||
telling clients to move a ship: `game.movement.ship`
|
|
||||||
|
|
||||||
round end: `game.round.next`
|
|
||||||
game finished: `game.finished` (includes what player(s) won)
|
|
||||||
19
hex.py
|
|
@ -1,19 +0,0 @@
|
||||||
from math import cos, sin, radians
|
|
||||||
|
|
||||||
h = int(input("Total hexagon height allowed: "))
|
|
||||||
canvas_size = int(input("SVG size: "))
|
|
||||||
move_by = abs(canvas_size - h) / 2
|
|
||||||
|
|
||||||
m = h // 2
|
|
||||||
p = {
|
|
||||||
"x": 0,
|
|
||||||
"y": m
|
|
||||||
}
|
|
||||||
|
|
||||||
print("\nPoints: ")
|
|
||||||
for _ in range(6):
|
|
||||||
print(f"{round(p['x'] + m + move_by)},{round(p['y'] + m + move_by)}", end=" ")
|
|
||||||
x, y = p["x"], p["y"]
|
|
||||||
p["x"] = round(x*cos(radians(60)) - y*sin(radians(60)), 5)
|
|
||||||
p["y"] = round(x*sin(radians(60)) + y*cos(radians(60)), 5)
|
|
||||||
print()
|
|
||||||
|
|
@ -1,158 +0,0 @@
|
||||||
[
|
|
||||||
{
|
|
||||||
"magnitude": 1,
|
|
||||||
"symbol": "Ar",
|
|
||||||
"name": "Argon",
|
|
||||||
"type": "movement"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"magnitude": 2,
|
|
||||||
"symbol": "B",
|
|
||||||
"name": "Boron",
|
|
||||||
"type": "movement"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"magnitude": 3,
|
|
||||||
"symbol": "C",
|
|
||||||
"name": "Carbon",
|
|
||||||
"type": "movement"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"magnitude": 5,
|
|
||||||
"symbol": "Dy",
|
|
||||||
"name": "Dysprosium",
|
|
||||||
"type": "movement"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"magnitude": 2,
|
|
||||||
"symbol": "Es",
|
|
||||||
"name": "Einsteinium",
|
|
||||||
"type": "movement"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"magnitude": 6,
|
|
||||||
"symbol": "F",
|
|
||||||
"name": "Fluorine",
|
|
||||||
"type": "movement"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"magnitude": 5,
|
|
||||||
"symbol": "Ga",
|
|
||||||
"name": "Gallium",
|
|
||||||
"type": "movement"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"magnitude": 4,
|
|
||||||
"symbol": "H",
|
|
||||||
"name": "Hydrogen",
|
|
||||||
"type": "movement"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"magnitude": 6,
|
|
||||||
"symbol": "Ir",
|
|
||||||
"name": "Iridium",
|
|
||||||
"type": "movement"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"magnitude": 2,
|
|
||||||
"symbol": "Jo",
|
|
||||||
"name": "Jodium",
|
|
||||||
"type": "stationary"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"magnitude": -2,
|
|
||||||
"symbol": "Kr",
|
|
||||||
"name": "Krypton",
|
|
||||||
"type": "movement"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"magnitude": 4,
|
|
||||||
"symbol": "Li",
|
|
||||||
"name": "Lithium",
|
|
||||||
"type": "movement"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"magnitude": 10,
|
|
||||||
"symbol": "Mg",
|
|
||||||
"name": "Magnesium",
|
|
||||||
"type": "movement"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"magnitude": -6,
|
|
||||||
"symbol": "Ne",
|
|
||||||
"name": "Neon",
|
|
||||||
"type": "movement"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"magnitude": 7,
|
|
||||||
"symbol": "O",
|
|
||||||
"name": "Oxygen",
|
|
||||||
"type": "movement"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"magnitude": 5,
|
|
||||||
"symbol": "Pu",
|
|
||||||
"name": "Plutonium",
|
|
||||||
"type": "movement"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"magnitude": 3,
|
|
||||||
"symbol": "Qt",
|
|
||||||
"name": "Sydnium",
|
|
||||||
"type": "stationary"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"magnitude": 9,
|
|
||||||
"symbol": "Ra",
|
|
||||||
"name": "Radium",
|
|
||||||
"type": "movement"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"magnitude": 9,
|
|
||||||
"symbol": "Si",
|
|
||||||
"name": "Silicon",
|
|
||||||
"type": "movement"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"magnitude": 2,
|
|
||||||
"symbol": "Th",
|
|
||||||
"name": "Thorium",
|
|
||||||
"type": "movement"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"magnitude": -5,
|
|
||||||
"symbol": "U",
|
|
||||||
"name": "Uranium",
|
|
||||||
"type": "movement"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"magnitude": 7,
|
|
||||||
"symbol": "V",
|
|
||||||
"name": "Vanadium",
|
|
||||||
"type": "movement"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"magnitude": 8,
|
|
||||||
"symbol": "W",
|
|
||||||
"name": "Tungsten",
|
|
||||||
"type": "movement"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"magnitude": -3,
|
|
||||||
"symbol": "Xe",
|
|
||||||
"name": "Xenon",
|
|
||||||
"type": "movement"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"magnitude": 8,
|
|
||||||
"symbol": "Y",
|
|
||||||
"name": "Yttrium",
|
|
||||||
"type": "movement"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"magnitude": 7,
|
|
||||||
"symbol": "Zr",
|
|
||||||
"name": "Zirconium",
|
|
||||||
"type": "movement"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
This is a list of all events that the server must support in order at the bare
|
|
||||||
minimum for the front-end to work with getting all the data that it needs.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
`get.game` (incoming)
|
|
||||||
Get's a game's current information, this includes player list, and options
|
|
||||||
|
|
||||||
`game.info` (outgoing)
|
|
||||||
The game data that was requested.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
`delete.game` (incoming)
|
|
||||||
Deletes a game from the system, kicking all the players from the lobby.
|
|
||||||
|
|
||||||
`game.deleted` (outgoing)
|
|
||||||
Alert for all the players that the game got deleted and to reset all state.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
`get.system.colours` (incoming)
|
|
||||||
Retrieves a list of all colours that are currently supported for players to pick
|
|
||||||
from for their spaceship.
|
|
||||||
|
|
||||||
`get.system.icons` (incoming)
|
|
||||||
Retrieves a list of all the supported icons that players can pick from for their
|
|
||||||
spaceship.
|
|
||||||
|
|
||||||
`system.colours` (outgoing)
|
|
||||||
The list of all colours that the players can pick from.
|
|
||||||
|
|
||||||
`system.icons` (outgoing)
|
|
||||||
The list of all the icons that players can pick from.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
`put.player.design` (incoming)
|
|
||||||
Updates a player's design that will be used in the game for their spaceship.
|
|
||||||
|
|
||||||
`game.player.update` (outgoing)
|
|
||||||
Tells everyone in the game that one of the players has updated something about
|
|
||||||
their data and to refresh the local data to keep it up to date.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
`put.game.option` (incoming)
|
|
||||||
Updates the game's options that affect how the game flow works.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
.PHONY: build dev prod test
|
|
||||||
|
|
||||||
build:
|
|
||||||
tsc
|
|
||||||
|
|
||||||
dev: build
|
|
||||||
NODE_ENV=development node dist/main.js
|
|
||||||
|
|
||||||
prod: build
|
|
||||||
NODE_ENV=production node dist/main.js
|
|
||||||
|
|
||||||
rund:
|
|
||||||
NODE_ENV=development node dist/main.js
|
|
||||||
|
|
||||||
run:
|
|
||||||
NODE_ENV=production node dist/main.js
|
|
||||||
|
|
||||||
test:
|
|
||||||
node_modules/mocha/bin/_mocha -r ts-node/register tests/**/*.spec.ts
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
{
|
|
||||||
"name": "gravwell-online-server",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "",
|
|
||||||
"main": "dist/main.js",
|
|
||||||
"scripts": {
|
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
|
||||||
"build": "tsc",
|
|
||||||
"start": "node dist/main.js"
|
|
||||||
},
|
|
||||||
"author": "Oliver Akins",
|
|
||||||
"license": "UNLICENSED",
|
|
||||||
"dependencies": {
|
|
||||||
"common": "link:../common",
|
|
||||||
"glob": "^7.2.0",
|
|
||||||
"joi": "^17.6.0",
|
|
||||||
"module-alias": "^2.2.2",
|
|
||||||
"socket.io": "^4.4.0",
|
|
||||||
"toml": "^3.0.0",
|
|
||||||
"tslog": "^3.3.1",
|
|
||||||
"uuid": "^8.3.2"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/chai": "^4.3.1",
|
|
||||||
"@types/glob": "^7.2.0",
|
|
||||||
"@types/mocha": "^9.1.1",
|
|
||||||
"@types/module-alias": "^2.0.1",
|
|
||||||
"@types/node": "^18.0.0",
|
|
||||||
"@types/uuid": "^8.3.4",
|
|
||||||
"chai": "^4.3.6",
|
|
||||||
"mocha": "^10.0.0",
|
|
||||||
"ts-node": "^10.8.1",
|
|
||||||
"typescript": "^4.7.4"
|
|
||||||
},
|
|
||||||
"_moduleAliases": {
|
|
||||||
"@": "./dist"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
962
server/pnpm-lock.yaml
generated
|
|
@ -1,962 +0,0 @@
|
||||||
lockfileVersion: 5.4
|
|
||||||
|
|
||||||
specifiers:
|
|
||||||
'@types/chai': ^4.3.1
|
|
||||||
'@types/glob': ^7.2.0
|
|
||||||
'@types/mocha': ^9.1.1
|
|
||||||
'@types/module-alias': ^2.0.1
|
|
||||||
'@types/node': ^18.0.0
|
|
||||||
'@types/uuid': ^8.3.4
|
|
||||||
chai: ^4.3.6
|
|
||||||
common: link:../common
|
|
||||||
glob: ^7.2.0
|
|
||||||
joi: ^17.6.0
|
|
||||||
mocha: ^10.0.0
|
|
||||||
module-alias: ^2.2.2
|
|
||||||
socket.io: ^4.4.0
|
|
||||||
toml: ^3.0.0
|
|
||||||
ts-node: ^10.8.1
|
|
||||||
tslog: ^3.3.1
|
|
||||||
typescript: ^4.7.4
|
|
||||||
uuid: ^8.3.2
|
|
||||||
|
|
||||||
dependencies:
|
|
||||||
common: link:../common/cjs
|
|
||||||
glob: 7.2.0
|
|
||||||
joi: 17.6.0
|
|
||||||
module-alias: 2.2.2
|
|
||||||
socket.io: 4.4.0
|
|
||||||
toml: 3.0.0
|
|
||||||
tslog: 3.3.1
|
|
||||||
uuid: 8.3.2
|
|
||||||
|
|
||||||
devDependencies:
|
|
||||||
'@types/chai': 4.3.1
|
|
||||||
'@types/glob': 7.2.0
|
|
||||||
'@types/mocha': 9.1.1
|
|
||||||
'@types/module-alias': 2.0.1
|
|
||||||
'@types/node': 18.0.0
|
|
||||||
'@types/uuid': 8.3.4
|
|
||||||
chai: 4.3.6
|
|
||||||
mocha: 10.0.0
|
|
||||||
ts-node: 10.8.1_qiyc72axg2v44xl4yovan2v55u
|
|
||||||
typescript: 4.7.4
|
|
||||||
|
|
||||||
packages:
|
|
||||||
|
|
||||||
/@cspotcode/source-map-support/0.8.1:
|
|
||||||
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
|
|
||||||
engines: {node: '>=12'}
|
|
||||||
dependencies:
|
|
||||||
'@jridgewell/trace-mapping': 0.3.9
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@hapi/hoek/9.3.0:
|
|
||||||
resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@hapi/topo/5.1.0:
|
|
||||||
resolution: {integrity: sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==}
|
|
||||||
dependencies:
|
|
||||||
'@hapi/hoek': 9.3.0
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@jridgewell/resolve-uri/3.0.7:
|
|
||||||
resolution: {integrity: sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==}
|
|
||||||
engines: {node: '>=6.0.0'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@jridgewell/sourcemap-codec/1.4.13:
|
|
||||||
resolution: {integrity: sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@jridgewell/trace-mapping/0.3.9:
|
|
||||||
resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==}
|
|
||||||
dependencies:
|
|
||||||
'@jridgewell/resolve-uri': 3.0.7
|
|
||||||
'@jridgewell/sourcemap-codec': 1.4.13
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@sideway/address/4.1.4:
|
|
||||||
resolution: {integrity: sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==}
|
|
||||||
dependencies:
|
|
||||||
'@hapi/hoek': 9.3.0
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@sideway/formula/3.0.0:
|
|
||||||
resolution: {integrity: sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@sideway/pinpoint/2.0.0:
|
|
||||||
resolution: {integrity: sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@tsconfig/node10/1.0.9:
|
|
||||||
resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@tsconfig/node12/1.0.11:
|
|
||||||
resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@tsconfig/node14/1.0.3:
|
|
||||||
resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@tsconfig/node16/1.0.3:
|
|
||||||
resolution: {integrity: sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@types/chai/4.3.1:
|
|
||||||
resolution: {integrity: sha512-/zPMqDkzSZ8t3VtxOa4KPq7uzzW978M9Tvh+j7GHKuo6k6GTLxPJ4J5gE5cjfJ26pnXst0N5Hax8Sr0T2Mi9zQ==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@types/component-emitter/1.2.11:
|
|
||||||
resolution: {integrity: sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@types/cookie/0.4.1:
|
|
||||||
resolution: {integrity: sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@types/cors/2.8.12:
|
|
||||||
resolution: {integrity: sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@types/glob/7.2.0:
|
|
||||||
resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==}
|
|
||||||
dependencies:
|
|
||||||
'@types/minimatch': 3.0.5
|
|
||||||
'@types/node': 18.0.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@types/minimatch/3.0.5:
|
|
||||||
resolution: {integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@types/mocha/9.1.1:
|
|
||||||
resolution: {integrity: sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@types/module-alias/2.0.1:
|
|
||||||
resolution: {integrity: sha512-DN/CCT1HQG6HquBNJdLkvV+4v5l/oEuwOHUPLxI+Eub0NED+lk0YUfba04WGH90EINiUrNgClkNnwGmbICeWMQ==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@types/node/18.0.0:
|
|
||||||
resolution: {integrity: sha512-cHlGmko4gWLVI27cGJntjs/Sj8th9aYwplmZFwmmgYQQvL5NUsgVJG7OddLvNfLqYS31KFN0s3qlaD9qCaxACA==}
|
|
||||||
|
|
||||||
/@types/uuid/8.3.4:
|
|
||||||
resolution: {integrity: sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@ungap/promise-all-settled/1.1.2:
|
|
||||||
resolution: {integrity: sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/accepts/1.3.7:
|
|
||||||
resolution: {integrity: sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==}
|
|
||||||
engines: {node: '>= 0.6'}
|
|
||||||
dependencies:
|
|
||||||
mime-types: 2.1.34
|
|
||||||
negotiator: 0.6.2
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/acorn-walk/8.2.0:
|
|
||||||
resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==}
|
|
||||||
engines: {node: '>=0.4.0'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/acorn/8.7.1:
|
|
||||||
resolution: {integrity: sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==}
|
|
||||||
engines: {node: '>=0.4.0'}
|
|
||||||
hasBin: true
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/ansi-colors/4.1.1:
|
|
||||||
resolution: {integrity: sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==}
|
|
||||||
engines: {node: '>=6'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/ansi-regex/5.0.1:
|
|
||||||
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/ansi-styles/4.3.0:
|
|
||||||
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
dependencies:
|
|
||||||
color-convert: 2.0.1
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/anymatch/3.1.2:
|
|
||||||
resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==}
|
|
||||||
engines: {node: '>= 8'}
|
|
||||||
dependencies:
|
|
||||||
normalize-path: 3.0.0
|
|
||||||
picomatch: 2.3.1
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/arg/4.1.3:
|
|
||||||
resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/argparse/2.0.1:
|
|
||||||
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/assertion-error/1.1.0:
|
|
||||||
resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/balanced-match/1.0.2:
|
|
||||||
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
|
|
||||||
|
|
||||||
/base64-arraybuffer/1.0.1:
|
|
||||||
resolution: {integrity: sha512-vFIUq7FdLtjZMhATwDul5RZWv2jpXQ09Pd6jcVEOvIsqCWTRFD/ONHNfyOS8dA/Ippi5dsIgpyKWKZaAKZltbA==}
|
|
||||||
engines: {node: '>= 0.6.0'}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/base64id/2.0.0:
|
|
||||||
resolution: {integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==}
|
|
||||||
engines: {node: ^4.5.0 || >= 5.9}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/binary-extensions/2.2.0:
|
|
||||||
resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/brace-expansion/1.1.11:
|
|
||||||
resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
|
|
||||||
dependencies:
|
|
||||||
balanced-match: 1.0.2
|
|
||||||
concat-map: 0.0.1
|
|
||||||
|
|
||||||
/brace-expansion/2.0.1:
|
|
||||||
resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
|
|
||||||
dependencies:
|
|
||||||
balanced-match: 1.0.2
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/braces/3.0.2:
|
|
||||||
resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
dependencies:
|
|
||||||
fill-range: 7.0.1
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/browser-stdout/1.3.1:
|
|
||||||
resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/buffer-from/1.1.2:
|
|
||||||
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/camelcase/6.3.0:
|
|
||||||
resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/chai/4.3.6:
|
|
||||||
resolution: {integrity: sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==}
|
|
||||||
engines: {node: '>=4'}
|
|
||||||
dependencies:
|
|
||||||
assertion-error: 1.1.0
|
|
||||||
check-error: 1.0.2
|
|
||||||
deep-eql: 3.0.1
|
|
||||||
get-func-name: 2.0.0
|
|
||||||
loupe: 2.3.4
|
|
||||||
pathval: 1.1.1
|
|
||||||
type-detect: 4.0.8
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/chalk/4.1.2:
|
|
||||||
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dependencies:
|
|
||||||
ansi-styles: 4.3.0
|
|
||||||
supports-color: 7.2.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/check-error/1.0.2:
|
|
||||||
resolution: {integrity: sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/chokidar/3.5.3:
|
|
||||||
resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
|
|
||||||
engines: {node: '>= 8.10.0'}
|
|
||||||
dependencies:
|
|
||||||
anymatch: 3.1.2
|
|
||||||
braces: 3.0.2
|
|
||||||
glob-parent: 5.1.2
|
|
||||||
is-binary-path: 2.1.0
|
|
||||||
is-glob: 4.0.3
|
|
||||||
normalize-path: 3.0.0
|
|
||||||
readdirp: 3.6.0
|
|
||||||
optionalDependencies:
|
|
||||||
fsevents: 2.3.2
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/cliui/7.0.4:
|
|
||||||
resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==}
|
|
||||||
dependencies:
|
|
||||||
string-width: 4.2.3
|
|
||||||
strip-ansi: 6.0.1
|
|
||||||
wrap-ansi: 7.0.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/color-convert/2.0.1:
|
|
||||||
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
|
|
||||||
engines: {node: '>=7.0.0'}
|
|
||||||
dependencies:
|
|
||||||
color-name: 1.1.4
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/color-name/1.1.4:
|
|
||||||
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/component-emitter/1.3.0:
|
|
||||||
resolution: {integrity: sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/concat-map/0.0.1:
|
|
||||||
resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=}
|
|
||||||
|
|
||||||
/cookie/0.4.1:
|
|
||||||
resolution: {integrity: sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==}
|
|
||||||
engines: {node: '>= 0.6'}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/cors/2.8.5:
|
|
||||||
resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==}
|
|
||||||
engines: {node: '>= 0.10'}
|
|
||||||
dependencies:
|
|
||||||
object-assign: 4.1.1
|
|
||||||
vary: 1.1.2
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/create-require/1.1.1:
|
|
||||||
resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/debug/4.3.3:
|
|
||||||
resolution: {integrity: sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==}
|
|
||||||
engines: {node: '>=6.0'}
|
|
||||||
peerDependencies:
|
|
||||||
supports-color: '*'
|
|
||||||
peerDependenciesMeta:
|
|
||||||
supports-color:
|
|
||||||
optional: true
|
|
||||||
dependencies:
|
|
||||||
ms: 2.1.2
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/debug/4.3.4_supports-color@8.1.1:
|
|
||||||
resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
|
|
||||||
engines: {node: '>=6.0'}
|
|
||||||
peerDependencies:
|
|
||||||
supports-color: '*'
|
|
||||||
peerDependenciesMeta:
|
|
||||||
supports-color:
|
|
||||||
optional: true
|
|
||||||
dependencies:
|
|
||||||
ms: 2.1.2
|
|
||||||
supports-color: 8.1.1
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/decamelize/4.0.0:
|
|
||||||
resolution: {integrity: sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/deep-eql/3.0.1:
|
|
||||||
resolution: {integrity: sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==}
|
|
||||||
engines: {node: '>=0.12'}
|
|
||||||
dependencies:
|
|
||||||
type-detect: 4.0.8
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/diff/4.0.2:
|
|
||||||
resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==}
|
|
||||||
engines: {node: '>=0.3.1'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/diff/5.0.0:
|
|
||||||
resolution: {integrity: sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==}
|
|
||||||
engines: {node: '>=0.3.1'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/emoji-regex/8.0.0:
|
|
||||||
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/engine.io-parser/5.0.2:
|
|
||||||
resolution: {integrity: sha512-wuiO7qO/OEkPJSFueuATIXtrxF7/6GTbAO9QLv7nnbjwZ5tYhLm9zxvLwxstRs0dcT0KUlWTjtIOs1T86jt12g==}
|
|
||||||
engines: {node: '>=10.0.0'}
|
|
||||||
dependencies:
|
|
||||||
base64-arraybuffer: 1.0.1
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/engine.io/6.1.0:
|
|
||||||
resolution: {integrity: sha512-ErhZOVu2xweCjEfYcTdkCnEYUiZgkAcBBAhW4jbIvNG8SLU3orAqoJCiytZjYF7eTpVmmCrLDjLIEaPlUAs1uw==}
|
|
||||||
engines: {node: '>=10.0.0'}
|
|
||||||
dependencies:
|
|
||||||
'@types/cookie': 0.4.1
|
|
||||||
'@types/cors': 2.8.12
|
|
||||||
'@types/node': 18.0.0
|
|
||||||
accepts: 1.3.7
|
|
||||||
base64id: 2.0.0
|
|
||||||
cookie: 0.4.1
|
|
||||||
cors: 2.8.5
|
|
||||||
debug: 4.3.3
|
|
||||||
engine.io-parser: 5.0.2
|
|
||||||
ws: 8.2.3
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- bufferutil
|
|
||||||
- supports-color
|
|
||||||
- utf-8-validate
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/escalade/3.1.1:
|
|
||||||
resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==}
|
|
||||||
engines: {node: '>=6'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/escape-string-regexp/4.0.0:
|
|
||||||
resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/fill-range/7.0.1:
|
|
||||||
resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
dependencies:
|
|
||||||
to-regex-range: 5.0.1
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/find-up/5.0.0:
|
|
||||||
resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dependencies:
|
|
||||||
locate-path: 6.0.0
|
|
||||||
path-exists: 4.0.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/flat/5.0.2:
|
|
||||||
resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==}
|
|
||||||
hasBin: true
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/fs.realpath/1.0.0:
|
|
||||||
resolution: {integrity: sha1-FQStJSMVjKpA20onh8sBQRmU6k8=}
|
|
||||||
|
|
||||||
/fsevents/2.3.2:
|
|
||||||
resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
|
|
||||||
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
|
|
||||||
os: [darwin]
|
|
||||||
requiresBuild: true
|
|
||||||
dev: true
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
/get-caller-file/2.0.5:
|
|
||||||
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
|
|
||||||
engines: {node: 6.* || 8.* || >= 10.*}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/get-func-name/2.0.0:
|
|
||||||
resolution: {integrity: sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/glob-parent/5.1.2:
|
|
||||||
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
|
|
||||||
engines: {node: '>= 6'}
|
|
||||||
dependencies:
|
|
||||||
is-glob: 4.0.3
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/glob/7.2.0:
|
|
||||||
resolution: {integrity: sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==}
|
|
||||||
dependencies:
|
|
||||||
fs.realpath: 1.0.0
|
|
||||||
inflight: 1.0.6
|
|
||||||
inherits: 2.0.4
|
|
||||||
minimatch: 3.0.4
|
|
||||||
once: 1.4.0
|
|
||||||
path-is-absolute: 1.0.1
|
|
||||||
|
|
||||||
/has-flag/4.0.0:
|
|
||||||
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/he/1.2.0:
|
|
||||||
resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==}
|
|
||||||
hasBin: true
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/inflight/1.0.6:
|
|
||||||
resolution: {integrity: sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=}
|
|
||||||
dependencies:
|
|
||||||
once: 1.4.0
|
|
||||||
wrappy: 1.0.2
|
|
||||||
|
|
||||||
/inherits/2.0.4:
|
|
||||||
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
|
|
||||||
|
|
||||||
/is-binary-path/2.1.0:
|
|
||||||
resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
dependencies:
|
|
||||||
binary-extensions: 2.2.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/is-extglob/2.1.1:
|
|
||||||
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
|
|
||||||
engines: {node: '>=0.10.0'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/is-fullwidth-code-point/3.0.0:
|
|
||||||
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/is-glob/4.0.3:
|
|
||||||
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
|
|
||||||
engines: {node: '>=0.10.0'}
|
|
||||||
dependencies:
|
|
||||||
is-extglob: 2.1.1
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/is-number/7.0.0:
|
|
||||||
resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
|
|
||||||
engines: {node: '>=0.12.0'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/is-plain-obj/2.1.0:
|
|
||||||
resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/is-unicode-supported/0.1.0:
|
|
||||||
resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/joi/17.6.0:
|
|
||||||
resolution: {integrity: sha512-OX5dG6DTbcr/kbMFj0KGYxuew69HPcAE3K/sZpEV2nP6e/j/C0HV+HNiBPCASxdx5T7DMoa0s8UeHWMnb6n2zw==}
|
|
||||||
dependencies:
|
|
||||||
'@hapi/hoek': 9.3.0
|
|
||||||
'@hapi/topo': 5.1.0
|
|
||||||
'@sideway/address': 4.1.4
|
|
||||||
'@sideway/formula': 3.0.0
|
|
||||||
'@sideway/pinpoint': 2.0.0
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/js-yaml/4.1.0:
|
|
||||||
resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
|
|
||||||
hasBin: true
|
|
||||||
dependencies:
|
|
||||||
argparse: 2.0.1
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/locate-path/6.0.0:
|
|
||||||
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dependencies:
|
|
||||||
p-locate: 5.0.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/log-symbols/4.1.0:
|
|
||||||
resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dependencies:
|
|
||||||
chalk: 4.1.2
|
|
||||||
is-unicode-supported: 0.1.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/loupe/2.3.4:
|
|
||||||
resolution: {integrity: sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==}
|
|
||||||
dependencies:
|
|
||||||
get-func-name: 2.0.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/make-error/1.3.6:
|
|
||||||
resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/mime-db/1.51.0:
|
|
||||||
resolution: {integrity: sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==}
|
|
||||||
engines: {node: '>= 0.6'}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/mime-types/2.1.34:
|
|
||||||
resolution: {integrity: sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==}
|
|
||||||
engines: {node: '>= 0.6'}
|
|
||||||
dependencies:
|
|
||||||
mime-db: 1.51.0
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/minimatch/3.0.4:
|
|
||||||
resolution: {integrity: sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==}
|
|
||||||
dependencies:
|
|
||||||
brace-expansion: 1.1.11
|
|
||||||
|
|
||||||
/minimatch/5.0.1:
|
|
||||||
resolution: {integrity: sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dependencies:
|
|
||||||
brace-expansion: 2.0.1
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/mocha/10.0.0:
|
|
||||||
resolution: {integrity: sha512-0Wl+elVUD43Y0BqPZBzZt8Tnkw9CMUdNYnUsTfOM1vuhJVZL+kiesFYsqwBkEEuEixaiPe5ZQdqDgX2jddhmoA==}
|
|
||||||
engines: {node: '>= 14.0.0'}
|
|
||||||
hasBin: true
|
|
||||||
dependencies:
|
|
||||||
'@ungap/promise-all-settled': 1.1.2
|
|
||||||
ansi-colors: 4.1.1
|
|
||||||
browser-stdout: 1.3.1
|
|
||||||
chokidar: 3.5.3
|
|
||||||
debug: 4.3.4_supports-color@8.1.1
|
|
||||||
diff: 5.0.0
|
|
||||||
escape-string-regexp: 4.0.0
|
|
||||||
find-up: 5.0.0
|
|
||||||
glob: 7.2.0
|
|
||||||
he: 1.2.0
|
|
||||||
js-yaml: 4.1.0
|
|
||||||
log-symbols: 4.1.0
|
|
||||||
minimatch: 5.0.1
|
|
||||||
ms: 2.1.3
|
|
||||||
nanoid: 3.3.3
|
|
||||||
serialize-javascript: 6.0.0
|
|
||||||
strip-json-comments: 3.1.1
|
|
||||||
supports-color: 8.1.1
|
|
||||||
workerpool: 6.2.1
|
|
||||||
yargs: 16.2.0
|
|
||||||
yargs-parser: 20.2.4
|
|
||||||
yargs-unparser: 2.0.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/module-alias/2.2.2:
|
|
||||||
resolution: {integrity: sha512-A/78XjoX2EmNvppVWEhM2oGk3x4lLxnkEA4jTbaK97QKSDjkIoOsKQlfylt/d3kKKi596Qy3NP5XrXJ6fZIC9Q==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/ms/2.1.2:
|
|
||||||
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
|
|
||||||
|
|
||||||
/ms/2.1.3:
|
|
||||||
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/nanoid/3.3.3:
|
|
||||||
resolution: {integrity: sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==}
|
|
||||||
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
|
|
||||||
hasBin: true
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/negotiator/0.6.2:
|
|
||||||
resolution: {integrity: sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==}
|
|
||||||
engines: {node: '>= 0.6'}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/normalize-path/3.0.0:
|
|
||||||
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
|
|
||||||
engines: {node: '>=0.10.0'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/object-assign/4.1.1:
|
|
||||||
resolution: {integrity: sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=}
|
|
||||||
engines: {node: '>=0.10.0'}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/once/1.4.0:
|
|
||||||
resolution: {integrity: sha1-WDsap3WWHUsROsF9nFC6753Xa9E=}
|
|
||||||
dependencies:
|
|
||||||
wrappy: 1.0.2
|
|
||||||
|
|
||||||
/p-limit/3.1.0:
|
|
||||||
resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dependencies:
|
|
||||||
yocto-queue: 0.1.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/p-locate/5.0.0:
|
|
||||||
resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dependencies:
|
|
||||||
p-limit: 3.1.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/path-exists/4.0.0:
|
|
||||||
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/path-is-absolute/1.0.1:
|
|
||||||
resolution: {integrity: sha1-F0uSaHNVNP+8es5r9TpanhtcX18=}
|
|
||||||
engines: {node: '>=0.10.0'}
|
|
||||||
|
|
||||||
/pathval/1.1.1:
|
|
||||||
resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/picomatch/2.3.1:
|
|
||||||
resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
|
|
||||||
engines: {node: '>=8.6'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/randombytes/2.1.0:
|
|
||||||
resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==}
|
|
||||||
dependencies:
|
|
||||||
safe-buffer: 5.2.1
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/readdirp/3.6.0:
|
|
||||||
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
|
|
||||||
engines: {node: '>=8.10.0'}
|
|
||||||
dependencies:
|
|
||||||
picomatch: 2.3.1
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/require-directory/2.1.1:
|
|
||||||
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
|
|
||||||
engines: {node: '>=0.10.0'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/safe-buffer/5.2.1:
|
|
||||||
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/serialize-javascript/6.0.0:
|
|
||||||
resolution: {integrity: sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==}
|
|
||||||
dependencies:
|
|
||||||
randombytes: 2.1.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/socket.io-adapter/2.3.3:
|
|
||||||
resolution: {integrity: sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/socket.io-parser/4.0.4:
|
|
||||||
resolution: {integrity: sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==}
|
|
||||||
engines: {node: '>=10.0.0'}
|
|
||||||
dependencies:
|
|
||||||
'@types/component-emitter': 1.2.11
|
|
||||||
component-emitter: 1.3.0
|
|
||||||
debug: 4.3.3
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- supports-color
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/socket.io/4.4.0:
|
|
||||||
resolution: {integrity: sha512-bnpJxswR9ov0Bw6ilhCvO38/1WPtE3eA2dtxi2Iq4/sFebiDJQzgKNYA7AuVVdGW09nrESXd90NbZqtDd9dzRQ==}
|
|
||||||
engines: {node: '>=10.0.0'}
|
|
||||||
dependencies:
|
|
||||||
accepts: 1.3.7
|
|
||||||
base64id: 2.0.0
|
|
||||||
debug: 4.3.3
|
|
||||||
engine.io: 6.1.0
|
|
||||||
socket.io-adapter: 2.3.3
|
|
||||||
socket.io-parser: 4.0.4
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- bufferutil
|
|
||||||
- supports-color
|
|
||||||
- utf-8-validate
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/source-map-support/0.5.21:
|
|
||||||
resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==}
|
|
||||||
dependencies:
|
|
||||||
buffer-from: 1.1.2
|
|
||||||
source-map: 0.6.1
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/source-map/0.6.1:
|
|
||||||
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
|
|
||||||
engines: {node: '>=0.10.0'}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/string-width/4.2.3:
|
|
||||||
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
dependencies:
|
|
||||||
emoji-regex: 8.0.0
|
|
||||||
is-fullwidth-code-point: 3.0.0
|
|
||||||
strip-ansi: 6.0.1
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/strip-ansi/6.0.1:
|
|
||||||
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
dependencies:
|
|
||||||
ansi-regex: 5.0.1
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/strip-json-comments/3.1.1:
|
|
||||||
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/supports-color/7.2.0:
|
|
||||||
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
dependencies:
|
|
||||||
has-flag: 4.0.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/supports-color/8.1.1:
|
|
||||||
resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dependencies:
|
|
||||||
has-flag: 4.0.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/to-regex-range/5.0.1:
|
|
||||||
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
|
|
||||||
engines: {node: '>=8.0'}
|
|
||||||
dependencies:
|
|
||||||
is-number: 7.0.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/toml/3.0.0:
|
|
||||||
resolution: {integrity: sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/ts-node/10.8.1_qiyc72axg2v44xl4yovan2v55u:
|
|
||||||
resolution: {integrity: sha512-Wwsnao4DQoJsN034wePSg5nZiw4YKXf56mPIAeD6wVmiv+RytNSWqc2f3fKvcUoV+Yn2+yocD71VOfQHbmVX4g==}
|
|
||||||
hasBin: true
|
|
||||||
peerDependencies:
|
|
||||||
'@swc/core': '>=1.2.50'
|
|
||||||
'@swc/wasm': '>=1.2.50'
|
|
||||||
'@types/node': '*'
|
|
||||||
typescript: '>=2.7'
|
|
||||||
peerDependenciesMeta:
|
|
||||||
'@swc/core':
|
|
||||||
optional: true
|
|
||||||
'@swc/wasm':
|
|
||||||
optional: true
|
|
||||||
dependencies:
|
|
||||||
'@cspotcode/source-map-support': 0.8.1
|
|
||||||
'@tsconfig/node10': 1.0.9
|
|
||||||
'@tsconfig/node12': 1.0.11
|
|
||||||
'@tsconfig/node14': 1.0.3
|
|
||||||
'@tsconfig/node16': 1.0.3
|
|
||||||
'@types/node': 18.0.0
|
|
||||||
acorn: 8.7.1
|
|
||||||
acorn-walk: 8.2.0
|
|
||||||
arg: 4.1.3
|
|
||||||
create-require: 1.1.1
|
|
||||||
diff: 4.0.2
|
|
||||||
make-error: 1.3.6
|
|
||||||
typescript: 4.7.4
|
|
||||||
v8-compile-cache-lib: 3.0.1
|
|
||||||
yn: 3.1.1
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/tslog/3.3.1:
|
|
||||||
resolution: {integrity: sha512-An3uyXX95uU/X7v5H6G9OKW6ip/gVOpvsERGJ/nR4Or5TP5GwoI9nUjhNWEc8mJOWC7uhPMg2UzkrVDUtadELg==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dependencies:
|
|
||||||
source-map-support: 0.5.21
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/type-detect/4.0.8:
|
|
||||||
resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==}
|
|
||||||
engines: {node: '>=4'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/typescript/4.7.4:
|
|
||||||
resolution: {integrity: sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==}
|
|
||||||
engines: {node: '>=4.2.0'}
|
|
||||||
hasBin: true
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/uuid/8.3.2:
|
|
||||||
resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==}
|
|
||||||
hasBin: true
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/v8-compile-cache-lib/3.0.1:
|
|
||||||
resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/vary/1.1.2:
|
|
||||||
resolution: {integrity: sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=}
|
|
||||||
engines: {node: '>= 0.8'}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/workerpool/6.2.1:
|
|
||||||
resolution: {integrity: sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/wrap-ansi/7.0.0:
|
|
||||||
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dependencies:
|
|
||||||
ansi-styles: 4.3.0
|
|
||||||
string-width: 4.2.3
|
|
||||||
strip-ansi: 6.0.1
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/wrappy/1.0.2:
|
|
||||||
resolution: {integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=}
|
|
||||||
|
|
||||||
/ws/8.2.3:
|
|
||||||
resolution: {integrity: sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==}
|
|
||||||
engines: {node: '>=10.0.0'}
|
|
||||||
peerDependencies:
|
|
||||||
bufferutil: ^4.0.1
|
|
||||||
utf-8-validate: ^5.0.2
|
|
||||||
peerDependenciesMeta:
|
|
||||||
bufferutil:
|
|
||||||
optional: true
|
|
||||||
utf-8-validate:
|
|
||||||
optional: true
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/y18n/5.0.8:
|
|
||||||
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/yargs-parser/20.2.4:
|
|
||||||
resolution: {integrity: sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/yargs-unparser/2.0.0:
|
|
||||||
resolution: {integrity: sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dependencies:
|
|
||||||
camelcase: 6.3.0
|
|
||||||
decamelize: 4.0.0
|
|
||||||
flat: 5.0.2
|
|
||||||
is-plain-obj: 2.1.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/yargs/16.2.0:
|
|
||||||
resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dependencies:
|
|
||||||
cliui: 7.0.4
|
|
||||||
escalade: 3.1.1
|
|
||||||
get-caller-file: 2.0.5
|
|
||||||
require-directory: 2.1.1
|
|
||||||
string-width: 4.2.3
|
|
||||||
y18n: 5.0.8
|
|
||||||
yargs-parser: 20.2.4
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/yn/3.1.1:
|
|
||||||
resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==}
|
|
||||||
engines: {node: '>=6'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/yocto-queue/0.1.0:
|
|
||||||
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dev: true
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
/** The server's current version */
|
|
||||||
export const VERSION = "0.1";
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
import { Status, ICreateLobby, colours, spaceships } from "common";
|
|
||||||
import { WebsocketEvent } from "@/types/WebsocketEvent";
|
|
||||||
import { Player } from "@/objects/Player";
|
|
||||||
import { Game } from "@/objects/Game";
|
|
||||||
import { games } from "@/main";
|
|
||||||
|
|
||||||
const data: WebsocketEvent = {
|
|
||||||
name: "req:lobby.create",
|
|
||||||
handler(_, socket, data: ICreateLobby) {
|
|
||||||
|
|
||||||
// Assert that the user's name conforms to a small subset of unicode to
|
|
||||||
// help prevent weird errors from occuring due to potentially violating
|
|
||||||
// strings and running code through the name entry.
|
|
||||||
if (data.name.match(/[^A-Za-z0-9\_\-]/)) {
|
|
||||||
socket.emit(`res:lobby.create`, {
|
|
||||||
success: Status.BadRequest,
|
|
||||||
message: `Can't use special characters in your name, only A-Z, 0-9, underscores, and dashes are allowed.`,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create the game:
|
|
||||||
let host = new Player(socket, {
|
|
||||||
name: data.name,
|
|
||||||
colour: colours[Math.floor(Math.random() * colours.length)],
|
|
||||||
ship: spaceships[0],
|
|
||||||
host: true,
|
|
||||||
});
|
|
||||||
let game = new Game(host);
|
|
||||||
game.log.info(`New game created by ${data.name}`);
|
|
||||||
|
|
||||||
socket.join(game.id);
|
|
||||||
socket.emit(`res:lobby.create`, {
|
|
||||||
status: Status.Success,
|
|
||||||
game_code: game.id,
|
|
||||||
players: game.players.map(p => p.json()),
|
|
||||||
});
|
|
||||||
|
|
||||||
games.set(game);
|
|
||||||
games.cleanup();
|
|
||||||
},
|
|
||||||
};
|
|
||||||
export default data;
|
|
||||||
|
|
@ -1,91 +0,0 @@
|
||||||
import { colours, IJoinLobby, spaceships, Status } from "common";
|
|
||||||
import { WebsocketEvent } from "@/types/WebsocketEvent";
|
|
||||||
import { Player } from "@/objects/Player";
|
|
||||||
import { games, log } from "@/main";
|
|
||||||
|
|
||||||
const data: WebsocketEvent = {
|
|
||||||
name: "req:lobby.players.join",
|
|
||||||
handler(_, socket, data: IJoinLobby) {
|
|
||||||
try {
|
|
||||||
log.debug(`Attempting to join a game`);
|
|
||||||
|
|
||||||
let gID = data.game_code;
|
|
||||||
let name = data.name;
|
|
||||||
|
|
||||||
let game = games.get(gID);
|
|
||||||
|
|
||||||
|
|
||||||
// Make sure the lobby exists that the player is attempting to connect to
|
|
||||||
if (!game) {
|
|
||||||
socket.emit(`res:lobby.players.join`, {
|
|
||||||
status: Status.NotFound,
|
|
||||||
message: `Game could not be found with that game code`,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Player name unique-ness check
|
|
||||||
let sameName = game.players.find(p => p.name == name);
|
|
||||||
if (sameName) {
|
|
||||||
socket.emit(`res:lobby.players.join`, {
|
|
||||||
status: Status.Forbidden,
|
|
||||||
message: `That name is already taken in the lobby, choose another name!`,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Make sure the player isn't trying to join a game part-way through
|
|
||||||
if (game.status !== `lobby`) {
|
|
||||||
socket.emit(`res:lobby.players.join`, {
|
|
||||||
status: Status.Forbidden,
|
|
||||||
message: `Can't join a game that is in-progress.`,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Lobby is full already
|
|
||||||
if (game.players.length >= 4) {
|
|
||||||
socket.emit(`res:lobby.players.join`, {
|
|
||||||
status: Status.Forbidden,
|
|
||||||
message: `Can't join a game that has all 4 spots taken already.`,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
let usedColours = game.players.map(p => p.colour);
|
|
||||||
let newPlayerColour = null;
|
|
||||||
do {
|
|
||||||
newPlayerColour = colours[Math.floor(Math.random() * colours.length)];
|
|
||||||
} while (usedColours.includes(newPlayerColour));
|
|
||||||
|
|
||||||
let player = new Player(socket, {
|
|
||||||
name,
|
|
||||||
colour: newPlayerColour,
|
|
||||||
ship: spaceships[0],
|
|
||||||
host: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
game.players.push(player);
|
|
||||||
game.log.info(`${name} joined the game`);
|
|
||||||
socket.join(game.id);
|
|
||||||
|
|
||||||
let playerData = game.players.map(p => p.json());
|
|
||||||
socket.emit(`res:lobby.players.join`, {
|
|
||||||
status: Status.Success,
|
|
||||||
game_code: game.id,
|
|
||||||
players: playerData,
|
|
||||||
});
|
|
||||||
socket.to(game.id).emit(`res:lobby.info`, {
|
|
||||||
status: Status.Success,
|
|
||||||
players: playerData,
|
|
||||||
});
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
socket.emit(`res:error`, {
|
|
||||||
status: Status.UnknownError,
|
|
||||||
message: err.message,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
||||||
export default data;
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
import { WebsocketEvent } from "@/types/WebsocketEvent";
|
|
||||||
import { log } from "@/main";
|
|
||||||
|
|
||||||
const data: WebsocketEvent = {
|
|
||||||
name: "req:ping",
|
|
||||||
handler(_, socket) {
|
|
||||||
log.debug(`Server is being pinged`);
|
|
||||||
socket.emit(`res:ping`);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
export default data;
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
import { WebsocketEvent } from "@/types/WebsocketEvent";
|
|
||||||
import { VERSION } from "@/constants";
|
|
||||||
import { games, log } from "@/main";
|
|
||||||
import { Status } from "common";
|
|
||||||
|
|
||||||
const data: WebsocketEvent = {
|
|
||||||
name: "req:server.info",
|
|
||||||
handler(_, socket) {
|
|
||||||
log.debug(`Getting server information`)
|
|
||||||
|
|
||||||
socket.emit(
|
|
||||||
`res:server.info`,
|
|
||||||
{
|
|
||||||
status: Status.Success,
|
|
||||||
version: VERSION,
|
|
||||||
game_count: games.count,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
export default data;
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
// Filepath alias resolution
|
|
||||||
import "module-alias/register";
|
|
||||||
|
|
||||||
import startWebsocketServer from "./websocket";
|
|
||||||
import { loadConfig } from "./utils/config";
|
|
||||||
import { GameDB } from "./objects/GameDB";
|
|
||||||
import { Logger } from "tslog";
|
|
||||||
|
|
||||||
export const config: IConfig = loadConfig();
|
|
||||||
|
|
||||||
// Define the logger
|
|
||||||
export const log = new Logger({
|
|
||||||
displayFilePath: "hidden",
|
|
||||||
displayFunctionName: false,
|
|
||||||
displayDateTime: true,
|
|
||||||
displayLoggerName: false,
|
|
||||||
displayLogLevel: true,
|
|
||||||
minLevel: config.log.level,
|
|
||||||
});
|
|
||||||
|
|
||||||
export const games = new GameDB();
|
|
||||||
|
|
||||||
startWebsocketServer();
|
|
||||||
|
|
@ -1,72 +0,0 @@
|
||||||
export class Deck<T> {
|
|
||||||
private _discard: T[];
|
|
||||||
private _unknown: T[];
|
|
||||||
private _deck: T[];
|
|
||||||
|
|
||||||
|
|
||||||
constructor(cards: T[]) {
|
|
||||||
this._deck = cards;
|
|
||||||
this._discard = [];
|
|
||||||
this._unknown = [];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
get size(): number { return this._deck.length; }
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Draws X cards from the deck
|
|
||||||
*
|
|
||||||
* @param quantity The number of cards to draw
|
|
||||||
* @throws Error If quantity is <= 0
|
|
||||||
* @throws Error If quantity > size
|
|
||||||
*/
|
|
||||||
public draw(quantity: number): T[] {
|
|
||||||
if (quantity <= 0) {
|
|
||||||
throw new Error(`Cannot get ${quantity} cards.`);
|
|
||||||
} else if (quantity > this.size) {
|
|
||||||
throw new Error(`Cannot draw more cards than there are in the deck.`);
|
|
||||||
};
|
|
||||||
|
|
||||||
let cards: T[] = [];
|
|
||||||
|
|
||||||
// Draw the cards for the player and move them into the unknown group
|
|
||||||
for (var i = 0; i < quantity; i++) {
|
|
||||||
|
|
||||||
// Determine the card for the player(s)
|
|
||||||
let index = Math.floor(Math.random() * this.size);
|
|
||||||
let card = this._deck[index];
|
|
||||||
|
|
||||||
// Move it from the arrays
|
|
||||||
cards.push(card);
|
|
||||||
this._deck.splice(index, 1);
|
|
||||||
this._unknown.push(card);
|
|
||||||
};
|
|
||||||
|
|
||||||
return cards;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds the specific card to the discard pile
|
|
||||||
*
|
|
||||||
* @param card The card to add to the discard pile
|
|
||||||
*/
|
|
||||||
public discard(card: T) {
|
|
||||||
if (!this._unknown.includes(card)) {
|
|
||||||
throw new Error("Cannot discard a card that doesn't exist in the deck");
|
|
||||||
};
|
|
||||||
this._unknown = this._unknown.filter(x => x != card);
|
|
||||||
this._discard.push(card);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resets all of the cards in the deck and puts them back in the draw pile
|
|
||||||
*/
|
|
||||||
public reset() {
|
|
||||||
this._deck.push(...this._discard, ...this._unknown);
|
|
||||||
this._discard = [];
|
|
||||||
this._unknown = [];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
@ -1,115 +0,0 @@
|
||||||
import { determineDirection, FuelCard } from "common";
|
|
||||||
import { config, games, log } from "@/main";
|
|
||||||
import { promises as fs } from "fs";
|
|
||||||
import { Player } from "./Player";
|
|
||||||
import { Logger } from "tslog";
|
|
||||||
import { Deck } from "./Deck";
|
|
||||||
import path from "path";
|
|
||||||
|
|
||||||
export class Game {
|
|
||||||
readonly id: string;
|
|
||||||
readonly host: Player;
|
|
||||||
|
|
||||||
readonly log: Logger;
|
|
||||||
|
|
||||||
private _status: string;
|
|
||||||
private _players: Player[];
|
|
||||||
private _deck: Deck<FuelCard>;
|
|
||||||
private board: (Player|null)[];
|
|
||||||
|
|
||||||
|
|
||||||
constructor(host: Player) {
|
|
||||||
|
|
||||||
this._status = `lobby`;
|
|
||||||
|
|
||||||
// Setup the board
|
|
||||||
this.board = new Array(55).fill(null);
|
|
||||||
this.board[26] = null;
|
|
||||||
this.board[36] = null;
|
|
||||||
|
|
||||||
// Init the player data
|
|
||||||
this.host = host;
|
|
||||||
this._players = [ host ];
|
|
||||||
|
|
||||||
// Instantiate the deck
|
|
||||||
this.loadDeck();
|
|
||||||
|
|
||||||
this.id = Game.generateID(config.game.code_length);
|
|
||||||
|
|
||||||
this.log = log.getChildLogger({
|
|
||||||
name: this.id,
|
|
||||||
displayLoggerName: true,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads the deck from the data file which contains an array of card
|
|
||||||
* definitions.
|
|
||||||
*/
|
|
||||||
private async loadDeck() {
|
|
||||||
if (config.game.fuel_deck.type == "file:json") {
|
|
||||||
let cards = JSON.parse(
|
|
||||||
await fs.readFile(
|
|
||||||
path.join(process.cwd(), config.game.fuel_deck.location),
|
|
||||||
`utf-8`
|
|
||||||
)
|
|
||||||
);
|
|
||||||
this._deck = new Deck(cards);
|
|
||||||
} else {
|
|
||||||
throw new Error(`Unsupported data format for the cards: "${config.game.fuel_deck.type}"`)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/** The current status of the game */
|
|
||||||
get status() { return this._status; }
|
|
||||||
|
|
||||||
/** The deck of the fuel cards */
|
|
||||||
get deck() { return this._deck; };
|
|
||||||
|
|
||||||
/** A list players of in the game */
|
|
||||||
get players() { return this._players; };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The algorithm to determine which direction the closest ship is, this
|
|
||||||
* uses an integer that can be multiplied by the player's fuel card
|
|
||||||
* magnitude in order to determine the delta for the board index.
|
|
||||||
*
|
|
||||||
* ---
|
|
||||||
*
|
|
||||||
* Possible Return Values:
|
|
||||||
* - `-1` = Away from the Warp Gate (towards the black hole)
|
|
||||||
* - `0` = Not moving
|
|
||||||
* - `1` = Towards the Warp Gate (away from the black hole)
|
|
||||||
*/
|
|
||||||
public movementDirection(player: Player): number {
|
|
||||||
let location = this.board.indexOf(player);
|
|
||||||
this.log.debug(`Calculating movement direction for ${player.name}`);
|
|
||||||
return determineDirection(this.board, location);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a game code with the given length
|
|
||||||
*
|
|
||||||
* @param length The length of the code to generate
|
|
||||||
*/
|
|
||||||
public static generateID(length: number): string {
|
|
||||||
let code: string;
|
|
||||||
|
|
||||||
// Prevent erroneous codes from being generated
|
|
||||||
if (length <= 0) {
|
|
||||||
throw new Error("Can't code have a length <= 0");
|
|
||||||
};
|
|
||||||
|
|
||||||
// Generate a new code until we find one that isn't taken already.
|
|
||||||
do {
|
|
||||||
code = ``;
|
|
||||||
|
|
||||||
for (var i = 0; i < length; i++) {
|
|
||||||
code += Math.floor(Math.random() * 9);
|
|
||||||
};
|
|
||||||
} while (games.has(code));
|
|
||||||
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
import { Game } from "./Game";
|
|
||||||
|
|
||||||
export class GameDB {
|
|
||||||
private games: {[index: string]: Game};
|
|
||||||
|
|
||||||
constructor () {
|
|
||||||
this.games = {};
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Determines if a game exists with the provided ID */
|
|
||||||
public has(id: string): boolean {
|
|
||||||
return this.games[id] != null;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Get's the Game object associated with the provided ID */
|
|
||||||
public get(id: string): Game|undefined {
|
|
||||||
return this.games[id];
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Adds a Game object into the database */
|
|
||||||
public set(game: Game): void {
|
|
||||||
this.games[game.id] = game;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This removes all inactive games from the system, this includes any games
|
|
||||||
* that do not have any currently connected players and are in the lobby
|
|
||||||
* state. This will not remove any games that are currently in-progress so
|
|
||||||
* that players can resume the game later if they happened to all get
|
|
||||||
* disconnected for some reason.
|
|
||||||
*/
|
|
||||||
public cleanup(): void {};
|
|
||||||
|
|
||||||
/** Returns a count of how many games currently exist in the database */
|
|
||||||
public get count() {
|
|
||||||
return Object.keys(this.games).length;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
import { PlayerData, IColour, ISpaceship } from "common";
|
|
||||||
import { Socket } from "socket.io";
|
|
||||||
|
|
||||||
export class Player {
|
|
||||||
readonly name: string;
|
|
||||||
|
|
||||||
// The player's design
|
|
||||||
public ship: ISpaceship;
|
|
||||||
public colour: IColour;
|
|
||||||
|
|
||||||
public readonly host: boolean;
|
|
||||||
|
|
||||||
constructor(socket: Socket, data: PlayerData) {
|
|
||||||
this.name = data.name;
|
|
||||||
this._socket = socket
|
|
||||||
this.ship = data.ship;
|
|
||||||
this.colour = data.colour;
|
|
||||||
this.host = data.host;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// The player's socket data
|
|
||||||
private _socket: Socket;
|
|
||||||
|
|
||||||
/** The socket that can be used to communicate directly with the player */
|
|
||||||
get socket() { return this._socket };
|
|
||||||
set socket(value: Socket) {
|
|
||||||
if (!this._socket?.connected) {
|
|
||||||
this._socket = value;
|
|
||||||
} else {
|
|
||||||
throw Error("Cannot overwrite a player's socket that is connected.");
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/** The properties of the Player object without any of the methods. */
|
|
||||||
public json() {
|
|
||||||
return {
|
|
||||||
name: this.name,
|
|
||||||
ship: this.ship,
|
|
||||||
colour: this.colour,
|
|
||||||
host: this.host,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
18
server/src/types/Config.d.ts
vendored
|
|
@ -1,18 +0,0 @@
|
||||||
interface IConfig {
|
|
||||||
game: {
|
|
||||||
code_length: number;
|
|
||||||
fuel_deck: {
|
|
||||||
type: "file:json" /* | "file:csv" | "web:json" | "web:csv" */;
|
|
||||||
location: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
server: {
|
|
||||||
port: number;
|
|
||||||
cors: {
|
|
||||||
origins: string[];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
log: {
|
|
||||||
level: "silly" | "trace" | "debug" | "info" | "warn" | "error" | "fatal";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
6
server/src/types/WebsocketEvent.d.ts
vendored
|
|
@ -1,6 +0,0 @@
|
||||||
import { Server, Socket } from "socket.io";
|
|
||||||
|
|
||||||
export interface WebsocketEvent {
|
|
||||||
name: string;
|
|
||||||
handler: (io: Server, socket: Socket, data: any) => any;
|
|
||||||
}
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
import { readFileSync } from "fs";
|
|
||||||
import toml from "toml";
|
|
||||||
import Joi from "joi";
|
|
||||||
|
|
||||||
const schema = Joi.object({
|
|
||||||
game: Joi.object({
|
|
||||||
code_length: Joi.number().integer().positive(),
|
|
||||||
fuel_deck: Joi.object({
|
|
||||||
type: Joi
|
|
||||||
.string()
|
|
||||||
.allow(
|
|
||||||
`file:json`,
|
|
||||||
// `file:csv`,
|
|
||||||
// `web:json`,
|
|
||||||
// `web:csv`
|
|
||||||
)
|
|
||||||
.required(),
|
|
||||||
location: Joi
|
|
||||||
.string()
|
|
||||||
.required(),
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
server: Joi.object({
|
|
||||||
port: Joi
|
|
||||||
.number()
|
|
||||||
.port()
|
|
||||||
.required(),
|
|
||||||
cors: Joi.object({
|
|
||||||
origins: Joi
|
|
||||||
.array()
|
|
||||||
.items(Joi.string()),
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
log: Joi.object({
|
|
||||||
level: Joi
|
|
||||||
.string()
|
|
||||||
.allow(
|
|
||||||
`silly`,
|
|
||||||
`trace`,
|
|
||||||
`debug`,
|
|
||||||
`info`,
|
|
||||||
`warn`,
|
|
||||||
`error`,
|
|
||||||
`fatal`
|
|
||||||
)
|
|
||||||
.optional()
|
|
||||||
.default(`info`),
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
export function loadConfig(): IConfig {
|
|
||||||
const data = toml.parse(readFileSync("config.toml", "utf-8"));
|
|
||||||
const { value, error } = schema.validate(data, {
|
|
||||||
abortEarly: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
console.error(error);
|
|
||||||
process.exit(1);
|
|
||||||
};
|
|
||||||
return value;
|
|
||||||
};
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
import { log, config } from "./main";
|
|
||||||
import { Server } from "socket.io";
|
|
||||||
|
|
||||||
// Event imports
|
|
||||||
import Ping from "./events/ping";
|
|
||||||
import ServerInfo from "./events/server_info";
|
|
||||||
import CreateLobby from "./events/lobby/create";
|
|
||||||
import JoinLobby from "./events/lobby/players/join";
|
|
||||||
|
|
||||||
export default async function() {
|
|
||||||
log.info("Starting socket.io server...");
|
|
||||||
|
|
||||||
const io = new Server();
|
|
||||||
|
|
||||||
io.on("connection", (socket) => {
|
|
||||||
log.silly(`Socket connected with ID: ${socket.id}`);
|
|
||||||
|
|
||||||
// Metadata Events
|
|
||||||
socket.on(Ping.name, (data) => Ping.handler(io, socket, data));
|
|
||||||
socket.on(ServerInfo.name, (data) => ServerInfo.handler(io, socket, data));
|
|
||||||
|
|
||||||
// Lobby Management Events
|
|
||||||
socket.on(CreateLobby.name, (data) => CreateLobby.handler(io, socket, data));
|
|
||||||
socket.on(JoinLobby.name, (data) => JoinLobby.handler(io, socket, data));
|
|
||||||
});
|
|
||||||
|
|
||||||
io.listen(config.server.port, {
|
|
||||||
cors: {
|
|
||||||
origin: config.server.cors.origins,
|
|
||||||
credentials: true,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
@ -1,126 +0,0 @@
|
||||||
import { expect } from "chai";
|
|
||||||
import "mocha";
|
|
||||||
|
|
||||||
import { Deck } from "../../src/objects/Deck";
|
|
||||||
|
|
||||||
describe("The Deck object", () => {
|
|
||||||
var drawSuccess = false;
|
|
||||||
|
|
||||||
|
|
||||||
it("should construct properly with strings", () => {
|
|
||||||
let d = new Deck<string>(["1", "2", "3", "4", "5"]);
|
|
||||||
expect(d.size).to.equal(5);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should construct properly with objects", () => {
|
|
||||||
let d = new Deck<any>([
|
|
||||||
{}, {}, {}, {}, {}
|
|
||||||
]);
|
|
||||||
expect(d.size).to.equal(5);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should draw a single card from the deck properly", () => {
|
|
||||||
let d = new Deck<string>(["1", "2", "3", "4", "5"]);
|
|
||||||
let c = d.draw(1);
|
|
||||||
expect(d.size).to.equal(4);
|
|
||||||
expect(c).to.have.length(1);
|
|
||||||
expect(c[0]).to.be.a("string");
|
|
||||||
expect(c[0]).to.be.oneOf(["1", "2", "3", "4", "5"]);
|
|
||||||
drawSuccess = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should draw multiple cards from the deck properly", () => {
|
|
||||||
let d = new Deck<string>(["1", "2", "3", "4", "5"]);
|
|
||||||
let draws = 2;
|
|
||||||
let c = d.draw(draws);
|
|
||||||
expect(d.size).to.equal(3);
|
|
||||||
expect(c).to.have.length(draws);
|
|
||||||
for (var i = 0; i < draws; i++) {
|
|
||||||
expect(c[i]).to.be.a("string");
|
|
||||||
expect(c[i]).to.be.oneOf(["1", "2", "3", "4", "5"]);
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should draw all of the cards from the deck properly", () => {
|
|
||||||
let d = new Deck<string>(["1", "2", "3", "4", "5"]);
|
|
||||||
let draws = 5;
|
|
||||||
let c = d.draw(draws);
|
|
||||||
expect(d.size).to.equal(0);
|
|
||||||
expect(c).to.have.length(draws);
|
|
||||||
for (var i = 0; i < draws; i++) {
|
|
||||||
expect(c[i]).to.be.a("string");
|
|
||||||
expect(c[i]).to.be.oneOf(["1", "2", "3", "4", "5"]);
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should throw an error when -1 cards are drawn", () => {
|
|
||||||
let d = new Deck<string>(["1", "2", "3", "4", "5"]);
|
|
||||||
try {
|
|
||||||
d.draw(-1);
|
|
||||||
throw "draw() didn't error with -1 given";
|
|
||||||
} catch (e) {};
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should throw an error when -5 cards are drawn", () => {
|
|
||||||
let d = new Deck<string>(["1", "2", "3", "4", "5"]);
|
|
||||||
try {
|
|
||||||
d.draw(-5);
|
|
||||||
throw "draw() didn't error with -5 given";
|
|
||||||
} catch (e) {};
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should throw an error when n+1 cards were requested", () => {
|
|
||||||
let d = new Deck<string>(["1", "2", "3", "4", "5"]);
|
|
||||||
try {
|
|
||||||
d.draw(6);
|
|
||||||
throw "Draw didn't error with 6 given";
|
|
||||||
} catch (e) {};
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should throw an error when n+5 cards were requested", () => {
|
|
||||||
let d = new Deck<string>(["1", "2", "3", "4", "5"]);
|
|
||||||
try {
|
|
||||||
d.draw(10);
|
|
||||||
throw "Draw didn't error with 10 given";
|
|
||||||
} catch (e) {};
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should error when discarding something that isn't a card in the deck", function (this: Mocha.Context) {
|
|
||||||
if (!drawSuccess) { this.skip() };
|
|
||||||
|
|
||||||
let d = new Deck<string>(["1", "2", "3", "4", "5"]);
|
|
||||||
d.draw(1);
|
|
||||||
|
|
||||||
try {
|
|
||||||
d.discard("potato");
|
|
||||||
throw "Didn't error when discarding an invalid card"
|
|
||||||
} catch (_) {};
|
|
||||||
});
|
|
||||||
|
|
||||||
it("shouldn't error when discarding a valid card", function (this: Mocha.Context) {
|
|
||||||
if (!drawSuccess) { this.skip() };
|
|
||||||
|
|
||||||
const d = new Deck<string>(["1", "2", "3", "4", "5"]);
|
|
||||||
const c = d.draw(1)[0];
|
|
||||||
d.discard(c);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should reset count when card is in unknown domain", function (this: Mocha.Context) {
|
|
||||||
if (!drawSuccess) { this.skip() };
|
|
||||||
|
|
||||||
const d = new Deck<string>(["1", "2", "3", "4", "5"]);
|
|
||||||
d.draw(1);
|
|
||||||
d.reset();
|
|
||||||
expect(d.size).to.equal(5);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should reset count when card is in discard", function (this: Mocha.Context) {
|
|
||||||
if (!drawSuccess) { this.skip() };
|
|
||||||
|
|
||||||
const d = new Deck<string>(["1", "2", "3", "4", "5"]);
|
|
||||||
const c = d.draw(1)[0];
|
|
||||||
d.discard(c);
|
|
||||||
d.reset();
|
|
||||||
expect(d.size).to.equal(5);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
@ -1,82 +0,0 @@
|
||||||
import { Socket } from "socket.io";
|
|
||||||
import { expect } from "chai";
|
|
||||||
import "mocha";
|
|
||||||
|
|
||||||
import { Player } from "../../src/objects/Player";
|
|
||||||
import { colours, spaceships } from "common";
|
|
||||||
|
|
||||||
describe("The player object", () => {
|
|
||||||
it("should construct properly", () => {
|
|
||||||
const data = {
|
|
||||||
name: "Oliver",
|
|
||||||
ship: spaceships[0],
|
|
||||||
colour: colours[0],
|
|
||||||
host: false,
|
|
||||||
}
|
|
||||||
const p = new Player(
|
|
||||||
{ connected: true } as Socket,
|
|
||||||
data
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(p.socket.connected).to.be.true;
|
|
||||||
expect(p.colour).to.equal(data.colour);
|
|
||||||
expect(p.ship).to.equal(data.ship);
|
|
||||||
expect(p.name).to.equal(data.name);
|
|
||||||
expect(p.host).to.equal(data.host);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("shouldn't let socket be assigned when connected", () => {
|
|
||||||
const p = new Player(
|
|
||||||
{ connected: true } as Socket,
|
|
||||||
{
|
|
||||||
name: "Oliver",
|
|
||||||
ship: spaceships[0],
|
|
||||||
colour: colours[0],
|
|
||||||
host: false,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
try {
|
|
||||||
p.socket = { connected : true } as Socket;
|
|
||||||
throw "Assigned socket when it was connected"
|
|
||||||
} catch (e) {};
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should let socket be assigned when not connected", () => {
|
|
||||||
const p = new Player(
|
|
||||||
{ connected: false } as Socket,
|
|
||||||
{
|
|
||||||
name: "Oliver",
|
|
||||||
ship: spaceships[0],
|
|
||||||
colour: colours[0],
|
|
||||||
host: false,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
try {
|
|
||||||
p.socket = { connected : true } as Socket;
|
|
||||||
} catch (e) {
|
|
||||||
throw "Didn't let socket be set when it wasn't connected"
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should construct the data object correctly", () => {
|
|
||||||
let data = {
|
|
||||||
name: "Oliver",
|
|
||||||
ship: spaceships[0],
|
|
||||||
colour: colours[0],
|
|
||||||
host: false,
|
|
||||||
};
|
|
||||||
const p = new Player(
|
|
||||||
{ connected: false } as Socket,
|
|
||||||
data
|
|
||||||
);
|
|
||||||
|
|
||||||
let j = p.json();
|
|
||||||
expect(j).to.have.keys(`name`, `ship`, `colour`, `host`);
|
|
||||||
expect(j.colour).to.equal(data.colour);
|
|
||||||
expect(j.ship).to.equal(data.ship);
|
|
||||||
expect(j.name).to.equal(data.name);
|
|
||||||
expect(j.host).to.equal(data.host);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
@ -1,79 +0,0 @@
|
||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
/* Visit https://aka.ms/tsconfig.json to read more about this file */
|
|
||||||
|
|
||||||
/* Basic Options */
|
|
||||||
// "incremental": true, /* Enable incremental compilation */
|
|
||||||
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', 'ES2021', or 'ESNEXT'. */
|
|
||||||
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
|
|
||||||
// "lib": [], /* Specify library files to be included in the compilation. */
|
|
||||||
// "allowJs": true, /* Allow javascript files to be compiled. */
|
|
||||||
// "checkJs": true, /* Report errors in .js files. */
|
|
||||||
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */
|
|
||||||
// "declaration": true, /* Generates corresponding '.d.ts' file. */
|
|
||||||
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
|
||||||
"sourceMap": true, /* Generates corresponding '.map' file. */
|
|
||||||
// "outFile": "./", /* Concatenate and emit output to single file. */
|
|
||||||
"outDir": "./dist", /* Redirect output structure to the directory. */
|
|
||||||
"rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
|
||||||
// "composite": true, /* Enable project compilation */
|
|
||||||
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
|
|
||||||
"removeComments": true, /* Do not emit comments to output. */
|
|
||||||
// "noEmit": true, /* Do not emit outputs. */
|
|
||||||
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
|
|
||||||
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
|
||||||
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
|
||||||
|
|
||||||
/* Strict Type-Checking Options */
|
|
||||||
// "strict": true, /* Enable all strict type-checking options. */
|
|
||||||
"noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
|
|
||||||
"strictNullChecks": true, /* Enable strict null checks. */
|
|
||||||
"strictFunctionTypes": true, /* Enable strict checking of function types. */
|
|
||||||
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
|
|
||||||
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
|
|
||||||
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
|
|
||||||
"alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
|
|
||||||
|
|
||||||
/* Additional Checks */
|
|
||||||
"noUnusedLocals": true, /* Report errors on unused locals. */
|
|
||||||
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
|
||||||
"noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
|
||||||
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
|
||||||
// "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
|
|
||||||
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an 'override' modifier. */
|
|
||||||
// "noPropertyAccessFromIndexSignature": true, /* Require undeclared properties from index signatures to use element accesses. */
|
|
||||||
|
|
||||||
/* Module Resolution Options */
|
|
||||||
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
|
||||||
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
|
|
||||||
"paths": {
|
|
||||||
"@/*": ["./src/*"]
|
|
||||||
}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
|
||||||
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
|
||||||
// "typeRoots": [], /* List of folders to include type definitions from. */
|
|
||||||
// "types": [], /* Type declaration files to be included in compilation. */
|
|
||||||
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
|
||||||
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
|
||||||
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
|
||||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
|
||||||
|
|
||||||
/* Source Map Options */
|
|
||||||
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
|
|
||||||
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
|
||||||
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
|
|
||||||
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
|
|
||||||
|
|
||||||
/* Experimental Options */
|
|
||||||
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
|
||||||
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
|
|
||||||
|
|
||||||
/* Advanced Options */
|
|
||||||
"skipLibCheck": true, /* Skip type checking of declaration files. */
|
|
||||||
"forceConsistentCasingInFileNames": true, /* Disallow inconsistently-cased references to the same file. */
|
|
||||||
|
|
||||||
"stripInternal": true
|
|
||||||
},
|
|
||||||
"exclude": [
|
|
||||||
"**/*.spec.ts"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
21
setup.sh
|
|
@ -1,21 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Build the common module that both subsystems depend on
|
|
||||||
cd common
|
|
||||||
make
|
|
||||||
|
|
||||||
|
|
||||||
# Setup the server side of the system
|
|
||||||
cd ../server
|
|
||||||
pnpm install
|
|
||||||
pnpm build
|
|
||||||
#pnpm link file:../common/cjs
|
|
||||||
# add command to copy the systemd service file to the right location
|
|
||||||
|
|
||||||
|
|
||||||
# Setup the website for the system
|
|
||||||
cd ../web-svelte
|
|
||||||
pnpm install
|
|
||||||
#pnpm link file:../common/cjs
|
|
||||||
pnpm build
|
|
||||||
# add command to help setup nginx to serve the built files
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
Space Shuttle Icon:
|
|
||||||
https://fontawesome.com/v5.15/icons/space-shuttle
|
|
||||||
License: https://fontawesome.com/license
|
|
||||||
Changes: Recolouring
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<link rel="icon" href="/favicon.ico" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
||||||
<title>Gravwell Online</title>
|
|
||||||
<link rel="stylesheet" href="/global.css">
|
|
||||||
<style>
|
|
||||||
@import url("https://fonts.googleapis.com/css2?family=Orbitron:wght@600&display=swap");
|
|
||||||
@import url("https://fonts.googleapis.com/icon?family=Material+Icons");
|
|
||||||
|
|
||||||
body {
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
font-family: 'Orbitron', sans-serif;
|
|
||||||
width: 100vw;
|
|
||||||
height: 100vh;
|
|
||||||
/* overflow: hidden; */
|
|
||||||
background:
|
|
||||||
radial-gradient(50% 75% at 50% 50%, #000000 35%, rgba(0, 0, 0, 0.171) 125%),
|
|
||||||
linear-gradient(335deg, #870051 15%, rgba(0, 0, 0, 0) 45%),
|
|
||||||
linear-gradient(225deg, #008505 15%, rgba(0, 0, 0, 0) 50%),
|
|
||||||
linear-gradient(170deg, #17A9A9 10%, rgba(0, 0, 0, 0) 50%),
|
|
||||||
linear-gradient(45deg, #070055 25%, rgba(0, 0, 0, 0) 50%),
|
|
||||||
black;
|
|
||||||
}
|
|
||||||
|
|
||||||
#app {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="app"></div>
|
|
||||||
<script type="module" src="/src/main.ts"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
{
|
|
||||||
"name": "web-svelte",
|
|
||||||
"version": "0.0.0",
|
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
|
||||||
"dev": "vite",
|
|
||||||
"build": "vite build",
|
|
||||||
"preview": "vite preview",
|
|
||||||
"check": "svelte-check --tsconfig ./tsconfig.json"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@sveltejs/vite-plugin-svelte": "^1.0.0-next.30",
|
|
||||||
"@tsconfig/svelte": "^2.0.1",
|
|
||||||
"svelte": "^3.49.0",
|
|
||||||
"svelte-check": "^2.2.7",
|
|
||||||
"svelte-preprocess": "^4.9.8",
|
|
||||||
"tslib": "^2.3.1",
|
|
||||||
"typescript": "^4.4.4",
|
|
||||||
"vite": "^3.0.2"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"sass": "^1.45.0",
|
|
||||||
"socket.io-client": "^4.4.0",
|
|
||||||
"svelte-particles": "^2.1.3",
|
|
||||||
"tsparticles": "^2.1.3"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
1232
web-svelte/pnpm-lock.yaml
generated
|
|
@ -1 +0,0 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2" viewBox="0 0 370 331"><circle cx="232.83" cy="218.38" r="49.85" transform="translate(-132.67 -132.45) scale(1.36436)"/><path d="M185 59.19c58.67 0 106.3 47.63 106.3 106.3S243.68 271.82 185 271.82 78.69 224.17 78.69 165.5 126.33 59.19 185 59.19Zm0 24.45c45.18 0 81.86 36.68 81.86 81.86s-36.68 81.86-81.86 81.86a81.9 81.9 0 0 1-81.86-81.86A81.9 81.9 0 0 1 185 83.64Z"/><path d="M184.52 325.88c88.57 0 160.38-71.8 160.38-160.38 0-53.53-26.23-100.94-66.53-130.07a159.66 159.66 0 0 0-93.85-30.31v38.49c67.31 0 121.89 54.57 121.89 121.89s-54.58 121.89-121.9 121.89v38.5Z"/><path d="M278.37 35.43s14.94 7.23 11.28-10.04c-6.92-32.57 45.14-29.43 52.12 108.4 9.43 186.36-63.4-98.36-63.4-98.36ZM185.49 5.12C96.9 5.12 25.1 76.92 25.1 165.5c0 53.53 26.23 100.94 66.53 130.07a159.65 159.65 0 0 0 93.85 30.31V287.4c-67.31 0-121.89-54.57-121.89-121.89S118.17 43.61 185.5 43.61V5.12Z"/><path d="M91.63 295.57s-14.94-7.23-11.27 10.04c6.9 32.57-45.14 29.43-52.12-108.4-9.44-186.36 63.4 98.36 63.4 98.36Z"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.1 KiB |
|
|
@ -1,3 +0,0 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 100 100">
|
|
||||||
<circle cx="50" cy="50" r="45" stroke="white" strokeWidth="2" fill="black" />
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 170 B |
|
|
@ -1,4 +0,0 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 100 100">
|
|
||||||
<polygon fill="white" points="50,100 7,75 7,25 50,0 93,25 93,75" />
|
|
||||||
<polygon fill="black" points="50,98 8,74 8,26 50,2 92,26 92,74" />
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 227 B |
|
|
@ -1 +0,0 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M12 3a9 9 0 0 0 0 18 1.5 1.5 0 0 0 1.11-2.51A1.5 1.5 0 0 1 14.23 16H16a5 5 0 0 0 5-5c0-4.42-4.03-8-9-8zm-5.5 9a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm3-4a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm5 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm3 4a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3z"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 388 B |
|
|
@ -1 +0,0 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="72" height="72" fill="none" viewBox="0 0 24 24"><path fill="#221b38" fill-rule="evenodd" d="M22.7 1.3a1 1 0 0 1 0 1.4l-6 6a1 1 0 1 1-1.4-1.4l6-6a1 1 0 0 1 1.4 0Z" clip-rule="evenodd"/><path fill="#221b38" fill-rule="evenodd" d="M16 2a1 1 0 0 1 1-1h5a1 1 0 0 1 1 1v5a1 1 0 1 1-2 0V3h-4a1 1 0 0 1-1-1ZM1.3 1.3a1 1 0 0 1 1.4 0l6 6a1 1 0 0 1-1.4 1.4l-6-6a1 1 0 0 1 0-1.4Z" clip-rule="evenodd"/><path fill="#221b38" fill-rule="evenodd" d="M1 2a1 1 0 0 1 1-1h5a1 1 0 0 1 0 2H3v4a1 1 0 0 1-2 0V2ZM8.7 15.3a1 1 0 0 1 0 1.4l-6 6a1 1 0 0 1-1.4-1.4l6-6a1 1 0 0 1 1.4 0Z" clip-rule="evenodd"/><path fill="#221b38" fill-rule="evenodd" d="M2 16a1 1 0 0 1 1 1v4h4a1 1 0 1 1 0 2H2a1 1 0 0 1-1-1v-5a1 1 0 0 1 1-1ZM15.3 15.3a1 1 0 0 1 1.4 0l6 6a1 1 0 0 1-1.4 1.4l-6-6a1 1 0 0 1 0-1.4Z" clip-rule="evenodd"/><path fill="#221b38" fill-rule="evenodd" d="M22 16a1 1 0 0 1 1 1v5a1 1 0 0 1-1 1h-5a1 1 0 1 1 0-2h4v-4a1 1 0 0 1 1-1Z" clip-rule="evenodd"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 982 B |
|
|
@ -1 +0,0 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M14 8a4 4 0 1 0-8 0 4 4 0 0 0 8 0zm3 2v2h6v-2h-6zM2 18v2h16v-2c0-2.66-5.33-4-8-4s-8 1.34-8 4z"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 211 B |
|
|
@ -1 +0,0 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewBox="0 0 640 512"><path fill="currentColor" d="M592.6 208.24C559.73 192.84 515.78 184 472 184H186.33c-4.96-6.55-10.59-11.98-16.72-16H376C229.16 137.75 219.4 32 96 32v128H80V32c-26.51 0-48 28.65-48 64v64c-23.2 0-32 10.03-32 24v40c0 13.98 8.82 24 32 24v16c-23.2 0-32 10.03-32 24v40c0 13.98 8.82 24 32 24v64c0 35.35 21.49 64 48 64V352h16v128c123.4 0 133.16-105.75 280-136H169.6c6.14-4.02 11.77-9.45 16.73-16H472c43.78 0 87.73-8.84 120.6-24.24C622.28 289.85 640 271.99 640 256s-17.72-33.84-47.4-47.76zM488 296a8 8 0 0 1-8-8v-64a8 8 0 0 1 8-8c31.9 0 31.94 80 0 80z"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 631 B |
|
|
@ -1 +0,0 @@
|
||||||
<svg viewBox="0 0 106 112" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2"><path d="M1.812 41.775c-7.559 28.21 9.182 57.206 37.392 64.764 17.048 4.568 34.384.262 47.102-10.088a52.64 52.64 0 0 0 17.663-27.304L91.71 65.863c-5.745 21.44-27.782 34.162-49.221 28.417C21.049 88.536 8.326 66.5 14.07 45.06L1.812 41.774Z"/><path d="M86.306 96.45s-3.577 4.143 2.237 4.45c10.96.577 5.52 16.887-38.973 7.347-60.155-12.898 36.736-11.796 36.736-11.796Zm17.58-26.994c7.559-28.21-9.182-57.206-37.392-64.765C49.446.123 32.11 4.43 19.393 14.78A52.64 52.64 0 0 0 1.73 42.083l12.258 3.285C19.733 23.928 41.77 11.205 63.21 16.95c21.439 5.745 34.162 27.782 28.417 49.221l12.26 3.285Z"/><path d="M19.393 14.78s3.577-4.142-2.237-4.449c-10.961-.577-5.52-16.887 38.972-7.348C116.283 15.881 19.393 14.78 19.393 14.78Z"/><path d="M52.695 108.277c29.081 0 52.657-23.575 52.657-52.657 0-17.575-8.61-33.14-21.843-42.705a52.419 52.419 0 0 0-30.814-9.952V15.6c22.102 0 40.02 17.918 40.02 40.02 0 22.102-17.918 40.02-40.02 40.02v12.637Z"/><path d="M83.509 12.915s4.906 2.373 3.702-3.298c-2.27-10.691 14.82-9.662 17.112 35.592 3.098 61.185-20.814-32.294-20.814-32.294ZM53.013 2.963C23.93 2.963.355 26.538.355 55.62c0 17.575 8.61 33.14 21.844 42.705a52.419 52.419 0 0 0 30.814 9.952V95.64c-22.103 0-40.02-17.918-40.02-40.02 0-22.102 17.917-40.02 40.02-40.02V2.963Z"/><path d="M22.198 98.325s-4.906-2.373-3.702 3.298c2.27 10.691-14.82 9.662-17.112-35.592-3.098-61.185 20.814 32.294 20.814 32.294Z"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.5 KiB |
|
|
@ -1 +0,0 @@
|
||||||
<svg viewBox="0 0 176 172" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2"><path d="M26.2 142.809 0 109.954l17.367-76.091L87.685 0l70.318 33.863 17.367 76.091-26.201 32.855 8.739 28.746H17.461l8.739-28.746ZM87.685 7.49l59.222 28.52 14.626 64.083-40.982 51.391H54.819l-40.983-51.391L28.463 36.01 87.685 7.49Z"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 410 B |
|
|
@ -1,22 +0,0 @@
|
||||||
:root {
|
|
||||||
--dark-but-not-black: #2c2f33;
|
|
||||||
--not-quite-black: #23272a;
|
|
||||||
}
|
|
||||||
|
|
||||||
.clickable {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.material-icons {
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.error {
|
|
||||||
padding: 10px;
|
|
||||||
background: #ff000033;
|
|
||||||
border-radius: 10px;
|
|
||||||
border-style: solid;
|
|
||||||
border-color: red;
|
|
||||||
border-width: 2px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
@ -1,110 +0,0 @@
|
||||||
{
|
|
||||||
"particles": {
|
|
||||||
"number": {
|
|
||||||
"value": 100,
|
|
||||||
"density": {
|
|
||||||
"enable": true,
|
|
||||||
"value_area": 800
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"color": {
|
|
||||||
"value": "#ffffff"
|
|
||||||
},
|
|
||||||
"shape": {
|
|
||||||
"type": "circle",
|
|
||||||
"stroke": {
|
|
||||||
"width": 0,
|
|
||||||
"color": "#000000"
|
|
||||||
},
|
|
||||||
"polygon": {
|
|
||||||
"nb_sides": 5
|
|
||||||
},
|
|
||||||
"image": {
|
|
||||||
"src": "img/github.svg",
|
|
||||||
"width": 100,
|
|
||||||
"height": 100
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"opacity": {
|
|
||||||
"value": 0.5,
|
|
||||||
"random": false,
|
|
||||||
"anim": {
|
|
||||||
"enable": false,
|
|
||||||
"speed": 1,
|
|
||||||
"opacity_min": 0.1,
|
|
||||||
"sync": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"value": 2,
|
|
||||||
"random": true,
|
|
||||||
"anim": {
|
|
||||||
"enable": true,
|
|
||||||
"speed": 4,
|
|
||||||
"size_min": 0.1,
|
|
||||||
"sync": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"line_linked": {
|
|
||||||
"enable": true,
|
|
||||||
"distance": 75,
|
|
||||||
"color": "#ffffff",
|
|
||||||
"opacity": 0.4,
|
|
||||||
"width": 1
|
|
||||||
},
|
|
||||||
"move": {
|
|
||||||
"enable": true,
|
|
||||||
"speed": 0.25,
|
|
||||||
"direction": "none",
|
|
||||||
"random": true,
|
|
||||||
"straight": false,
|
|
||||||
"out_mode": "bounce",
|
|
||||||
"bounce": false,
|
|
||||||
"attract": {
|
|
||||||
"enable": false,
|
|
||||||
"rotateX": 600,
|
|
||||||
"rotateY": 1200
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"interactivity": {
|
|
||||||
"detect_on": "canvas",
|
|
||||||
"events": {
|
|
||||||
"onhover": {
|
|
||||||
"enable": false,
|
|
||||||
"mode": "grab"
|
|
||||||
},
|
|
||||||
"onclick": {
|
|
||||||
"enable": false,
|
|
||||||
"mode": "push"
|
|
||||||
},
|
|
||||||
"resize": true
|
|
||||||
},
|
|
||||||
"modes": {
|
|
||||||
"grab": {
|
|
||||||
"distance": 100,
|
|
||||||
"line_linked": {
|
|
||||||
"opacity": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"bubble": {
|
|
||||||
"distance": 400,
|
|
||||||
"size": 40,
|
|
||||||
"duration": 2,
|
|
||||||
"opacity": 8,
|
|
||||||
"speed": 3
|
|
||||||
},
|
|
||||||
"repulse": {
|
|
||||||
"distance": 200,
|
|
||||||
"duration": 0.4
|
|
||||||
},
|
|
||||||
"push": {
|
|
||||||
"particles_nb": 4
|
|
||||||
},
|
|
||||||
"remove": {
|
|
||||||
"particles_nb": 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"retina_detect": true
|
|
||||||
}
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
<script lang="ts">
|
|
||||||
|
|
||||||
// Library imports
|
|
||||||
import Particles from "svelte-particles";
|
|
||||||
import { loadFull } from "tsparticles";
|
|
||||||
|
|
||||||
// View imports
|
|
||||||
import MultiplayerLobby from "./views/lobby/multiplayer.svelte";
|
|
||||||
import MovementView from "./views/movement.svelte";
|
|
||||||
import Home from "./views/home.svelte";
|
|
||||||
|
|
||||||
// Store imports
|
|
||||||
import { state } from "./stores";
|
|
||||||
|
|
||||||
async function particlesInit(engine: any) {
|
|
||||||
await loadFull(engine);
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<!-- Static particles across all of our pages -->
|
|
||||||
<div id="particles">
|
|
||||||
<Particles url="/particlesConfig.json" {particlesInit} />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- The state the game is in -->
|
|
||||||
{#if $state == "main-menu"}
|
|
||||||
<Home />
|
|
||||||
{:else if $state == "multiplayer-lobby"}
|
|
||||||
<MultiplayerLobby />
|
|
||||||
{:else if $state == "game-movement"}
|
|
||||||
<MovementView />
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
#particles {
|
|
||||||
position: fixed;
|
|
||||||
z-index: -100000;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,182 +0,0 @@
|
||||||
<script lang="ts">
|
|
||||||
import Spaceship from "./icons/spaceship.svelte";
|
|
||||||
import Warpgate from "./icons/warpgate.svelte";
|
|
||||||
import Hexagon from "./Hexagon.svelte";
|
|
||||||
import { players } from "../stores";
|
|
||||||
import type { Board } from "common"
|
|
||||||
|
|
||||||
export let board: Board;
|
|
||||||
</script>
|
|
||||||
|
|
||||||
|
|
||||||
<main class="board">
|
|
||||||
<div class="singularity inner-grid"></div>
|
|
||||||
<div class="side-hex right-down-1 inner-grid">
|
|
||||||
<Hexagon>
|
|
||||||
{#if board[10] != null}
|
|
||||||
<div
|
|
||||||
class="spaceship-icon"
|
|
||||||
style="--colour: {$players[board[10]].colour.hex};"
|
|
||||||
>
|
|
||||||
<Spaceship
|
|
||||||
spaceship="{$players[board[10]].ship.id}"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</Hexagon>
|
|
||||||
</div>
|
|
||||||
<div class="side-hex left-down-1 inner-grid">
|
|
||||||
<Hexagon>
|
|
||||||
{#if board[21] != null}
|
|
||||||
<div
|
|
||||||
class="spaceship-icon"
|
|
||||||
style="--colour: {$players[board[21]].colour.hex};"
|
|
||||||
>
|
|
||||||
<Spaceship
|
|
||||||
spaceship="{$players[board[21]].ship.id}"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</Hexagon>
|
|
||||||
</div>
|
|
||||||
<div class="side-hex right-down-2 inner-grid">
|
|
||||||
<Hexagon>
|
|
||||||
{#if board[32] != null}
|
|
||||||
<div
|
|
||||||
class="spaceship-icon"
|
|
||||||
style="--colour: {$players[board[32]].colour.hex};"
|
|
||||||
>
|
|
||||||
<Spaceship
|
|
||||||
spaceship="{$players[board[32]].ship.id}"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</Hexagon>
|
|
||||||
</div>
|
|
||||||
<div class="side-hex left-down-2 inner-grid">
|
|
||||||
<Hexagon>
|
|
||||||
{#if board[43] != null}
|
|
||||||
<div
|
|
||||||
class="spaceship-icon"
|
|
||||||
style="--colour: {$players[board[43]].colour.hex};"
|
|
||||||
>
|
|
||||||
<Spaceship
|
|
||||||
spaceship="{$players[board[43]].ship.id}"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</Hexagon>
|
|
||||||
</div>
|
|
||||||
<div class="warp-gate inner-grid">
|
|
||||||
<Warpgate></Warpgate>
|
|
||||||
</div>
|
|
||||||
{#each Array(5) as _, row}
|
|
||||||
<div class="main-row {row % 2 == 1 ? `row-reverse` : ``}">
|
|
||||||
{#each Array(10) as _, col}
|
|
||||||
{@const boardIndex = col + (( row * 10 ) + (1 * row))}
|
|
||||||
<div>
|
|
||||||
<Hexagon>
|
|
||||||
{#if board[boardIndex] != null}
|
|
||||||
<div
|
|
||||||
class="spaceship-icon"
|
|
||||||
style="--colour: {$players[board[boardIndex]].colour.hex};"
|
|
||||||
>
|
|
||||||
<Spaceship
|
|
||||||
spaceship="{$players[board[boardIndex]].ship.id}"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</Hexagon>
|
|
||||||
</div>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
{/each}
|
|
||||||
</main>
|
|
||||||
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
main {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
display: grid;
|
|
||||||
grid-template-rows: repeat(5, 20fr);
|
|
||||||
grid-template-columns: 100px 100fr 100px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-row {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-evenly;
|
|
||||||
|
|
||||||
> div {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
height: 95%;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.row-reverse {
|
|
||||||
flex-direction: row-reverse;
|
|
||||||
|
|
||||||
.spaceship-icon {
|
|
||||||
transform: scaleX(-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.inner-grid {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.spaceship-icon {
|
|
||||||
/*
|
|
||||||
Smaller version: 55px
|
|
||||||
Larger version: 75px
|
|
||||||
*/
|
|
||||||
--size: 55px;
|
|
||||||
width: var(--size);
|
|
||||||
height: var(--size);
|
|
||||||
display: flex;
|
|
||||||
color: var(--colour);
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
.side-hex {
|
|
||||||
.spaceship-icon {
|
|
||||||
transform: rotate(90deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.singularity {
|
|
||||||
background-image: url(/assets/black-hole.svg);
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-position: center;
|
|
||||||
grid-column: 1 / 2;
|
|
||||||
grid-row: 1 / 2;
|
|
||||||
}
|
|
||||||
.right-down-1 {
|
|
||||||
grid-column: -1 / -2;
|
|
||||||
grid-row: 1 / 3;
|
|
||||||
}
|
|
||||||
.left-down-1 {
|
|
||||||
grid-column: 1 / 2;
|
|
||||||
grid-row: 2 / 4;
|
|
||||||
}
|
|
||||||
.right-down-2 {
|
|
||||||
grid-column: -1 / -2;
|
|
||||||
grid-row: 3 / 5;
|
|
||||||
}
|
|
||||||
.left-down-2 {
|
|
||||||
grid-column: 1 / 2;
|
|
||||||
grid-row: 4 / 6;
|
|
||||||
}
|
|
||||||
.warp-gate {
|
|
||||||
border-radius: 10px;
|
|
||||||
grid-column: -1 / -2;
|
|
||||||
grid-row: -1 / -2;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,138 +0,0 @@
|
||||||
<script lang="ts">
|
|
||||||
import SciFiButton from "./SciFi-Button.svelte";
|
|
||||||
import { createEventDispatcher } from "svelte";
|
|
||||||
import type { FuelCard } from "common";
|
|
||||||
|
|
||||||
export let hidden: boolean = false;
|
|
||||||
export let button: boolean = true;
|
|
||||||
export let buttonText: string = "Use Fuel Card";
|
|
||||||
export let card: FuelCard;
|
|
||||||
export let half: boolean = false;
|
|
||||||
|
|
||||||
const emit = createEventDispatcher();
|
|
||||||
|
|
||||||
let colour: string;
|
|
||||||
let magnitudeShape = "";
|
|
||||||
if (card.type == "stationary") {
|
|
||||||
colour = `#008A71`;
|
|
||||||
magnitudeShape = `hexagon`;
|
|
||||||
} else {
|
|
||||||
if (card.magnitude < 0) {
|
|
||||||
colour = `#600068`;
|
|
||||||
magnitudeShape = `circle`;
|
|
||||||
} else {
|
|
||||||
colour = `#536800`;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
|
|
||||||
<div
|
|
||||||
class="card {hidden ? 'hidden' : ''} {half ? 'half' : ''}"
|
|
||||||
style="--colour: {colour};"
|
|
||||||
on:mouseenter="{() => emit(`hover`, { card, visible: true })}"
|
|
||||||
on:mouseleave="{() => emit(`hover`, { card, visible: false })}"
|
|
||||||
>
|
|
||||||
{#if !hidden}
|
|
||||||
<div class="magnitude {magnitudeShape}">
|
|
||||||
{Math.abs(card.magnitude)}
|
|
||||||
</div>
|
|
||||||
<div class="main-content">
|
|
||||||
<h1>{card.symbol}</h1>
|
|
||||||
{card.name}
|
|
||||||
</div>
|
|
||||||
{#if button && !half}
|
|
||||||
<div class="button-container">
|
|
||||||
<SciFiButton
|
|
||||||
classes="use-fuel-card-button"
|
|
||||||
textColour="#FFFFFF"
|
|
||||||
hoverTextColour="#FFFFFF"
|
|
||||||
background="rgba(0,0,0,0.6)"
|
|
||||||
>
|
|
||||||
{buttonText}
|
|
||||||
</SciFiButton>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
|
|
||||||
$border-radius: 10px;
|
|
||||||
|
|
||||||
.card {
|
|
||||||
align-items: center;
|
|
||||||
background: var(--colour);
|
|
||||||
border-radius: $border-radius;
|
|
||||||
color: white;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
margin: 10px;
|
|
||||||
min-width: 150px;
|
|
||||||
position: relative;
|
|
||||||
user-select: none;
|
|
||||||
width: calc(100% / 9);
|
|
||||||
|
|
||||||
&.hidden {
|
|
||||||
background: #3D3D3D;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .button-container {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .magnitude {
|
|
||||||
$size: 40px;
|
|
||||||
|
|
||||||
background: rgba(255, 255, 255, 0.3);
|
|
||||||
border-radius: 10px 0 10px 0;
|
|
||||||
color: black;
|
|
||||||
display: flex;
|
|
||||||
left: 0;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
width: $size;
|
|
||||||
height: $size;
|
|
||||||
|
|
||||||
&.hexagon {
|
|
||||||
background-image: url(/assets/hexagon.svg);
|
|
||||||
background-position: center;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-size: 85%;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.circle {
|
|
||||||
background-image: url(/assets/circle.svg);
|
|
||||||
background-position: center;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-size: 85%;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> .main-content {
|
|
||||||
margin-bottom: 30px;
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
text-align: center;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.half {
|
|
||||||
padding-top: 15px;
|
|
||||||
padding-bottom: 15px;
|
|
||||||
|
|
||||||
> .main-content {
|
|
||||||
margin-bottom: unset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
<div class="hexagon">
|
|
||||||
<slot></slot>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
.hexagon {
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
background-image: url(/assets/hexagon.svg);
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-position: center;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,122 +0,0 @@
|
||||||
<script lang="ts">
|
|
||||||
import SciFiButton from "./SciFi-Button.svelte";
|
|
||||||
import { createEventDispatcher } from "svelte";
|
|
||||||
import { myName, isHost } from "../stores";
|
|
||||||
import type { IColour } from "common";
|
|
||||||
|
|
||||||
export let name: string;
|
|
||||||
export let colour: IColour;
|
|
||||||
|
|
||||||
const emit = createEventDispatcher();
|
|
||||||
|
|
||||||
function exitPlayer() {};
|
|
||||||
|
|
||||||
function changeColour() {
|
|
||||||
emit("changeColour");
|
|
||||||
};
|
|
||||||
|
|
||||||
let canLeave = $isHost || name == $myName;
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="player" style="--colour: {colour.hex};">
|
|
||||||
|
|
||||||
<!-- The player's change Colour button -->
|
|
||||||
{#if $myName == name}
|
|
||||||
<SciFiButton
|
|
||||||
background="{colour.hex}"
|
|
||||||
on:click={changeColour}
|
|
||||||
height="60px"
|
|
||||||
width="60px"
|
|
||||||
hoverBackground="{colour.hex}"
|
|
||||||
>
|
|
||||||
<div style="display: flex; align-items: center; justify-content: center;">
|
|
||||||
<img
|
|
||||||
src="/assets/icons/change_colour.svg"
|
|
||||||
alt="Change your spaceship's colour"
|
|
||||||
style="baseline: center"
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</SciFiButton>
|
|
||||||
|
|
||||||
<!-- The placeholder element that just gets coloured for other player colours -->
|
|
||||||
{:else}
|
|
||||||
<div class="player-colour"></div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<!-- The player's name -->
|
|
||||||
<div class="player-name">
|
|
||||||
<span class="name">
|
|
||||||
{name}
|
|
||||||
</span>
|
|
||||||
{#if $myName == name}
|
|
||||||
<span class="player-indicator">
|
|
||||||
You
|
|
||||||
</span>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Whether or not to show the kick Player button in the row -->
|
|
||||||
{#if canLeave}
|
|
||||||
<SciFiButton
|
|
||||||
background="#ff0000"
|
|
||||||
on:click={exitPlayer}
|
|
||||||
height="60px"
|
|
||||||
width="75px"
|
|
||||||
hoverBackground="#ff0000"
|
|
||||||
>
|
|
||||||
<div style="display: flex; align-items: center; justify-content: center;">
|
|
||||||
<img
|
|
||||||
src="/assets/icons/kick_person.svg"
|
|
||||||
alt="Remove person from the game"
|
|
||||||
style="baseline: center"
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</SciFiButton>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
@import "../styles/mixins";
|
|
||||||
|
|
||||||
.player {
|
|
||||||
height: 70px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
text-align: left;
|
|
||||||
background: rgba(255, 255, 255, 0.1);
|
|
||||||
border-radius: 10px;
|
|
||||||
margin: 10px;
|
|
||||||
max-width: 95%;
|
|
||||||
|
|
||||||
> div.player-colour {
|
|
||||||
margin: 10px;
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
background: var(--colour);
|
|
||||||
display: inline-block;
|
|
||||||
border-radius: 7px;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .player-name {
|
|
||||||
flex-grow: 1;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
.name {
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.player-indicator {
|
|
||||||
border-radius: 5px;
|
|
||||||
background-color: #00aa00;
|
|
||||||
color: black;
|
|
||||||
padding: 5px 7px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@include medium {
|
|
||||||
max-width: 47%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
<script lang="ts">
|
|
||||||
import { createEventDispatcher } from "svelte";
|
|
||||||
import Card from "./Card.svelte";
|
|
||||||
import { hand } from "../stores";
|
|
||||||
|
|
||||||
const emit = createEventDispatcher();
|
|
||||||
let canChooseFuel = true;
|
|
||||||
|
|
||||||
// Prevent rendering of a board preview when the player isn't allowed to select
|
|
||||||
// a card.
|
|
||||||
function filterHoverEvents(e: any) {
|
|
||||||
if (canChooseFuel) {
|
|
||||||
emit(`hover`, e.detail);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
|
|
||||||
<div id="hand">
|
|
||||||
{#each $hand as card (card.symbol)}
|
|
||||||
<Card
|
|
||||||
on:hover="{filterHoverEvents}"
|
|
||||||
hidden="{false}"
|
|
||||||
button="{canChooseFuel}"
|
|
||||||
{card}
|
|
||||||
/>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
#hand {
|
|
||||||
background: rgba(0,0,0, 0.6);
|
|
||||||
border-color: white;
|
|
||||||
border-radius: 15px;
|
|
||||||
border-style: solid;
|
|
||||||
border-width: 1px;
|
|
||||||
display: flex;
|
|
||||||
height: 100%;
|
|
||||||
justify-content: space-evenly;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,117 +0,0 @@
|
||||||
<script lang="ts">
|
|
||||||
export let height: string|number = "50px";
|
|
||||||
export let width: string|number = "unset";
|
|
||||||
export let textColour: string = "#000000";
|
|
||||||
export let hoverTextColour: string = "#000000";
|
|
||||||
export let background: string = "#00aa00";
|
|
||||||
export let hoverBackground: string = "transparent";
|
|
||||||
export let classes: string = "";
|
|
||||||
export let title: string = "";
|
|
||||||
|
|
||||||
|
|
||||||
// Add the units to the height value if not provided, and ensure that the
|
|
||||||
// provided height is not less than 50 (the default)
|
|
||||||
$: if (typeof(height) == "string") {
|
|
||||||
if (height.match(/[0-9]$/)) {
|
|
||||||
if (height.match(/^[0-4]?[0-9]$/)) {
|
|
||||||
height = `50`;
|
|
||||||
};
|
|
||||||
height = `${height}px`;
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
if (height < 50) {
|
|
||||||
height = 50;
|
|
||||||
};
|
|
||||||
height = `${height}px`;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Add the units to the width value if not provided
|
|
||||||
$: if (typeof(width) == "string") {
|
|
||||||
if (width.match(/[0-9]$/)) {
|
|
||||||
width = `${width}px`;
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
width = `${width}px`;
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div
|
|
||||||
style="
|
|
||||||
--height: {height};
|
|
||||||
--width: {width};
|
|
||||||
--background-colour: {background};
|
|
||||||
--hover-background-colour: {hoverBackground};
|
|
||||||
--text-colour: {textColour};
|
|
||||||
--hover-text-colour: {hoverTextColour};"
|
|
||||||
class="button-container {classes}"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
class="clickable"
|
|
||||||
{title}
|
|
||||||
on:click|trusted|stopPropagation
|
|
||||||
>
|
|
||||||
<slot></slot>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
div.button-container {
|
|
||||||
display: inline-block;
|
|
||||||
position: relative;
|
|
||||||
width: var(--width);
|
|
||||||
height: var(--height);
|
|
||||||
}
|
|
||||||
|
|
||||||
$button-background: var(--background-colour);
|
|
||||||
$hover-background: var(--hover-background-colour);
|
|
||||||
$text-colour: var(--text-colour);
|
|
||||||
$hover-text-colour: var(--hover-text-colour);
|
|
||||||
|
|
||||||
button {
|
|
||||||
background: $button-background;
|
|
||||||
border-radius: 5px;
|
|
||||||
border: 3px solid $button-background;
|
|
||||||
box-sizing: border-box;
|
|
||||||
color: $text-colour;
|
|
||||||
font-family: 'Orbitron', sans-serif;
|
|
||||||
height: calc(100% - 20px);
|
|
||||||
margin: 10px;
|
|
||||||
padding: 5px 7px;
|
|
||||||
transition: all .7s ease;
|
|
||||||
transition: opacity .7s ease;
|
|
||||||
width: calc(100% - 20px);
|
|
||||||
outline: none;
|
|
||||||
|
|
||||||
&:active {
|
|
||||||
opacity: .2;
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover, &:focus {
|
|
||||||
background-color: $hover-background;
|
|
||||||
border-radius: 20px;
|
|
||||||
color: $hover-text-colour;
|
|
||||||
|
|
||||||
&:before {
|
|
||||||
border-radius: min(
|
|
||||||
calc(((var(--height) - 20px) / 2) + 5px),
|
|
||||||
25px
|
|
||||||
);
|
|
||||||
border: 2px $button-background solid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:before {
|
|
||||||
content: ' ';
|
|
||||||
border: 2px transparent solid;
|
|
||||||
position: absolute;
|
|
||||||
left: 5px;
|
|
||||||
top: 5px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
width: calc(100% - 10px);
|
|
||||||
height: calc(100% - 10px); /* 100% - 20px + 10px */
|
|
||||||
transition: all .8s ease;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,119 +0,0 @@
|
||||||
<script lang="ts">
|
|
||||||
import { createEventDispatcher } from "svelte";
|
|
||||||
|
|
||||||
const emit = createEventDispatcher();
|
|
||||||
|
|
||||||
export let disabled: boolean = false;
|
|
||||||
export let state: boolean;
|
|
||||||
export let name: string;
|
|
||||||
export let id: string;
|
|
||||||
|
|
||||||
function onToggle() {
|
|
||||||
emit(`toggle`, id);
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<label class="container" {disabled}>
|
|
||||||
<slot></slot>
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
{disabled}
|
|
||||||
{name}
|
|
||||||
{id}
|
|
||||||
bind:checked="{state}"
|
|
||||||
on:click="{onToggle}"
|
|
||||||
>
|
|
||||||
<span class="checkmark"></span>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
$unchecked: #ff0000;
|
|
||||||
$checked: #00aa00;
|
|
||||||
|
|
||||||
/* Create a custom checkbox */
|
|
||||||
.checkmark {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
height: 25px;
|
|
||||||
width: 25px;
|
|
||||||
background-color: $unchecked;
|
|
||||||
border-radius: 12px;
|
|
||||||
|
|
||||||
&:after {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:after {
|
|
||||||
left: 7px;
|
|
||||||
top: 2px;
|
|
||||||
width: 7px;
|
|
||||||
height: 14px;
|
|
||||||
border: solid black;
|
|
||||||
border-width: 0 3px 3px 0;
|
|
||||||
-webkit-transform: rotate(45deg);
|
|
||||||
-ms-transform: rotate(45deg);
|
|
||||||
transform: rotate(45deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.container {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
position: relative;
|
|
||||||
padding-left: 35px;
|
|
||||||
margin: 10px;
|
|
||||||
cursor: pointer;
|
|
||||||
-webkit-user-select: none;
|
|
||||||
-moz-user-select: none;
|
|
||||||
-ms-user-select: none;
|
|
||||||
user-select: none;
|
|
||||||
height: 25px;
|
|
||||||
|
|
||||||
input {
|
|
||||||
position: absolute;
|
|
||||||
opacity: 0;
|
|
||||||
cursor: pointer;
|
|
||||||
height: 0;
|
|
||||||
width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Checked checkmark */
|
|
||||||
input:checked ~ .checkmark {
|
|
||||||
background-color: $checked;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Darken the checkmark background colour when hovering */
|
|
||||||
&:hover {
|
|
||||||
input ~ .checkmark {
|
|
||||||
background-color: darken($unchecked, 20%);
|
|
||||||
}
|
|
||||||
|
|
||||||
input:checked ~ .checkmark {
|
|
||||||
background-color: darken($checked, 20%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Indicate to users when they can't actually use the options */
|
|
||||||
&[disabled="true"] {
|
|
||||||
cursor: not-allowed;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
input ~ .checkmark {
|
|
||||||
background-color: $unchecked;
|
|
||||||
}
|
|
||||||
|
|
||||||
input:checked ~ .checkmark {
|
|
||||||
background-color: $checked;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Show the checkmark when checked */
|
|
||||||
input:checked ~ .checkmark:after {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,172 +0,0 @@
|
||||||
<script lang="ts">
|
|
||||||
import { players } from "../stores";
|
|
||||||
import Spaceship from "./icons/spaceship.svelte";
|
|
||||||
import Card from "./Card.svelte";
|
|
||||||
|
|
||||||
$: stopped = false;
|
|
||||||
|
|
||||||
$: sortedPlayers = Object.values($players).sort(
|
|
||||||
(p1, p2) => p1.fuel.symbol.localeCompare(p2.fuel.symbol)
|
|
||||||
);
|
|
||||||
|
|
||||||
$: activePlayer = "a";
|
|
||||||
</script>
|
|
||||||
|
|
||||||
|
|
||||||
<div id="ships-moving">
|
|
||||||
<div id="player-order-container">
|
|
||||||
<div class="player-order background">
|
|
||||||
{#each sortedPlayers as player (player.id)}
|
|
||||||
<div class="player">
|
|
||||||
<div class="card">
|
|
||||||
<Card card={player.fuel} half={true} />
|
|
||||||
</div>
|
|
||||||
<div class="meta">
|
|
||||||
<div
|
|
||||||
class="spaceship-icon"
|
|
||||||
style="--colour: {player.colour.hex};"
|
|
||||||
>
|
|
||||||
<Spaceship
|
|
||||||
spaceship="{player.ship.id}"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="name">
|
|
||||||
{player.name}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="e-stop-container">
|
|
||||||
<div class="e-stop background">
|
|
||||||
<h2>Emergency Stop!</h2>
|
|
||||||
<p>
|
|
||||||
Pressing this will stop you from moving
|
|
||||||
</p>
|
|
||||||
<div class="button-container">
|
|
||||||
<button
|
|
||||||
disabled={stopped}
|
|
||||||
on:click="{() => {stopped = true}}"
|
|
||||||
>
|
|
||||||
<h1>STOP{#if stopped}PED{/if}</h1>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
#ships-moving {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1fr 30%;
|
|
||||||
height: 100%;
|
|
||||||
padding: 0;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#player-order-container {
|
|
||||||
grid-column: 1 / 2;
|
|
||||||
|
|
||||||
.player-order {
|
|
||||||
color: white;
|
|
||||||
display: flex;
|
|
||||||
height: 100%;
|
|
||||||
justify-content: space-evenly;
|
|
||||||
margin-right: 5px;
|
|
||||||
width: calc(100% - 5px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.card {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.player {
|
|
||||||
display: grid;
|
|
||||||
grid-template-rows: 50% 50%;
|
|
||||||
|
|
||||||
.meta {
|
|
||||||
align-items: center;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: space-evenly;
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
.name {
|
|
||||||
background: rgba(255,255,255,0.2);
|
|
||||||
border-radius: 5px;
|
|
||||||
padding: 5px;
|
|
||||||
width: 80%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.spaceship-icon {
|
|
||||||
aspect-ratio: 1 / 1;
|
|
||||||
color: var(--colour);
|
|
||||||
height: 50%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#e-stop-container {
|
|
||||||
grid-column: 2 / 3;
|
|
||||||
|
|
||||||
.e-stop {
|
|
||||||
align-items: center;
|
|
||||||
color: white;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
height: 100%;
|
|
||||||
margin-left: 5px;
|
|
||||||
text-align: center;
|
|
||||||
width: calc(100% - 5px);
|
|
||||||
|
|
||||||
|
|
||||||
> h2,
|
|
||||||
> p {
|
|
||||||
margin-bottom: 0;
|
|
||||||
margin-top: 10px;
|
|
||||||
width: 90%;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .button-container {
|
|
||||||
align-items: center;
|
|
||||||
display: flex;
|
|
||||||
flex-grow: 1;
|
|
||||||
justify-content: center;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
$height: 10px;
|
|
||||||
background: red;
|
|
||||||
border-radius: 10px;
|
|
||||||
border-style: none;
|
|
||||||
box-shadow: 0 $height 0 darken(red, 20%);
|
|
||||||
font-family: 'Orbitron', sans-serif;
|
|
||||||
margin-top: -5px;
|
|
||||||
outline: none;
|
|
||||||
width: 80%;
|
|
||||||
|
|
||||||
&[disabled],
|
|
||||||
&:active {
|
|
||||||
box-shadow: none;
|
|
||||||
transform: translateY($height);
|
|
||||||
}
|
|
||||||
|
|
||||||
&[disabled] {
|
|
||||||
color: rgba(0,0,0, 0.6);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.background {
|
|
||||||
background: rgba(0,0,0, 0.6);
|
|
||||||
border-color: white;
|
|
||||||
border-radius: 15px;
|
|
||||||
border-style: solid;
|
|
||||||
border-width: 1px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,52 +0,0 @@
|
||||||
<!--
|
|
||||||
Possible extra Spaceship icons:
|
|
||||||
https://www.flaticon.com/free-icon/spaceship_6437894
|
|
||||||
https://fontawesome.com/v5.15/icons/starfighter?style=solid
|
|
||||||
https://fontawesome.com/v5.15/icons/starship-freighter?style=solid
|
|
||||||
https://fontawesome.com/v5.15/icons/starship?style=solid
|
|
||||||
https://fontawesome.com/icons/sailboat?s=solid
|
|
||||||
-->
|
|
||||||
<script lang="ts">
|
|
||||||
export let spaceship = "space-shuttle";
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{#if spaceship == "rocket"}
|
|
||||||
<div class="rocket">
|
|
||||||
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="rocket" class="svg-inline--fa fa-rocket fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M505.12019,19.09375c-1.18945-5.53125-6.65819-11-12.207-12.1875C460.716,0,435.507,0,410.40747,0,307.17523,0,245.26909,55.20312,199.05238,128H94.83772c-16.34763.01562-35.55658,11.875-42.88664,26.48438L2.51562,253.29688A28.4,28.4,0,0,0,0,264a24.00867,24.00867,0,0,0,24.00582,24H127.81618l-22.47457,22.46875c-11.36521,11.36133-12.99607,32.25781,0,45.25L156.24582,406.625c11.15623,11.1875,32.15619,13.15625,45.27726,0l22.47457-22.46875V488a24.00867,24.00867,0,0,0,24.00581,24,28.55934,28.55934,0,0,0,10.707-2.51562l98.72834-49.39063c14.62888-7.29687,26.50776-26.5,26.50776-42.85937V312.79688c72.59753-46.3125,128.03493-108.40626,128.03493-211.09376C512.07526,76.5,512.07526,51.29688,505.12019,19.09375ZM384.04033,168A40,40,0,1,1,424.05,128,40.02322,40.02322,0,0,1,384.04033,168Z"></path></svg>
|
|
||||||
</div>
|
|
||||||
{:else if spaceship == "space-shuttle"}
|
|
||||||
<div class="space-shuttle">
|
|
||||||
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="space-shuttle" class="svg-inline--fa fa-space-shuttle fa-w-20" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path fill="currentColor" d="M592.604 208.244C559.735 192.836 515.777 184 472 184H186.327c-4.952-6.555-10.585-11.978-16.72-16H376C229.157 137.747 219.403 32 96.003 32H96v128H80V32c-26.51 0-48 28.654-48 64v64c-23.197 0-32 10.032-32 24v40c0 13.983 8.819 24 32 24v16c-23.197 0-32 10.032-32 24v40c0 13.983 8.819 24 32 24v64c0 35.346 21.49 64 48 64V352h16v128h.003c123.4 0 133.154-105.747 279.997-136H169.606c6.135-4.022 11.768-9.445 16.72-16H472c43.777 0 87.735-8.836 120.604-24.244C622.282 289.845 640 271.992 640 256s-17.718-33.845-47.396-47.756zM488 296a8 8 0 0 1-8-8v-64a8 8 0 0 1 8-8c31.909 0 31.942 80 0 80z"></path></svg>
|
|
||||||
</div>
|
|
||||||
{:else if spaceship == "sailboat"}
|
|
||||||
<div class="sailboat">
|
|
||||||
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="sailboat" class="svg-inline--fa fa-sailboat fa-w-20" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--! Font Awesome Pro 6.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path fill="currentColor" d="M256 16C256 9.018 260.5 2.841 267.2 .7414C273.9-1.358 281.1 1.105 285.1 6.826L509.1 326.8C512.5 331.7 512.9 338.1 510.2 343.4C507.4 348.7 501.1 352 496 352H272C263.2 352 256 344.8 256 336V16zM212.1 96.54C219.1 98.4 224 104.7 224 112V336C224 344.8 216.8 352 208 352H80C74.3 352 69.02 348.1 66.16 344C63.3 339.1 63.28 333 66.11 328.1L194.1 104.1C197.7 97.76 205.1 94.68 212.1 96.54V96.54zM5.718 404.3C2.848 394.1 10.52 384 21.12 384H554.9C565.5 384 573.2 394.1 570.3 404.3L566.3 418.7C550.7 473.9 500.4 512 443 512H132.1C75.62 512 25.27 473.9 9.747 418.7L5.718 404.3z"/></svg>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
svg {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%
|
|
||||||
}
|
|
||||||
|
|
||||||
.rocket {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
transform: translate(-5px, 0px) rotate(45deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.space-shuttle {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sailboat {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
transform: translate(3px, 5px);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
<div class="main">
|
|
||||||
<div class="shell"></div>
|
|
||||||
<div class="center"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
div {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.shell {
|
|
||||||
background-image: url(/assets/warp-gate-shell.svg);
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-position: center;
|
|
||||||
transform: rotate(90deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.center {
|
|
||||||
--size: 60%;
|
|
||||||
width: var(--size);
|
|
||||||
height: var(--size);
|
|
||||||
position: absolute;
|
|
||||||
background-image: url(/assets/warp-gate-center.svg);
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-position: center;
|
|
||||||
animation: rotate 3s linear infinite;
|
|
||||||
top: 21%;
|
|
||||||
left: 21%;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-reduced-motion) {
|
|
||||||
.center {
|
|
||||||
animation: rotate 10s linear infinite;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes rotate {
|
|
||||||
to {
|
|
||||||
transform: rotate(0deg);
|
|
||||||
}
|
|
||||||
from {
|
|
||||||
transform: rotate(360deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,98 +0,0 @@
|
||||||
<script lang="ts">
|
|
||||||
import SciFiButton from "../SciFi-Button.svelte";
|
|
||||||
import { fade, scale } from "svelte/transition";
|
|
||||||
import { createEventDispatcher } from "svelte";
|
|
||||||
|
|
||||||
const emit = createEventDispatcher();
|
|
||||||
|
|
||||||
|
|
||||||
export let open = false;
|
|
||||||
function closeModal() {
|
|
||||||
emit(`close`);
|
|
||||||
open = false;
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{#if open}
|
|
||||||
<div class="modal">
|
|
||||||
<div
|
|
||||||
class="background clickable"
|
|
||||||
in:fade
|
|
||||||
out:fade="{{ delay: 200 }}"
|
|
||||||
on:click="{closeModal}"
|
|
||||||
></div>
|
|
||||||
<div
|
|
||||||
class="foreground"
|
|
||||||
in:scale="{{ delay: 400, start: 0, opacity: 1 }}"
|
|
||||||
out:scale="{{ start: 0, opacity: 1 }}"
|
|
||||||
>
|
|
||||||
<SciFiButton
|
|
||||||
classes="close-button"
|
|
||||||
on:click={closeModal}
|
|
||||||
height="60"
|
|
||||||
width="60"
|
|
||||||
on:click
|
|
||||||
>
|
|
||||||
<div class="icon-container">
|
|
||||||
<span class="material-icons">
|
|
||||||
close
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</SciFiButton>
|
|
||||||
<slot></slot>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
@import "../../styles/mixins";
|
|
||||||
|
|
||||||
.modal {
|
|
||||||
z-index: 100;
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100vw;
|
|
||||||
height: 100vh;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
.background {
|
|
||||||
position: absolute;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background-color: rgba(0,0,0, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
.foreground {
|
|
||||||
z-index: 101;
|
|
||||||
max-height: 80vh;
|
|
||||||
overflow: auto;
|
|
||||||
width: 90%;
|
|
||||||
padding: 15px;
|
|
||||||
position: relative;
|
|
||||||
border-radius: 10px;
|
|
||||||
|
|
||||||
background: var(--dark-but-not-black);
|
|
||||||
color: #FFFFFF;
|
|
||||||
|
|
||||||
.icon-container {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(.close-button) {
|
|
||||||
position: absolute;
|
|
||||||
top: 10px;
|
|
||||||
right: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@include medium {
|
|
||||||
width: 75%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,124 +0,0 @@
|
||||||
<script lang="ts">
|
|
||||||
import { isHost, myName, gameCode, players } from "../../stores";
|
|
||||||
import { createEventDispatcher, onMount } from "svelte";
|
|
||||||
import SciFiButton from "../SciFi-Button.svelte";
|
|
||||||
import { ILobbyInfo, Status } from "common";
|
|
||||||
import BaseModal from "./BaseModal.svelte";
|
|
||||||
import { socket } from "../../main";
|
|
||||||
|
|
||||||
const emit = createEventDispatcher();
|
|
||||||
|
|
||||||
export let open: boolean = false;
|
|
||||||
export let joining: boolean;
|
|
||||||
|
|
||||||
let errorMessage: string|null = null;
|
|
||||||
|
|
||||||
function handleLobbyConnection(data: ILobbyInfo) {
|
|
||||||
if (data.status == Status.Success) {
|
|
||||||
console.debug(`Succesfully joined lobby`);
|
|
||||||
|
|
||||||
let url = new URL(window.location.href);
|
|
||||||
let qs = url.searchParams;
|
|
||||||
qs.set(`game`, data.game_code);
|
|
||||||
|
|
||||||
window.history.replaceState(null, null, url)
|
|
||||||
|
|
||||||
gameCode.set(data.game_code);
|
|
||||||
players.set(data.players);
|
|
||||||
emit(`joined`);
|
|
||||||
} else {
|
|
||||||
console.error(data);
|
|
||||||
errorMessage = data.message;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
onMount(() => {
|
|
||||||
socket.on(`res:lobby.players.join`, handleLobbyConnection);
|
|
||||||
socket.on(`res:lobby.create`, handleLobbyConnection);
|
|
||||||
return () => {
|
|
||||||
socket.off(`res:lobby.players.join`);
|
|
||||||
socket.off(`res:lobby.create`);
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
function connectToLobby() {
|
|
||||||
errorMessage = null;
|
|
||||||
isHost.set(!joining);
|
|
||||||
|
|
||||||
// Emit the correct event for the modal type
|
|
||||||
if (joining) {
|
|
||||||
socket.emit(`req:lobby.players.join`, {
|
|
||||||
name: $myName,
|
|
||||||
game_code: $gameCode,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
socket.emit(`req:lobby.create`, {
|
|
||||||
name: $myName
|
|
||||||
});
|
|
||||||
};
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<BaseModal {open} on:close>
|
|
||||||
<div class="foreground">
|
|
||||||
<h1>{joining ? "Join Game" : "Create Lobby"}</h1>
|
|
||||||
<hr>
|
|
||||||
<div class="form">
|
|
||||||
<label for="name">Username:</label>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
name="name"
|
|
||||||
id="name"
|
|
||||||
bind:value="{$myName}"
|
|
||||||
>
|
|
||||||
{#if joining}
|
|
||||||
<br>
|
|
||||||
<label for="game-code">Game Code:</label>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
name="game code"
|
|
||||||
id="game-code"
|
|
||||||
bind:value="{$gameCode}"
|
|
||||||
>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
<br>
|
|
||||||
<SciFiButton
|
|
||||||
on:click="{connectToLobby}"
|
|
||||||
>
|
|
||||||
{joining ? "Join Game" : "Create Lobby"}
|
|
||||||
</SciFiButton>
|
|
||||||
{#if errorMessage}
|
|
||||||
<div class="error">
|
|
||||||
{errorMessage}
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</BaseModal>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
.foreground {
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
.form {
|
|
||||||
display: inline-block;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="text"] {
|
|
||||||
background: black;
|
|
||||||
color: white;
|
|
||||||
padding: 5px 7px;
|
|
||||||
outline: none;
|
|
||||||
border-radius: 7px;
|
|
||||||
border-width: 2px;
|
|
||||||
border-color: transparent;
|
|
||||||
border-style: solid;
|
|
||||||
margin: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="text"]:focus {
|
|
||||||
border-color: #0a0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
<script lang="ts">
|
|
||||||
import BaseModal from "./BaseModal.svelte";
|
|
||||||
import type { IGameOption } from "common";
|
|
||||||
|
|
||||||
export let visibleOptions: IGameOption[];
|
|
||||||
export let open: boolean = false;
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<BaseModal {open} on:close>
|
|
||||||
<div class="foreground">
|
|
||||||
<h1>Option Info</h1>
|
|
||||||
<hr>
|
|
||||||
{#each visibleOptions as opt}
|
|
||||||
{#if !opt.hidden}
|
|
||||||
<h2>{opt.name}</h2>
|
|
||||||
<p>
|
|
||||||
{opt.description}
|
|
||||||
</p>
|
|
||||||
{/if}
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
</BaseModal>
|
|
||||||
|
|
@ -1,205 +0,0 @@
|
||||||
<script lang="ts">
|
|
||||||
import { Status, colours, spaceships } from "common";
|
|
||||||
import SpaceShuttle from "../icons/spaceship.svelte";
|
|
||||||
import SciFiButton from "../SciFi-Button.svelte";
|
|
||||||
import { createEventDispatcher, onMount } from "svelte";
|
|
||||||
import { myName, players } from "../../stores";
|
|
||||||
import BaseModal from "./BaseModal.svelte";
|
|
||||||
import Hexagon from "../Hexagon.svelte";
|
|
||||||
import { socket } from "../../main";
|
|
||||||
|
|
||||||
const emit = createEventDispatcher();
|
|
||||||
|
|
||||||
export let open: boolean = false;
|
|
||||||
|
|
||||||
let player = $players.find(p => p.name == $myName);
|
|
||||||
|
|
||||||
$: myColour = player.colour;
|
|
||||||
$: takenColours = $players.map(p => p.colour);
|
|
||||||
|
|
||||||
var selectedColour = player.colour.hex;
|
|
||||||
var selectedShip = player.ship.id;
|
|
||||||
var error = null;
|
|
||||||
|
|
||||||
function designUpdate(data: any) {
|
|
||||||
if (data.status != Status.Success) {
|
|
||||||
error = data.message;
|
|
||||||
|
|
||||||
/*
|
|
||||||
TODO (Maybe): If the list of colours doesn't auto-update the available
|
|
||||||
colours based on which are already taken when another player saves, we
|
|
||||||
will need to update the list manually here on Status.OutOfDate
|
|
||||||
*/
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Alert the parent and remove any errors
|
|
||||||
error = null;
|
|
||||||
emit(`save`, {
|
|
||||||
colour: selectedColour,
|
|
||||||
ship: selectedShip,
|
|
||||||
});
|
|
||||||
|
|
||||||
emit(`close`);
|
|
||||||
};
|
|
||||||
|
|
||||||
onMount(() => {
|
|
||||||
socket.on(`req:lobby.players.update`, designUpdate);
|
|
||||||
return () => {
|
|
||||||
socket.off(`req:lobby.players.update`);
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
function saveShipDesign() {
|
|
||||||
/* TODO: Send event to server, wait for confirmation */
|
|
||||||
let response: any = {
|
|
||||||
status: Status.UnknownError,
|
|
||||||
message: `Testing the error design`,
|
|
||||||
};
|
|
||||||
|
|
||||||
socket.emit(`req:lobby.players.update`, {});
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
|
|
||||||
<BaseModal {open} on:close>
|
|
||||||
<div>
|
|
||||||
<h2>Spaceship Designer</h2>
|
|
||||||
<hr>
|
|
||||||
<div class="flex-container">
|
|
||||||
<div class="options">
|
|
||||||
<div class="colour">
|
|
||||||
<h3>Colour:</h3>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Create the dropdown that allows the user to see all of
|
|
||||||
the colours but not choose ones that other users
|
|
||||||
currently have selected.
|
|
||||||
-->
|
|
||||||
<select
|
|
||||||
name="colour"
|
|
||||||
id="spaceship-colour"
|
|
||||||
bind:value="{selectedColour}"
|
|
||||||
>
|
|
||||||
<!-- Display each colour as given by the server -->
|
|
||||||
{#each colours as c}
|
|
||||||
<option
|
|
||||||
value="{c.hex}"
|
|
||||||
disabled="{
|
|
||||||
c.hex != myColour.hex
|
|
||||||
&& takenColours.includes(c)
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
{c.name}
|
|
||||||
</option>
|
|
||||||
{/each}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="spaceship">
|
|
||||||
<h3>Spaceship</h3>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Create the dropdown that allows users to select which
|
|
||||||
spaceship icon they want for their player.
|
|
||||||
-->
|
|
||||||
<select
|
|
||||||
name="spaceship"
|
|
||||||
id="spaceship-icon"
|
|
||||||
bind:value="{selectedShip}"
|
|
||||||
>
|
|
||||||
{#each spaceships as ship}
|
|
||||||
<option value="{ship.id}">{ship.name}</option>
|
|
||||||
{/each}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="preview">
|
|
||||||
<h3>Preview:</h3>
|
|
||||||
<Hexagon>
|
|
||||||
<div
|
|
||||||
class="spaceship-icon"
|
|
||||||
style="--colour: {selectedColour};"
|
|
||||||
>
|
|
||||||
<SpaceShuttle
|
|
||||||
spaceship="{selectedShip}"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</Hexagon>
|
|
||||||
<SciFiButton
|
|
||||||
on:click="{saveShipDesign}"
|
|
||||||
>
|
|
||||||
Save Design
|
|
||||||
</SciFiButton>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{#if error}
|
|
||||||
<div class="error">
|
|
||||||
{error}
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</BaseModal>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
@import "../../styles/mixins";
|
|
||||||
|
|
||||||
.flex-container {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
> div {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
width: 90%;
|
|
||||||
flex-grow: 1;
|
|
||||||
margin: 5px;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
> * {
|
|
||||||
text-align: center;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
@include medium {
|
|
||||||
width: 30%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
margin-bottom: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
select {
|
|
||||||
border-radius: 5px;
|
|
||||||
background: black;
|
|
||||||
color: white;
|
|
||||||
outline: none;
|
|
||||||
border-width: 2px;
|
|
||||||
border-style: solid;
|
|
||||||
border-color: transparent;
|
|
||||||
padding: 5px 7px;
|
|
||||||
width: 90%;
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
border-color: #00aa00;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.spaceship-icon {
|
|
||||||
/*
|
|
||||||
Smaller version: 55px
|
|
||||||
Larger version: 75px
|
|
||||||
*/
|
|
||||||
--size: 80px;
|
|
||||||
width: var(--size);
|
|
||||||
height: var(--size);
|
|
||||||
display: flex;
|
|
||||||
color: var(--colour);
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
transform: rotate(-90deg);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
import type { IServerInfo } from "common";
|
|
||||||
import io from "socket.io-client";
|
|
||||||
import App from "./App.svelte";
|
|
||||||
|
|
||||||
let url = "/";
|
|
||||||
if (import.meta.env.DEV) {
|
|
||||||
url = "http://localhost:3001/";
|
|
||||||
};
|
|
||||||
|
|
||||||
export const socket = io(url);
|
|
||||||
|
|
||||||
|
|
||||||
socket.on(`res:error`, (data) => {
|
|
||||||
console.error(data);
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on("connect", () => {
|
|
||||||
console.log("Connected to websocket server. Server info below:");
|
|
||||||
socket.once("res:server.info", (data: IServerInfo) => {
|
|
||||||
console.table(data);
|
|
||||||
});
|
|
||||||
socket.emit("req:server.info");
|
|
||||||
});
|
|
||||||
|
|
||||||
const app = new App({
|
|
||||||
target: document.getElementById('app')
|
|
||||||
})
|
|
||||||
|
|
||||||
export default app
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
import type { Board, FuelCard, PlayerData } from "common";
|
|
||||||
import { writable } from "svelte/store";
|
|
||||||
|
|
||||||
export const gameCode = writable<string>("");
|
|
||||||
export const state = writable<string>("game-movement");
|
|
||||||
export const myName = writable<string>("");
|
|
||||||
export const isHost = writable<boolean>(false);
|
|
||||||
export const players = writable<{[index: string]: PlayerData}>({
|
|
||||||
a: {
|
|
||||||
id: `a`,
|
|
||||||
name: `Player 1`,
|
|
||||||
host: true,
|
|
||||||
colour: { name: `green`, hex: `#00aa00` },
|
|
||||||
ship: { name: `shuttle`, id: `space-shuttle` },
|
|
||||||
fuel: {
|
|
||||||
"magnitude": 2,
|
|
||||||
"symbol": "Jo",
|
|
||||||
"name": "Jodium",
|
|
||||||
"type": "stationary"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
b: {
|
|
||||||
id: `b`,
|
|
||||||
name: `Player 4`,
|
|
||||||
host: false,
|
|
||||||
colour: { name: `green`, hex: `#00a` },
|
|
||||||
ship: { name: `shuttle`, id: `rocket` },
|
|
||||||
fuel: {
|
|
||||||
"magnitude": 1,
|
|
||||||
"symbol": "Ar",
|
|
||||||
"name": "Argon",
|
|
||||||
"type": "movement"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
c: {
|
|
||||||
id: `c`,
|
|
||||||
name: `Player 3`,
|
|
||||||
host: false,
|
|
||||||
colour: { name: "Magenta", hex: "#b7094c" },
|
|
||||||
ship: { name: `shuttle`, id: `rocket` },
|
|
||||||
fuel: {
|
|
||||||
"magnitude": 10,
|
|
||||||
"symbol": "Mg",
|
|
||||||
"name": "Magnesium",
|
|
||||||
"type": "movement"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
d: {
|
|
||||||
id: `d`,
|
|
||||||
name: `Player 2`,
|
|
||||||
host: false,
|
|
||||||
colour: { name: "Purple", hex: "#7400b8" },
|
|
||||||
ship: { name: `shuttle`, id: `rocket` },
|
|
||||||
fuel: {
|
|
||||||
"magnitude": -2,
|
|
||||||
"symbol": "Kr",
|
|
||||||
"name": "Krypton",
|
|
||||||
"type": "movement"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
export const board = writable<Board>(new Array(54).fill(null));
|
|
||||||
export const hand = writable<FuelCard[]>([]);
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
@mixin small {
|
|
||||||
@media (min-width: 576px) {
|
|
||||||
@content;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin medium {
|
|
||||||
@media (min-width: 768px) {
|
|
||||||
@content;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin large {
|
|
||||||
@media (min-width: 992px) {
|
|
||||||
@content;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin x-large {
|
|
||||||
@media (min-width: 1200px) {
|
|
||||||
@content;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,119 +0,0 @@
|
||||||
<script lang="ts">
|
|
||||||
import LobbyModal from "../components/modals/JoinLobby.svelte";
|
|
||||||
import SciFiButton from "../components/SciFi-Button.svelte";
|
|
||||||
import { state } from "../stores";
|
|
||||||
|
|
||||||
// The modals that can appear from this component
|
|
||||||
const modal = {
|
|
||||||
joinLobby: false,
|
|
||||||
};
|
|
||||||
let joiningLobby = false;
|
|
||||||
|
|
||||||
function hostGame() {
|
|
||||||
joiningLobby = false;
|
|
||||||
modal.joinLobby = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
function joinGame() {
|
|
||||||
joiningLobby = true;
|
|
||||||
modal.joinLobby = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
function joinedLobby() {
|
|
||||||
modal.joinLobby = false;
|
|
||||||
setTimeout(() => {
|
|
||||||
state.set("multiplayer-lobby");
|
|
||||||
}, 750);
|
|
||||||
};
|
|
||||||
|
|
||||||
function singleplayerGame() {};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<LobbyModal
|
|
||||||
open="{modal.joinLobby}"
|
|
||||||
joining="{joiningLobby}"
|
|
||||||
on:joined={joinedLobby}
|
|
||||||
on:close="{_ => modal.joinLobby = false}"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<main>
|
|
||||||
<div>
|
|
||||||
<h1>Gravwell</h1>
|
|
||||||
<div class="sci-fi-box">
|
|
||||||
<h2>Multiplayer</h2>
|
|
||||||
<div class="flex-row">
|
|
||||||
<SciFiButton
|
|
||||||
on:click={joinGame}
|
|
||||||
>
|
|
||||||
Join Game
|
|
||||||
</SciFiButton>
|
|
||||||
<SciFiButton
|
|
||||||
on:click={hostGame}
|
|
||||||
>
|
|
||||||
Host Game
|
|
||||||
</SciFiButton>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<br>
|
|
||||||
<div class="sci-fi-box">
|
|
||||||
<h2>Singleplayer</h2>
|
|
||||||
<p>
|
|
||||||
Coming Soon
|
|
||||||
</p>
|
|
||||||
<div style="display: none;" class="flex-row">
|
|
||||||
<SciFiButton
|
|
||||||
on:click={singleplayerGame}
|
|
||||||
>
|
|
||||||
Start Game
|
|
||||||
</SciFiButton>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
main {
|
|
||||||
color: #FFFFFF;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
text-align: center;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 4rem;
|
|
||||||
font-weight: 100;
|
|
||||||
line-height: 1.1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sci-fi-box {
|
|
||||||
border-radius: 10px;
|
|
||||||
border-width: 2px;
|
|
||||||
border-style: solid;
|
|
||||||
border-color: white;
|
|
||||||
margin: 5px;
|
|
||||||
background: rgba(0, 0, 0, 0.5);
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
margin: 0px;
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.flex-row {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
.flex-row > :global(div) {
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 480px) {
|
|
||||||
h1 {
|
|
||||||
max-width: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,224 +0,0 @@
|
||||||
<script lang="ts">
|
|
||||||
import ShipDesigner from "../../components/modals/ShipDesigner.svelte";
|
|
||||||
import OptionInfo from "../../components/modals/OptionInfo.svelte";
|
|
||||||
import SciFiCheckbox from "../../components/SciFi-Checkbox.svelte";
|
|
||||||
import SciFiButton from "../../components/SciFi-Button.svelte";
|
|
||||||
import { ILobbyInfo, Status, gameOptions } from "common";
|
|
||||||
import Player from "../../components/Player.svelte";
|
|
||||||
import { isHost, players } from "../../stores";
|
|
||||||
import { socket } from "../../main";
|
|
||||||
import { onMount } from "svelte";
|
|
||||||
|
|
||||||
function handleLobbyInfo(data: ILobbyInfo) {
|
|
||||||
if (data.status == Status.Success) {
|
|
||||||
for (const player of data.players) {
|
|
||||||
$players[player.id] = player;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.table(data);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
onMount(() => {
|
|
||||||
socket.on(`res:lobby.info`, handleLobbyInfo);
|
|
||||||
return () => {
|
|
||||||
socket.off(`res:lobby.info`);
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
function tempButtonHandler() {};
|
|
||||||
|
|
||||||
// The modals that can appear in the lobby
|
|
||||||
const modal = {
|
|
||||||
options: false,
|
|
||||||
shipDesigner: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
$: visibleOptions = gameOptions.filter(x => !x.hidden);
|
|
||||||
|
|
||||||
/** Copies the game link to clipboard for easy sharing */
|
|
||||||
function copyLinkToClipboard() {
|
|
||||||
navigator.clipboard.writeText(window.location.href);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* What gets called when the host toggles one of the options in the lobby so
|
|
||||||
* that the other players can see the change happen on their screen.
|
|
||||||
*/
|
|
||||||
function toggleOption(e: CustomEvent<string>) {
|
|
||||||
let option = visibleOptions.find(x => x.id == e.detail);
|
|
||||||
console.debug(`Toggled option: ${option.name}`);
|
|
||||||
|
|
||||||
// TODO: Send websocket event to server
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<OptionInfo
|
|
||||||
open="{modal.options}"
|
|
||||||
{visibleOptions}
|
|
||||||
on:close="{_ => modal.options = false}"
|
|
||||||
/>
|
|
||||||
<ShipDesigner
|
|
||||||
open="{modal.shipDesigner}"
|
|
||||||
on:selectColour="{tempButtonHandler}"
|
|
||||||
on:close="{_ => modal.shipDesigner = false}"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<main>
|
|
||||||
<div>
|
|
||||||
<h1>Gravwell</h1>
|
|
||||||
<SciFiButton
|
|
||||||
width="69%"
|
|
||||||
on:click={copyLinkToClipboard}
|
|
||||||
>
|
|
||||||
Copy Game Link
|
|
||||||
</SciFiButton>
|
|
||||||
<div class="sci-fi-box">
|
|
||||||
<h2>Players</h2>
|
|
||||||
<div class="player-box">
|
|
||||||
{#each Object.entries($players) as [id, p], i (id)}
|
|
||||||
<Player
|
|
||||||
name="{p.name}"
|
|
||||||
colour="{p.colour}"
|
|
||||||
on:changeColour="{_ => modal.shipDesigner = true}"
|
|
||||||
/>
|
|
||||||
{#if i == 1}
|
|
||||||
<div class="divider"></div>
|
|
||||||
{/if}
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="sci-fi-box">
|
|
||||||
<div class="info-button-container">
|
|
||||||
<SciFiButton
|
|
||||||
on:click={_ => modal.options = true}
|
|
||||||
height="60px"
|
|
||||||
width="60px"
|
|
||||||
>
|
|
||||||
<div style="display: flex; align-items: center; justify-content: center;">
|
|
||||||
<span class="material-icons">help_outline</span>
|
|
||||||
</div>
|
|
||||||
</SciFiButton>
|
|
||||||
</div>
|
|
||||||
<h2>Options</h2>
|
|
||||||
<div class="options-box">
|
|
||||||
{#each visibleOptions as option}
|
|
||||||
<div>
|
|
||||||
<SciFiCheckbox
|
|
||||||
name="{option.name}"
|
|
||||||
id="{option.id}"
|
|
||||||
disabled="{!$isHost}"
|
|
||||||
bind:state="{option.active}"
|
|
||||||
on:toggle="{toggleOption}"
|
|
||||||
>
|
|
||||||
{option.name}
|
|
||||||
</SciFiCheckbox>
|
|
||||||
</div>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="flex-row">
|
|
||||||
<SciFiButton
|
|
||||||
title="Starts the game"
|
|
||||||
on:click={tempButtonHandler}
|
|
||||||
>
|
|
||||||
Start Game
|
|
||||||
</SciFiButton>
|
|
||||||
<SciFiButton
|
|
||||||
title="Delete the lobby, preventing further games from being played"
|
|
||||||
background="#ff0000"
|
|
||||||
on:click={tempButtonHandler}
|
|
||||||
>
|
|
||||||
Delete Game
|
|
||||||
</SciFiButton>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
main {
|
|
||||||
color: #FFFFFF;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
text-align: center;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 4rem;
|
|
||||||
font-weight: 100;
|
|
||||||
line-height: 1.1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.sci-fi-box {
|
|
||||||
border-radius: 10px;
|
|
||||||
border-width: 2px;
|
|
||||||
border-style: solid;
|
|
||||||
border-color: white;
|
|
||||||
margin: 5px;
|
|
||||||
background: rgba(0, 0, 0, 0.5);
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
margin: 10px 0px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.player-box {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
> .divider {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
> :global(div) {
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.options-box {
|
|
||||||
padding-bottom: 5px;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-evenly;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
|
|
||||||
> div {
|
|
||||||
background: rgba(255, 255, 255, 0.1);
|
|
||||||
border-radius: 5px;
|
|
||||||
padding: 3px 7px;
|
|
||||||
margin: 5px 5px 10px 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
> div:first-child {
|
|
||||||
margin-left: 10px;
|
|
||||||
}
|
|
||||||
> div:last-child {
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.info-button-container {
|
|
||||||
position: absolute;
|
|
||||||
top: -2px;
|
|
||||||
right: -2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.flex-row {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
.flex-row > :global(div) {
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 480px) {
|
|
||||||
h1 {
|
|
||||||
max-width: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,122 +0,0 @@
|
||||||
<script lang="ts">
|
|
||||||
import ShipsMoving from "../components/ShipsMoving.svelte";
|
|
||||||
import PlayerHand from "../components/PlayerHand.svelte";
|
|
||||||
import Board from "../components/Board.svelte";
|
|
||||||
import { board } from "../stores";
|
|
||||||
|
|
||||||
const controlsState: string = "player-order";
|
|
||||||
|
|
||||||
const notice = {
|
|
||||||
visible: false,
|
|
||||||
message: null,
|
|
||||||
classes: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
const preview = {
|
|
||||||
visible: false,
|
|
||||||
board: null,
|
|
||||||
};
|
|
||||||
function previewBoard(e: any) {
|
|
||||||
let { card, visible } = e.detail;
|
|
||||||
if (visible) {
|
|
||||||
notice.message = `This is a preview of what the board would look like if you played ${card.name}, it doesn't guarantee the outcome of playing the card.`;
|
|
||||||
notice.classes = [ `warning` ];
|
|
||||||
preview.board = [ ...$board ];
|
|
||||||
preview.board[Math.abs(card.magnitude)] = "a";
|
|
||||||
} else {
|
|
||||||
notice.message = null;
|
|
||||||
notice.classes = [];
|
|
||||||
preview.board = null;
|
|
||||||
};
|
|
||||||
preview.visible = visible;
|
|
||||||
notice.visible = visible;
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
|
|
||||||
<main>
|
|
||||||
{#if !preview.visible || !preview.board}
|
|
||||||
<div id="main-board">
|
|
||||||
<Board board="{$board}"/>
|
|
||||||
</div>
|
|
||||||
{:else}
|
|
||||||
<div id="preview-board">
|
|
||||||
<Board board="{preview.board}"/>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
{#if notice.visible}
|
|
||||||
<div id="notice-container">
|
|
||||||
<div class="notice {notice.classes.join(` `)}">
|
|
||||||
{notice.message}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
{#if controlsState == "player-hand"}
|
|
||||||
<div id="player-controls">
|
|
||||||
<PlayerHand
|
|
||||||
on:hover="{previewBoard}"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{:else if controlsState == "player-order"}
|
|
||||||
<div id="player-controls">
|
|
||||||
<ShipsMoving />
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</main>
|
|
||||||
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
main {
|
|
||||||
display: grid;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
grid-template-rows: 15px 70fr 75px 30fr 15px;
|
|
||||||
grid-template-columns: 15px 100fr 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#main-board {
|
|
||||||
grid-column: 2 / 3;
|
|
||||||
grid-row: 2 / 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
#preview-board {
|
|
||||||
z-index: 10;
|
|
||||||
grid-column: 2 / 3;
|
|
||||||
grid-row: 2 / 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
#notice-container {
|
|
||||||
align-items: center;
|
|
||||||
display: flex;
|
|
||||||
grid-column: 2 / 3;
|
|
||||||
grid-row: 3 / 4;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
.notice {
|
|
||||||
text-align: center;
|
|
||||||
align-items: center;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
width: 75%;
|
|
||||||
height: 90%;
|
|
||||||
border-radius: 10px;
|
|
||||||
|
|
||||||
&.warning {
|
|
||||||
background: yellowgreen;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.error {
|
|
||||||
background: red;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.info {
|
|
||||||
background: blue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#player-controls {
|
|
||||||
grid-column: 2 / 3;
|
|
||||||
grid-row: 4 / 5;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
2
web-svelte/src/vite-env.d.ts
vendored
|
|
@ -1,2 +0,0 @@
|
||||||
/// <reference types="svelte" />
|
|
||||||
/// <reference types="vite/client" />
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
import sveltePreprocess from "svelte-preprocess";
|
|
||||||
import * as sass from "sass";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
// Consult https://github.com/sveltejs/svelte-preprocess
|
|
||||||
// for more information about preprocessors
|
|
||||||
preprocess: sveltePreprocess({
|
|
||||||
sass: {
|
|
||||||
sync: true,
|
|
||||||
implementation: sass
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
{
|
|
||||||
"extends": "@tsconfig/svelte/tsconfig.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"target": "esnext",
|
|
||||||
"useDefineForClassFields": true,
|
|
||||||
"module": "esnext",
|
|
||||||
"resolveJsonModule": true,
|
|
||||||
"baseUrl": ".",
|
|
||||||
/**
|
|
||||||
* Typecheck JS in `.svelte` and `.js` files by default.
|
|
||||||
* Disable checkJs if you'd like to use dynamic types in JS.
|
|
||||||
* Note that setting allowJs false does not prevent the use
|
|
||||||
* of JS in `.svelte` files.
|
|
||||||
*/
|
|
||||||
"allowJs": true,
|
|
||||||
"checkJs": true
|
|
||||||
},
|
|
||||||
"include": ["src/**/*.d.ts", "src/**/*.ts", "src/**/*.js", "src/**/*.svelte"]
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
import { defineConfig } from 'vite'
|
|
||||||
import { svelte } from '@sveltejs/vite-plugin-svelte'
|
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
|
||||||
export default defineConfig({
|
|
||||||
plugins: [svelte()]
|
|
||||||
})
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
-100000 = Star Particle Layer
|
|
||||||
|
|
||||||
100 = Main Modal Layer
|
|
||||||
101 = Modal Content Layer
|
|
||||||