Things and støff
This commit is contained in:
@@ -1,9 +1,9 @@
|
|||||||
import WebSocket from "ws";
|
import WebSocket from "ws";
|
||||||
import { Player } from "./player.js";
|
import { Player } from "./player.js";
|
||||||
import * as msg from "../utils/messages.js";
|
|
||||||
import { mustBeString, mustBe } from "../utils/mustbe.js";
|
import { mustBeString, mustBe } from "../utils/mustbe.js";
|
||||||
import { Scene } from "../scenes/scene.js";
|
import { Scene } from "../scenes/scene.js";
|
||||||
import { gGame } from "./globals.js";
|
import { gGame } from "./globals.js";
|
||||||
|
import { formatMessage, MessageType } from "../utils/messages.js";
|
||||||
|
|
||||||
export class Session {
|
export class Session {
|
||||||
/** @type {WebSocket} */
|
/** @type {WebSocket} */
|
||||||
@@ -71,7 +71,7 @@ export class Session {
|
|||||||
/**
|
/**
|
||||||
* Send a message via our websocket.
|
* Send a message via our websocket.
|
||||||
*
|
*
|
||||||
* @param {string|number} messageType
|
* @param {MessageType} messageType The message "header" (the first arg in the array sent to the client) holds the message type.
|
||||||
* @param {...any} args
|
* @param {...any} args
|
||||||
*/
|
*/
|
||||||
send(messageType, ...args) {
|
send(messageType, ...args) {
|
||||||
@@ -79,7 +79,7 @@ export class Session {
|
|||||||
console.error("Trying to send a message without a valid websocket", messageType, args);
|
console.error("Trying to send a message without a valid websocket", messageType, args);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._websocket.send(JSON.stringify([messageType, ...args]));
|
this._websocket.send(formatMessage(messageType, ...args));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -100,7 +100,7 @@ export class Session {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.send(
|
this.send(
|
||||||
msg.PROMPT, // message type
|
MessageType.PROMPT, // message type
|
||||||
text, // TODO: prompt text must be string or an array of strings
|
text, // TODO: prompt text must be string or an array of strings
|
||||||
mustBe(options, "object"),
|
mustBe(options, "object"),
|
||||||
);
|
);
|
||||||
@@ -113,12 +113,12 @@ export class Session {
|
|||||||
* @param {object?} options message options for the client.
|
* @param {object?} options message options for the client.
|
||||||
*/
|
*/
|
||||||
sendText(text, options = {}) {
|
sendText(text, options = {}) {
|
||||||
this.send(msg.TEXT, text, options);
|
this.send(MessageType.TEXT, text, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param {string|string[]} errorMessage */
|
/** @param {string|string[]} errorMessage */
|
||||||
sendError(errorMessage) {
|
sendError(errorMessage, options = { verbatim: true }) {
|
||||||
this.send(msg.ERROR, mustBeString(errorMessage));
|
this.send(MessageType.ERROR, mustBeString(errorMessage), options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -128,15 +128,15 @@ export class Session {
|
|||||||
calamity(errorMessage) {
|
calamity(errorMessage) {
|
||||||
//
|
//
|
||||||
// The client should know not to format calamaties anyway, but we add “preformatted” anyway
|
// The client should know not to format calamaties anyway, but we add “preformatted” anyway
|
||||||
this.send(msg.CALAMITY, errorMessage, { preformatted: true });
|
this.send(MessageType.CALAMITY, errorMessage, { preformatted: true });
|
||||||
this.close();
|
this.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} systemMessageType
|
* @param {MessageType} systemMessageType
|
||||||
* @param {any?} value
|
* @param {any?} value
|
||||||
*/
|
*/
|
||||||
sendSystemMessage(systemMessageType, value = undefined) {
|
sendSystemMessage(systemMessageType, value = undefined) {
|
||||||
this.send(msg.SYSTEM, mustBeString(systemMessageType), value);
|
this.send(MessageType.SYSTEM, mustBeString(systemMessageType), value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
889
server/package-lock.json
generated
889
server/package-lock.json
generated
@@ -1,446 +1,453 @@
|
|||||||
{
|
{
|
||||||
"name": "websocket-mud",
|
"name": "websocket-mud",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "websocket-mud",
|
"name": "websocket-mud",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"figlet": "^1.8.2",
|
"figlet": "^1.8.2",
|
||||||
"ws": "^8.14.2"
|
"sprintf-js": "^1.1.3",
|
||||||
},
|
"ws": "^8.14.2"
|
||||||
"devDependencies": {
|
},
|
||||||
"nodemon": "^3.0.1",
|
"devDependencies": {
|
||||||
"prettier": "3.6.2"
|
"nodemon": "^3.0.1",
|
||||||
},
|
"prettier": "3.6.2"
|
||||||
"engines": {
|
},
|
||||||
"node": ">=14.0.0"
|
"engines": {
|
||||||
}
|
"node": ">=14.0.0"
|
||||||
},
|
}
|
||||||
"node_modules/anymatch": {
|
|
||||||
"version": "3.1.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
|
|
||||||
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "ISC",
|
|
||||||
"dependencies": {
|
|
||||||
"normalize-path": "^3.0.0",
|
|
||||||
"picomatch": "^2.0.4"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/balanced-match": {
|
|
||||||
"version": "1.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
|
||||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/binary-extensions": {
|
|
||||||
"version": "2.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
|
|
||||||
"integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/brace-expansion": {
|
|
||||||
"version": "1.1.12",
|
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
|
||||||
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"balanced-match": "^1.0.0",
|
|
||||||
"concat-map": "0.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/braces": {
|
|
||||||
"version": "3.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
|
|
||||||
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"fill-range": "^7.1.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/chokidar": {
|
|
||||||
"version": "3.6.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
|
|
||||||
"integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"anymatch": "~3.1.2",
|
|
||||||
"braces": "~3.0.2",
|
|
||||||
"glob-parent": "~5.1.2",
|
|
||||||
"is-binary-path": "~2.1.0",
|
|
||||||
"is-glob": "~4.0.1",
|
|
||||||
"normalize-path": "~3.0.0",
|
|
||||||
"readdirp": "~3.6.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 8.10.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://paulmillr.com/funding/"
|
|
||||||
},
|
|
||||||
"optionalDependencies": {
|
|
||||||
"fsevents": "~2.3.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/concat-map": {
|
|
||||||
"version": "0.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
|
||||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/debug": {
|
|
||||||
"version": "4.4.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
|
|
||||||
"integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"ms": "^2.1.3"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6.0"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"supports-color": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/figlet": {
|
|
||||||
"version": "1.8.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/figlet/-/figlet-1.8.2.tgz",
|
|
||||||
"integrity": "sha512-iPCpE9B/rOcjewIzDnagP9F2eySzGeHReX8WlrZQJkqFBk2wvq8gY0c6U6Hd2y9HnX1LQcYSeP7aEHoPt6sVKQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"bin": {
|
|
||||||
"figlet": "bin/index.js"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.4.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/fill-range": {
|
|
||||||
"version": "7.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
|
||||||
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"to-regex-range": "^5.0.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/fsevents": {
|
|
||||||
"version": "2.3.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
|
||||||
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
|
|
||||||
"dev": true,
|
|
||||||
"hasInstallScript": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"darwin"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/glob-parent": {
|
|
||||||
"version": "5.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
|
||||||
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "ISC",
|
|
||||||
"dependencies": {
|
|
||||||
"is-glob": "^4.0.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/has-flag": {
|
|
||||||
"version": "3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
|
||||||
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/ignore-by-default": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
|
|
||||||
"integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "ISC"
|
|
||||||
},
|
|
||||||
"node_modules/is-binary-path": {
|
|
||||||
"version": "2.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
|
||||||
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"binary-extensions": "^2.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/is-extglob": {
|
|
||||||
"version": "2.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
|
||||||
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.10.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/is-glob": {
|
|
||||||
"version": "4.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
|
||||||
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"is-extglob": "^2.1.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.10.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/is-number": {
|
|
||||||
"version": "7.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
|
||||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.12.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/minimatch": {
|
|
||||||
"version": "3.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
|
||||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "ISC",
|
|
||||||
"dependencies": {
|
|
||||||
"brace-expansion": "^1.1.7"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "*"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/ms": {
|
|
||||||
"version": "2.1.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
|
||||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/nodemon": {
|
|
||||||
"version": "3.1.10",
|
|
||||||
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.10.tgz",
|
|
||||||
"integrity": "sha512-WDjw3pJ0/0jMFmyNDp3gvY2YizjLmmOUQo6DEBY+JgdvW/yQ9mEeSw6H5ythl5Ny2ytb7f9C2nIbjSxMNzbJXw==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"chokidar": "^3.5.2",
|
|
||||||
"debug": "^4",
|
|
||||||
"ignore-by-default": "^1.0.1",
|
|
||||||
"minimatch": "^3.1.2",
|
|
||||||
"pstree.remy": "^1.1.8",
|
|
||||||
"semver": "^7.5.3",
|
|
||||||
"simple-update-notifier": "^2.0.0",
|
|
||||||
"supports-color": "^5.5.0",
|
|
||||||
"touch": "^3.1.0",
|
|
||||||
"undefsafe": "^2.0.5"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"nodemon": "bin/nodemon.js"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/nodemon"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/normalize-path": {
|
|
||||||
"version": "3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
|
||||||
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.10.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/picomatch": {
|
|
||||||
"version": "2.3.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
|
||||||
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8.6"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/jonschlinkert"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/prettier": {
|
|
||||||
"version": "3.6.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz",
|
|
||||||
"integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"bin": {
|
|
||||||
"prettier": "bin/prettier.cjs"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=14"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/prettier/prettier?sponsor=1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/pstree.remy": {
|
|
||||||
"version": "1.1.8",
|
|
||||||
"resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz",
|
|
||||||
"integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/readdirp": {
|
|
||||||
"version": "3.6.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
|
||||||
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"picomatch": "^2.2.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8.10.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/semver": {
|
|
||||||
"version": "7.7.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
|
|
||||||
"integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "ISC",
|
|
||||||
"bin": {
|
|
||||||
"semver": "bin/semver.js"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/simple-update-notifier": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"semver": "^7.5.3"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/supports-color": {
|
|
||||||
"version": "5.5.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
|
||||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"has-flag": "^3.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/to-regex-range": {
|
|
||||||
"version": "5.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
|
||||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"is-number": "^7.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/touch": {
|
|
||||||
"version": "3.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz",
|
|
||||||
"integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "ISC",
|
|
||||||
"bin": {
|
|
||||||
"nodetouch": "bin/nodetouch.js"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/undefsafe": {
|
|
||||||
"version": "2.0.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz",
|
|
||||||
"integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/ws": {
|
|
||||||
"version": "8.18.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz",
|
|
||||||
"integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==",
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10.0.0"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"bufferutil": "^4.0.1",
|
|
||||||
"utf-8-validate": ">=5.0.2"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"bufferutil": {
|
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"utf-8-validate": {
|
"node_modules/anymatch": {
|
||||||
"optional": true
|
"version": "3.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
|
||||||
|
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"normalize-path": "^3.0.0",
|
||||||
|
"picomatch": "^2.0.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/balanced-match": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/binary-extensions": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
|
||||||
|
"integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/brace-expansion": {
|
||||||
|
"version": "1.1.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||||
|
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"balanced-match": "^1.0.0",
|
||||||
|
"concat-map": "0.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/braces": {
|
||||||
|
"version": "3.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
|
||||||
|
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"fill-range": "^7.1.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/chokidar": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"anymatch": "~3.1.2",
|
||||||
|
"braces": "~3.0.2",
|
||||||
|
"glob-parent": "~5.1.2",
|
||||||
|
"is-binary-path": "~2.1.0",
|
||||||
|
"is-glob": "~4.0.1",
|
||||||
|
"normalize-path": "~3.0.0",
|
||||||
|
"readdirp": "~3.6.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8.10.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"fsevents": "~2.3.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/concat-map": {
|
||||||
|
"version": "0.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||||
|
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/debug": {
|
||||||
|
"version": "4.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
|
||||||
|
"integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"ms": "^2.1.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"supports-color": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/figlet": {
|
||||||
|
"version": "1.8.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/figlet/-/figlet-1.8.2.tgz",
|
||||||
|
"integrity": "sha512-iPCpE9B/rOcjewIzDnagP9F2eySzGeHReX8WlrZQJkqFBk2wvq8gY0c6U6Hd2y9HnX1LQcYSeP7aEHoPt6sVKQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"figlet": "bin/index.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/fill-range": {
|
||||||
|
"version": "7.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
||||||
|
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"to-regex-range": "^5.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/fsevents": {
|
||||||
|
"version": "2.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||||
|
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
|
||||||
|
"dev": true,
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/glob-parent": {
|
||||||
|
"version": "5.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||||
|
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"is-glob": "^4.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/has-flag": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ignore-by-default": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
|
"node_modules/is-binary-path": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"binary-extensions": "^2.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-extglob": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-glob": {
|
||||||
|
"version": "4.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
||||||
|
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"is-extglob": "^2.1.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-number": {
|
||||||
|
"version": "7.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||||
|
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.12.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/minimatch": {
|
||||||
|
"version": "3.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||||
|
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"brace-expansion": "^1.1.7"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ms": {
|
||||||
|
"version": "2.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
|
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/nodemon": {
|
||||||
|
"version": "3.1.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.10.tgz",
|
||||||
|
"integrity": "sha512-WDjw3pJ0/0jMFmyNDp3gvY2YizjLmmOUQo6DEBY+JgdvW/yQ9mEeSw6H5ythl5Ny2ytb7f9C2nIbjSxMNzbJXw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"chokidar": "^3.5.2",
|
||||||
|
"debug": "^4",
|
||||||
|
"ignore-by-default": "^1.0.1",
|
||||||
|
"minimatch": "^3.1.2",
|
||||||
|
"pstree.remy": "^1.1.8",
|
||||||
|
"semver": "^7.5.3",
|
||||||
|
"simple-update-notifier": "^2.0.0",
|
||||||
|
"supports-color": "^5.5.0",
|
||||||
|
"touch": "^3.1.0",
|
||||||
|
"undefsafe": "^2.0.5"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"nodemon": "bin/nodemon.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/nodemon"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/normalize-path": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/picomatch": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
||||||
|
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.6"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/jonschlinkert"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/prettier": {
|
||||||
|
"version": "3.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz",
|
||||||
|
"integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"prettier": "bin/prettier.cjs"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/prettier/prettier?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/pstree.remy": {
|
||||||
|
"version": "1.1.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz",
|
||||||
|
"integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/readdirp": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"picomatch": "^2.2.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/semver": {
|
||||||
|
"version": "7.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
|
||||||
|
"integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"bin": {
|
||||||
|
"semver": "bin/semver.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/simple-update-notifier": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"semver": "^7.5.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/sprintf-js": {
|
||||||
|
"version": "1.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
|
||||||
|
"integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==",
|
||||||
|
"license": "BSD-3-Clause"
|
||||||
|
},
|
||||||
|
"node_modules/supports-color": {
|
||||||
|
"version": "5.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||||
|
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"has-flag": "^3.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/to-regex-range": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"is-number": "^7.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/touch": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"bin": {
|
||||||
|
"nodetouch": "bin/nodetouch.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/undefsafe": {
|
||||||
|
"version": "2.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz",
|
||||||
|
"integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/ws": {
|
||||||
|
"version": "8.18.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz",
|
||||||
|
"integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"figlet": "^1.8.2",
|
"figlet": "^1.8.2",
|
||||||
|
"sprintf-js": "^1.1.3",
|
||||||
"ws": "^8.14.2"
|
"ws": "^8.14.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -33,7 +34,6 @@
|
|||||||
"quoteProps": "consistent",
|
"quoteProps": "consistent",
|
||||||
"singleQuote": false,
|
"singleQuote": false,
|
||||||
"trailingComma": "all",
|
"trailingComma": "all",
|
||||||
"tabWidth": 4,
|
|
||||||
"bracketSpacing": true,
|
"bracketSpacing": true,
|
||||||
"objectWrap": "preserve",
|
"objectWrap": "preserve",
|
||||||
"arrowParens": "always"
|
"arrowParens": "always"
|
||||||
|
|||||||
BIN
server/public/android-chrome-192x192.png
Normal file
BIN
server/public/android-chrome-192x192.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 55 KiB |
BIN
server/public/android-chrome-512x512.png
Normal file
BIN
server/public/android-chrome-512x512.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 448 KiB |
BIN
server/public/apple-touch-icon.png
Normal file
BIN
server/public/apple-touch-icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 49 KiB |
@@ -1,11 +1,16 @@
|
|||||||
import { crackdown } from "./crackdown.js";
|
import { crackdown } from "./crackdown.js";
|
||||||
|
import { parseArgs } from "./parseArgs.js";
|
||||||
|
import { MessageType } from "./messages.js";
|
||||||
|
|
||||||
const MsgContext.REPLY = "R";
|
/** Regex to validate if a :help [topic] command i entered correctly */
|
||||||
const QUIT = "QUIT";
|
|
||||||
const HELP = "HELP";
|
|
||||||
const COLON = ":";
|
|
||||||
const helpRegex = /^:help(?:\s+(.*))?$/;
|
const helpRegex = /^:help(?:\s+(.*))?$/;
|
||||||
const colonRegex = /^:([a-z0-9_]+)(?:\s+(.*))?$/;
|
|
||||||
|
/** Regex to validate if a :<command> [args] was entered correctly */
|
||||||
|
const colonRegex = /^:([a-z0-9_]+)(?:\s+(.*?)\s*)?$/;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The client that talks to the MUD Sever
|
||||||
|
*/
|
||||||
class MUDClient {
|
class MUDClient {
|
||||||
//
|
//
|
||||||
// Constructor
|
// Constructor
|
||||||
@@ -14,7 +19,7 @@ class MUDClient {
|
|||||||
this.websocket = null;
|
this.websocket = null;
|
||||||
|
|
||||||
/** @type {boolean} Are we in development mode (decided by the server); */
|
/** @type {boolean} Are we in development mode (decided by the server); */
|
||||||
this.dev = false;
|
this.isDev = false;
|
||||||
|
|
||||||
this.promptOptions = {};
|
this.promptOptions = {};
|
||||||
this.shouldReply = false;
|
this.shouldReply = false;
|
||||||
@@ -176,8 +181,8 @@ class MUDClient {
|
|||||||
//
|
//
|
||||||
// The quit command has its own message type
|
// The quit command has its own message type
|
||||||
if (inputText === ":quit") {
|
if (inputText === ":quit") {
|
||||||
this.send(QUIT);
|
this.send(MessageType.QUIT);
|
||||||
this.writeToOutput("> " + inputText, { class: "input" });
|
this.writeToOutput("> " + inputText, { verbatim: true, class: "input" });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,8 +198,8 @@ class MUDClient {
|
|||||||
let help = helpRegex.exec(inputText);
|
let help = helpRegex.exec(inputText);
|
||||||
if (help) {
|
if (help) {
|
||||||
console.log("here");
|
console.log("here");
|
||||||
help[1] ? this.send(HELP, help[1].trim()) : this.send(HELP);
|
help[1] ? this.send(MshType.HELP, help[1].trim()) : this.send(MshType.HELP);
|
||||||
this.writeToOutput("> " + inputText, { class: "input" });
|
this.writeToOutput("> " + inputText, { verbatim: true, class: "input" });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,19 +209,14 @@ class MUDClient {
|
|||||||
// _ | (_| (_) | | | | | | | | | | | (_| | | | | (_| |
|
// _ | (_| (_) | | | | | | | | | | | (_| | | | | (_| |
|
||||||
// (_) \___\___/|_| |_| |_|_| |_| |_|\__,_|_| |_|\__,_|
|
// (_) \___\___/|_| |_| |_|_| |_| |_|\__,_|_| |_|\__,_|
|
||||||
//------------------------------------------------------
|
//------------------------------------------------------
|
||||||
let colonCommand = colonRegex.exec(inputText);
|
const colon = colonRegex.exec(inputText);
|
||||||
if (colonCommand) {
|
if (colon) {
|
||||||
this.send(COLON, colonCommand[1], colonCommand[2]);
|
const args = typeof colon[2] === "string" ? parseArgs(colon[2]) : [];
|
||||||
this.writeToOutput("> " + inputText, { class: "input" });
|
this.send(MessageType.COLON, colon[1], args);
|
||||||
|
this.writeToOutput("> " + inputText, { verbatim: true, class: "input colon" });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// The server doesn't want any input from us, so we just ignore this input
|
|
||||||
if (!this.shouldReply) {
|
|
||||||
// the server is not ready for data!
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// _
|
// _
|
||||||
// _ __ ___ _ __ | |_ _
|
// _ __ ___ _ __ | |_ _
|
||||||
// | '__/ _ \ '_ \| | | | |
|
// | '__/ _ \ '_ \| | | | |
|
||||||
@@ -227,6 +227,12 @@ class MUDClient {
|
|||||||
// We handle replies below
|
// We handle replies below
|
||||||
//-------------------------
|
//-------------------------
|
||||||
|
|
||||||
|
//
|
||||||
|
if (!this.shouldReply) {
|
||||||
|
// the server is not ready for data!
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// The server wants a password, let's hash it before sending it.
|
// The server wants a password, let's hash it before sending it.
|
||||||
if (this.promptOptions.password) {
|
if (this.promptOptions.password) {
|
||||||
inputText = await this.hashPassword(inputText);
|
inputText = await this.hashPassword(inputText);
|
||||||
@@ -238,14 +244,14 @@ class MUDClient {
|
|||||||
this.username = inputText;
|
this.username = inputText;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.send(REPLY, inputText);
|
this.send(MessageType.REPLY, inputText);
|
||||||
this.shouldReply = false;
|
this.shouldReply = false;
|
||||||
this.promptOptions = {};
|
this.promptOptions = {};
|
||||||
|
|
||||||
//
|
//
|
||||||
// We add our own command to the output stream so the
|
// We add our own command to the output stream so the
|
||||||
// player can see what they typed.
|
// player can see what they typed.
|
||||||
this.writeToOutput("> " + inputText, { class: "input" });
|
this.writeToOutput("> " + inputText, { verbatim: true, class: "input" });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,7 +263,7 @@ class MUDClient {
|
|||||||
//
|
//
|
||||||
/** @param {any[]} data*/
|
/** @param {any[]} data*/
|
||||||
onMessageReceived(data) {
|
onMessageReceived(data) {
|
||||||
if (this.dev) {
|
if (this.isDev) {
|
||||||
console.debug(data);
|
console.debug(data);
|
||||||
}
|
}
|
||||||
const messageType = data.shift();
|
const messageType = data.shift();
|
||||||
@@ -291,7 +297,7 @@ class MUDClient {
|
|||||||
return this.handleDebugMessages(data);
|
return this.handleDebugMessages(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.dev) {
|
if (this.isDev) {
|
||||||
this.writeToOutput(`unknown message type: ${messageType}: ${JSON.stringify(data)}`, {
|
this.writeToOutput(`unknown message type: ${messageType}: ${JSON.stringify(data)}`, {
|
||||||
class: "debug",
|
class: "debug",
|
||||||
verbatim: true,
|
verbatim: true,
|
||||||
@@ -314,7 +320,7 @@ class MUDClient {
|
|||||||
// Debug messages let the server send data to be displayed on the player's screen
|
// Debug messages let the server send data to be displayed on the player's screen
|
||||||
// and also logged to the players browser's log.
|
// and also logged to the players browser's log.
|
||||||
handleDebugMessages(data) {
|
handleDebugMessages(data) {
|
||||||
if (!this.dev) {
|
if (!this.isDev) {
|
||||||
return; // debug messages are thrown away if we're not in dev mode.
|
return; // debug messages are thrown away if we're not in dev mode.
|
||||||
}
|
}
|
||||||
this.writeToOutput(data, { class: "debug", verbatim: true });
|
this.writeToOutput(data, { class: "debug", verbatim: true });
|
||||||
@@ -332,16 +338,16 @@ class MUDClient {
|
|||||||
console.debug("Incoming system message", data);
|
console.debug("Incoming system message", data);
|
||||||
|
|
||||||
/** @type {string} */
|
/** @type {string} */
|
||||||
const messageType = data.shift();
|
const systemMessageType = data.shift();
|
||||||
|
|
||||||
switch (messageType) {
|
switch (systemMessageType) {
|
||||||
case "username":
|
case "username":
|
||||||
this.username = data[0];
|
this.username = data[0];
|
||||||
break;
|
break;
|
||||||
case "dev":
|
case "dev":
|
||||||
// This is a message that tells us that the server is in
|
// This is a message that tells us that the server is in
|
||||||
// "dev" mode, and that we should do the same.
|
// "dev" mode, and that we should do the same.
|
||||||
this.dev = data[0];
|
this.isDev = !!data[0];
|
||||||
this.status.textContent = "[DEV] " + this.status.textContent;
|
this.status.textContent = "[DEV] " + this.status.textContent;
|
||||||
break;
|
break;
|
||||||
case "salt":
|
case "salt":
|
||||||
@@ -349,12 +355,12 @@ class MUDClient {
|
|||||||
console.debug("updating crypto salt", data[0]);
|
console.debug("updating crypto salt", data[0]);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
console.debug("unknown system message", messageType, data);
|
console.debug("unknown system message", systemMessageType, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're in dev mode, we should output all system messages (in a shaded/faint fashion).
|
// If we're in dev mode, we should output all system messages (in a shaded/faint fashion).
|
||||||
if (this.dev) {
|
if (this.isDev) {
|
||||||
this.writeToOutput(`system message: ${messageType} = ${JSON.stringify(data)}`, { class: "debug" });
|
this.writeToOutput(`system message: ${systemMessageType} = ${JSON.stringify(data)}`, { class: "debug" });
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -436,7 +442,7 @@ class MUDClient {
|
|||||||
* @param {string} className
|
* @param {string} className
|
||||||
*/
|
*/
|
||||||
updateStatus(message, className) {
|
updateStatus(message, className) {
|
||||||
this.status.textContent = this.dev ? `[DEV] Status: ${message}` : `Status: ${message}`;
|
this.status.textContent = this.isDev ? `[DEV] Status: ${message}` : `Status: ${message}`;
|
||||||
this.status.className = className;
|
this.status.className = className;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
server/public/favicon-16x16.png
Normal file
BIN
server/public/favicon-16x16.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 783 B |
BIN
server/public/favicon-32x32.png
Normal file
BIN
server/public/favicon-32x32.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.4 KiB |
BIN
server/public/favicon.ico
Normal file
BIN
server/public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
1
server/public/messages.js
Symbolic link
1
server/public/messages.js
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../utils/messages.js
|
||||||
1
server/public/mustbe.js
Symbolic link
1
server/public/mustbe.js
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../utils/mustbe.js
|
||||||
@@ -1,5 +1,3 @@
|
|||||||
import { mustBeString } from "./mustbe.js";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse a command string into arguments. For use with colon-commands.
|
* Parse a command string into arguments. For use with colon-commands.
|
||||||
*
|
*
|
||||||
@@ -7,7 +5,9 @@ import { mustBeString } from "./mustbe.js";
|
|||||||
* @returns {(string|number)[]} Command arguments
|
* @returns {(string|number)[]} Command arguments
|
||||||
*/
|
*/
|
||||||
export function parseArgs(cmdString) {
|
export function parseArgs(cmdString) {
|
||||||
mustBeString(cmdString);
|
if (typeof cmdString === "string") {
|
||||||
|
throw new Error("Expected string. GoT a finger in the eye instead");
|
||||||
|
}
|
||||||
const args = [];
|
const args = [];
|
||||||
const quoteChars = ["'", '"', "`"];
|
const quoteChars = ["'", '"', "`"];
|
||||||
const backslash = "\\";
|
const backslash = "\\";
|
||||||
@@ -16,7 +16,8 @@ export function parseArgs(cmdString) {
|
|||||||
let inQuotes = false; // are we inside quotes of some kind?
|
let inQuotes = false; // are we inside quotes of some kind?
|
||||||
let currentQuoteChar = ""; // if were in quotes, which are they?
|
let currentQuoteChar = ""; // if were in quotes, which are they?
|
||||||
|
|
||||||
const push = (value) => {
|
// helper function
|
||||||
|
const pushVal = (value) => {
|
||||||
const n = Number(value);
|
const n = Number(value);
|
||||||
if (Number.isSafeInteger(n)) {
|
if (Number.isSafeInteger(n)) {
|
||||||
args.push(n);
|
args.push(n);
|
||||||
@@ -39,7 +40,7 @@ export function parseArgs(cmdString) {
|
|||||||
} else if (char === " " || char === "\t") {
|
} else if (char === " " || char === "\t") {
|
||||||
// Whitespace - end current arg if it exists
|
// Whitespace - end current arg if it exists
|
||||||
if (currentArg) {
|
if (currentArg) {
|
||||||
push(currentArg);
|
pushVal(currentArg);
|
||||||
currentArg = "";
|
currentArg = "";
|
||||||
}
|
}
|
||||||
// Skip multiple whitespace
|
// Skip multiple whitespace
|
||||||
@@ -68,7 +69,7 @@ export function parseArgs(cmdString) {
|
|||||||
|
|
||||||
// Add final argument if exists
|
// Add final argument if exists
|
||||||
if (currentArg) {
|
if (currentArg) {
|
||||||
push(currentArg);
|
pushVal(currentArg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentQuoteChar) {
|
if (currentQuoteChar) {
|
||||||
@@ -79,5 +80,3 @@ export function parseArgs(cmdString) {
|
|||||||
|
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(parseArgs("\"k1m er '-9 ' `anus pikke`"));
|
|
||||||
1
server/public/site.webmanifest
Normal file
1
server/public/site.webmanifest
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
|
||||||
@@ -2,10 +2,10 @@ import { PasswordPrompt } from "./passwordPrompt.js";
|
|||||||
import { Player } from "../../models/player.js";
|
import { Player } from "../../models/player.js";
|
||||||
import { Scene } from "../scene.js";
|
import { Scene } from "../scene.js";
|
||||||
import { UsernamePrompt } from "./usernamePrompt.js";
|
import { UsernamePrompt } from "./usernamePrompt.js";
|
||||||
|
import { CreateUsernamePrompt } from "../playerCreation/createUsernamePrompt.js";
|
||||||
|
|
||||||
/** @property {Session} session */
|
/** @property {Session} session */
|
||||||
export class AuthenticationScene extends Scene {
|
export class AuthenticationScene extends Scene {
|
||||||
|
|
||||||
introText = [
|
introText = [
|
||||||
"= Welcome", //
|
"= Welcome", //
|
||||||
];
|
];
|
||||||
@@ -15,13 +15,13 @@ export class AuthenticationScene extends Scene {
|
|||||||
|
|
||||||
onReady() {
|
onReady() {
|
||||||
// current prompt
|
// current prompt
|
||||||
this.doPrompt(new UsernamePrompt(this));
|
this.show(UsernamePrompt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param {Player} player */
|
/** @param {Player} player */
|
||||||
usernameAccepted(player) {
|
usernameAccepted(player) {
|
||||||
this.player = player;
|
this.player = player;
|
||||||
this.doPrompt(new PasswordPrompt(this));
|
this.show(PasswordPrompt);
|
||||||
}
|
}
|
||||||
|
|
||||||
passwordAccepted() {
|
passwordAccepted() {
|
||||||
@@ -34,4 +34,8 @@ export class AuthenticationScene extends Scene {
|
|||||||
this.session.setScene("new JustLoggedInScene");
|
this.session.setScene("new JustLoggedInScene");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createPlayer() {
|
||||||
|
scene.session.setScene(new PlayerCreationScene(this.scene));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { Prompt } from "../prompt.js";
|
import { Prompt } from "../prompt.js";
|
||||||
import * as security from "../../utils/security.js";
|
import * as security from "../../utils/security.js";
|
||||||
import { Config } from "../../config.js";
|
import { Config } from "../../config.js";
|
||||||
import { context } from "../../utils/messages.js";
|
|
||||||
|
|
||||||
export class PasswordPrompt extends Prompt {
|
export class PasswordPrompt extends Prompt {
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,11 +1,16 @@
|
|||||||
import { Player } from "../../models/player.js";
|
import { Player } from "../../models/player.js";
|
||||||
import { Prompt } from "../prompt.js";
|
import { Prompt } from "../prompt.js";
|
||||||
import * as security from "../../utils/security.js";
|
import * as security from "../../utils/security.js";
|
||||||
import { context } from "../../utils/messages.js";
|
|
||||||
import { gGame } from "../../models/globals.js";
|
import { gGame } from "../../models/globals.js";
|
||||||
import { PlayerCreationScene } from "../playerCreation/playerCreationSene.js";
|
import { PlayerCreationScene } from "../playerCreation/playerCreationSene.js";
|
||||||
import { Config } from "../../config.js";
|
import { Config } from "../../config.js";
|
||||||
|
import { AuthenticationScene } from "./authenticationScene.js";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class
|
||||||
|
*
|
||||||
|
* @property {AuthenticationScene} scene
|
||||||
|
*/
|
||||||
export class UsernamePrompt extends Prompt {
|
export class UsernamePrompt extends Prompt {
|
||||||
//
|
//
|
||||||
promptText = [
|
promptText = [
|
||||||
@@ -24,17 +29,14 @@ export class UsernamePrompt extends Prompt {
|
|||||||
// Let the client know that we're asking for a username
|
// Let the client know that we're asking for a username
|
||||||
promptOptions = { username: true };
|
promptOptions = { username: true };
|
||||||
|
|
||||||
//
|
/** @returns {AuthenticationScene} */
|
||||||
// User entered ":create"
|
get scene() {
|
||||||
onColon_create() {
|
return this._scene;
|
||||||
// User creation scene.
|
|
||||||
this.scene.session.setScene(new PlayerCreationScene(this.scene));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// User replied to our prompt
|
// User replied to our prompt
|
||||||
onReply(text) {
|
onReply(text) {
|
||||||
|
|
||||||
//
|
//
|
||||||
// do basic syntax checks on usernames
|
// do basic syntax checks on usernames
|
||||||
if (!security.isUsernameSane(text)) {
|
if (!security.isUsernameSane(text)) {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { Prompt } from "../prompt.js";
|
import { Prompt } from "../prompt.js";
|
||||||
import * as security from "../../utils/security.js";
|
import * as security from "../../utils/security.js";
|
||||||
import { Config } from "../../config.js";
|
import { Config } from "../../config.js";
|
||||||
import { context } from "../../utils/messages.js";
|
|
||||||
|
|
||||||
export class CreatePasswordPrompt extends Prompt {
|
export class CreatePasswordPrompt extends Prompt {
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export class PlayerCreationScene extends Scene {
|
|||||||
this.session.calamity("Server is full, no more players can be created");
|
this.session.calamity("Server is full, no more players can be created");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.doPrompt(new CreateUsernamePrompt(this));
|
this.showPrompt(new CreateUsernamePrompt(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -27,13 +27,13 @@ export class PlayerCreationScene extends Scene {
|
|||||||
*
|
*
|
||||||
* @param {string} username
|
* @param {string} username
|
||||||
*/
|
*/
|
||||||
onUsernameAccepted(username) {
|
usernameAccepted(username) {
|
||||||
const player = gGame.createPlayer(username);
|
const player = gGame.createPlayer(username);
|
||||||
this.player = player;
|
this.player = player;
|
||||||
|
|
||||||
this.session.sendSystemMessage("salt", player.salt);
|
this.session.sendSystemMessage("salt", player.salt);
|
||||||
this.session.sendText(`Username _*${username}*_ is available, and I've reserved it for you :)`);
|
this.session.sendText(`Username _*${username}*_ is available, and I've reserved it for you :)`);
|
||||||
this.doPrompt("new passwordprompt");
|
this.showPrompt("new passwordprompt");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -42,9 +42,15 @@ export class PlayerCreationScene extends Scene {
|
|||||||
*
|
*
|
||||||
* @param {string} password
|
* @param {string} password
|
||||||
*/
|
*/
|
||||||
onPasswordAccepted(password) {
|
passwordAccepted(password) {
|
||||||
this.password = password;
|
this.password = password;
|
||||||
this.session.sendText("*_Success_* ✅ You will now be asked to log in again, sorry for that ;)");
|
this.session.sendText("*_Success_* ✅ You will now be asked to log in again, sorry for that ;)");
|
||||||
this.player.setPasswordHash(security.generateHash(this.password));
|
this.player.setPasswordHash(security.generateHash(this.password));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// User entered ":create"
|
||||||
|
onColon__create() {
|
||||||
|
this.scene.createPlayer();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import figlet from "figlet";
|
import figlet from "figlet";
|
||||||
import { gGame } from "../models/globals.js";
|
import { gGame } from "../models/globals.js";
|
||||||
import * as msg from "../utils/messages.js";
|
|
||||||
import { Session } from "../models/session.js";
|
import { Session } from "../models/session.js";
|
||||||
import { Scene } from "./scene.js";
|
import { Scene } from "./scene.js";
|
||||||
import { WebsocketMessage } from "../utils/messages.js";
|
import { MessageType, WebsocketMessage } from "../utils/messages.js";
|
||||||
import { mustBe, mustBeString } from "../utils/mustbe.js";
|
import { mustBe, mustBeString } from "../utils/mustbe.js";
|
||||||
|
import { sprintf } from "sprintf-js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {object} PromptMethods
|
* @typedef {object} PromptMethods
|
||||||
@@ -19,8 +19,13 @@ import { mustBe, mustBeString } from "../utils/mustbe.js";
|
|||||||
* - onColon(...)
|
* - onColon(...)
|
||||||
*/
|
*/
|
||||||
export class Prompt {
|
export class Prompt {
|
||||||
/** @protected @readonly @constant @type {Scene} */
|
/** @private @readonly @type {Scene} */
|
||||||
scene;
|
_scene;
|
||||||
|
|
||||||
|
/** @type {Scene} */
|
||||||
|
get scene() {
|
||||||
|
return this._scene;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Extra info about the prompt we send to the client.
|
// Extra info about the prompt we send to the client.
|
||||||
@@ -58,7 +63,7 @@ export class Prompt {
|
|||||||
if (!(scene instanceof Scene)) {
|
if (!(scene instanceof Scene)) {
|
||||||
throw new Error("Expected an instance of >>Scene<< but got " + typeof scene);
|
throw new Error("Expected an instance of >>Scene<< but got " + typeof scene);
|
||||||
}
|
}
|
||||||
this.scene = scene;
|
this._scene = scene;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -92,24 +97,42 @@ export class Prompt {
|
|||||||
* Triggered when a user types a :command that begins with a colon
|
* Triggered when a user types a :command that begins with a colon
|
||||||
*
|
*
|
||||||
* @param {string} command
|
* @param {string} command
|
||||||
* @param {string} argLine
|
* @param {any[]} args
|
||||||
*/
|
*/
|
||||||
onColon(command, argLine) {
|
|
||||||
const methodName = "onColon_" + command;
|
onColon(command, args) {
|
||||||
const method = this[methodName];
|
const methodName = "onColon__" + command;
|
||||||
if (typeof method === "function") {
|
const property = this[methodName];
|
||||||
method.call(this, argLine);
|
|
||||||
|
//
|
||||||
|
// Default: we have no handler for the Foo command,
|
||||||
|
// So let's see if daddy can handle it.
|
||||||
|
if (property === undefined) {
|
||||||
|
return this.scene.onColon(command, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// If the prompt has a method called onColon_foo() =>
|
||||||
|
if (typeof property === "function") {
|
||||||
|
property.call(this, args);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// For static "denial of commands" such as :inv ==> "you cannot access your inventory right now"
|
// If the prompt has a _string_ called onColon_foo =>
|
||||||
if (typeof method === "string") {
|
if (typeof property === "string") {
|
||||||
this.sendText(method);
|
this.sendText(property);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// :inv ==> you cannot INV right now
|
//
|
||||||
this.sendError(`You cannot ${command.toUpperCase()} right now`);
|
// We found a property that has the right name but the wrong type.
|
||||||
|
throw new Error(
|
||||||
|
[
|
||||||
|
`Logic error. Prompt has a handler for a command called ${command}`,
|
||||||
|
`but it is neither a function or a string, but a ${typeof property}`,
|
||||||
|
].join(" "),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -167,7 +190,7 @@ export class Prompt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} systemMessageType
|
* @param {string} systemMessageType The subtype of the system message (dev, salt, username, etc.)
|
||||||
* @param {any?} value
|
* @param {any?} value
|
||||||
*/
|
*/
|
||||||
sendSystemMessage(...args) {
|
sendSystemMessage(...args) {
|
||||||
@@ -184,13 +207,6 @@ export class Prompt {
|
|||||||
|
|
||||||
//
|
//
|
||||||
// Easter ægg
|
// Easter ægg
|
||||||
onColon_pull_out_wand = "You cannot pull out your wand right now! But thanks for trying 😘🍌🍆";
|
// Example of having a string as a colon-handler
|
||||||
|
onColon__pull_out_wand = "You cannot pull out your wand right now! But thanks for trying 😘🍌🍆";
|
||||||
//
|
|
||||||
// Easter ægg2
|
|
||||||
onColon_imperial(argLine) {
|
|
||||||
const n = Number(argLine);
|
|
||||||
|
|
||||||
this.sendText(`${n} centimeters is only ${n / 2.54} inches. This is why americans have such small wands`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,16 @@
|
|||||||
import { Session } from "../models/session.js";
|
import { Session } from "../models/session.js";
|
||||||
import { Prompt } from "./prompt.js";
|
import { Prompt } from "./prompt.js";
|
||||||
const MsgContext.ERROR_INSANE_PASSWORD = "Invalid password.";
|
|
||||||
const MsgContext.ERROR_INCORRECT_PASSWOD = "Incorrect password.";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Scene - a class for showing one or more prompts in a row.
|
||||||
|
*
|
||||||
|
* Scenes are mostly there to keep track of which prompt to show,
|
||||||
|
* and to store data for subsequent prompts to access.
|
||||||
|
*
|
||||||
|
* The prompts themselves are responsible for data validation and
|
||||||
|
* interpretation.
|
||||||
|
*
|
||||||
* @abstract
|
* @abstract
|
||||||
* @method onReady
|
|
||||||
*/
|
*/
|
||||||
export class Scene {
|
export class Scene {
|
||||||
/**
|
/**
|
||||||
@@ -31,8 +36,7 @@ export class Scene {
|
|||||||
return this._prompt;
|
return this._prompt;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor() {
|
constructor() {}
|
||||||
}
|
|
||||||
|
|
||||||
/** @param {Session} session */
|
/** @param {Session} session */
|
||||||
execute(session) {
|
execute(session) {
|
||||||
@@ -51,8 +55,73 @@ export class Scene {
|
|||||||
/**
|
/**
|
||||||
* @param {Prompt} prompt
|
* @param {Prompt} prompt
|
||||||
*/
|
*/
|
||||||
doPrompt(prompt) {
|
showPrompt(prompt) {
|
||||||
this._prompt = prompt;
|
this._prompt = prompt;
|
||||||
prompt.execute();
|
prompt.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @param {new (scene: Scene) => Prompt} promptClassReference */
|
||||||
|
show(promptClassReference) {
|
||||||
|
this.showPrompt(new promptClassReference(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggered when a user types a :command that begins with a colon
|
||||||
|
* and the current Prompt cannot handle that command.
|
||||||
|
*
|
||||||
|
* @param {string} command
|
||||||
|
* @param {any[]} args
|
||||||
|
*/
|
||||||
|
onColon(command, args) {
|
||||||
|
const propertyName = "onColon__" + command;
|
||||||
|
const property = this[propertyName];
|
||||||
|
|
||||||
|
//
|
||||||
|
// Default: we have no handler for the Foo command
|
||||||
|
if (property === undefined) {
|
||||||
|
this.session.sendError(`You cannot ${command.toUpperCase()} right now`, { verbatim: true }); // :foo ==> you cannot FOO right now
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// If the prompt has a method called onColon_foo() =>
|
||||||
|
if (typeof property === "function") {
|
||||||
|
property.call(this, args);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// If the prompt has a _string_ called onColon_foo =>
|
||||||
|
if (typeof property === "string") {
|
||||||
|
this.session.sendText(property);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// We found a property that has the right name but the wrong type.
|
||||||
|
throw new Error(
|
||||||
|
[
|
||||||
|
`Logic error. Scene has a handler for a command called ${command}`,
|
||||||
|
`but it is neither a function or a string, but a ${typeof property}`,
|
||||||
|
].join(" "),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Easter ægg
|
||||||
|
// Example dynamic colon handler
|
||||||
|
/** @param {any[]} args */
|
||||||
|
onColon__imperial(args) {
|
||||||
|
if (args.length === 0) {
|
||||||
|
this.session.sendText("The imperial system is the freeest system ever. Also the least good");
|
||||||
|
}
|
||||||
|
|
||||||
|
const n = Number(args[0]);
|
||||||
|
|
||||||
|
this.session.sendText(
|
||||||
|
sprintf("%.2f centimeters is only %.2f inches. This is american wands are so short!", n, n / 2.54),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
onColon__hi = "Hoe";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ import WebSocket, { WebSocketServer } from "ws";
|
|||||||
import http from "http";
|
import http from "http";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import * as msg from "./utils/messages.js";
|
|
||||||
import { Session } from "./models/session.js";
|
import { Session } from "./models/session.js";
|
||||||
import { GameSeeder } from "./seeders/gameSeeder.js";
|
import { GameSeeder } from "./seeders/gameSeeder.js";
|
||||||
import { Config } from "./config.js";
|
import { Config } from "./config.js";
|
||||||
import { gGame } from "./models/globals.js";
|
import { gGame } from "./models/globals.js";
|
||||||
import { AuthenticationScene } from "./scenes/authentication/authenticationScene.js";
|
import { AuthenticationScene } from "./scenes/authentication/authenticationScene.js";
|
||||||
|
import { MessageType, WebsocketMessage, formatMessage } from "./utils/messages.js";
|
||||||
|
|
||||||
// __ __ _ _ ____ ____
|
// __ __ _ _ ____ ____
|
||||||
// | \/ | | | | _ \ / ___| ___ _ ____ _____ _ __
|
// | \/ | | | | _ \ / ___| ___ _ ____ _____ _ __
|
||||||
@@ -32,7 +32,7 @@ class MudServer {
|
|||||||
console.info("New connection established");
|
console.info("New connection established");
|
||||||
const session = new Session(websocket, gGame);
|
const session = new Session(websocket, gGame);
|
||||||
if (Config.dev) {
|
if (Config.dev) {
|
||||||
websocket.send(msg.prepareToSend(msg.SYSTEM, "dev", true));
|
websocket.send(formatMessage(MessageType.SYSTEM, "dev", true));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ____ _ ___ ____ _____
|
// ____ _ ___ ____ _____
|
||||||
@@ -56,7 +56,7 @@ class MudServer {
|
|||||||
this.onMessage(session, data);
|
this.onMessage(session, data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error, data.toString(), data);
|
console.error(error, data.toString(), data);
|
||||||
websocket.send(msg.prepareToSend(msg.CALAMITY, error));
|
websocket.send(formatMessage(MessageType.CALAMITY, error));
|
||||||
session.close();
|
session.close();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -159,7 +159,7 @@ class MudServer {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const msgObj = new msg.WebsocketMessage(data.toString());
|
const msgObj = new WebsocketMessage(data.toString());
|
||||||
|
|
||||||
//
|
//
|
||||||
// Handle replies to prompts. The main workhorse of the game.
|
// Handle replies to prompts. The main workhorse of the game.
|
||||||
@@ -174,7 +174,7 @@ class MudServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Handle QUIT messages. When the player types :quit
|
// Handle MessageType.QUIT messages. When the player types :quit
|
||||||
if (msgObj.isQuit()) {
|
if (msgObj.isQuit()) {
|
||||||
session.scene.onQuit();
|
session.scene.onQuit();
|
||||||
session.close(0, "Closing the socket, graceful goodbye!");
|
session.close(0, "Closing the socket, graceful goodbye!");
|
||||||
@@ -184,7 +184,7 @@ class MudServer {
|
|||||||
//
|
//
|
||||||
// Handle any text that starts with ":" that isn't :help or :quit
|
// Handle any text that starts with ":" that isn't :help or :quit
|
||||||
if (msgObj.isColon()) {
|
if (msgObj.isColon()) {
|
||||||
return session.scene.prompt.onColon(msgObj.command, msgObj.argLine);
|
return session.scene.prompt.onColon(msgObj.command, msgObj.args);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,19 +1,6 @@
|
|||||||
import { mustBe, mustBeInteger, mustBeString, mustMatch } from "./mustbe.js";
|
import { mustBe, mustBeString, mustMatch } from "./mustbe.js";
|
||||||
|
|
||||||
const colonCommandRegex = /^:([a-z0-9_]+)(:?\s*(.*))?$/;
|
export const MessageType = Object.freeze({
|
||||||
|
|
||||||
/**
|
|
||||||
* Enum-like object holding placeholder tokens.
|
|
||||||
*
|
|
||||||
* @readonly
|
|
||||||
* @enum {string}
|
|
||||||
*/
|
|
||||||
export const MsgContext = Object.freeze({
|
|
||||||
PASSWORD: ":password",
|
|
||||||
USERNAME: ":username",
|
|
||||||
});
|
|
||||||
|
|
||||||
export const MsgTtype = Object.freeze({
|
|
||||||
/**
|
/**
|
||||||
* Very bad logic error. Player must quit game, refresh page, and log in again.
|
* Very bad logic error. Player must quit game, refresh page, and log in again.
|
||||||
*
|
*
|
||||||
@@ -28,7 +15,7 @@ export const MsgTtype = Object.freeze({
|
|||||||
*
|
*
|
||||||
* Server-->Client-->Player
|
* Server-->Client-->Player
|
||||||
*/
|
*/
|
||||||
MsgContext.ERROR: "E",
|
ERROR: "E",
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Message to be displayed.
|
* Message to be displayed.
|
||||||
@@ -42,7 +29,7 @@ export const MsgTtype = Object.freeze({
|
|||||||
*
|
*
|
||||||
* Player-->Client-->Server
|
* Player-->Client-->Server
|
||||||
*/
|
*/
|
||||||
MsgContext.REPLY: "R",
|
REPLY: "R",
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Player wants to quit.
|
* Player wants to quit.
|
||||||
@@ -93,7 +80,7 @@ export const MsgTtype = Object.freeze({
|
|||||||
* Represents a message sent to/from client
|
* Represents a message sent to/from client
|
||||||
*
|
*
|
||||||
* @property {string?} command
|
* @property {string?} command
|
||||||
* @property {string?} argLine
|
* @property {any[]} args
|
||||||
*/
|
*/
|
||||||
export class WebsocketMessage {
|
export class WebsocketMessage {
|
||||||
/** @protected @type {any[]} _arr The array that contains the message data */
|
/** @protected @type {any[]} _arr The array that contains the message data */
|
||||||
@@ -136,22 +123,22 @@ export class WebsocketMessage {
|
|||||||
this.type = mustBeString(data[0]);
|
this.type = mustBeString(data[0]);
|
||||||
|
|
||||||
switch (this.type) {
|
switch (this.type) {
|
||||||
case MsgContext.REPLY: // player ==> client ==> server
|
case MessageType.REPLY: // player ==> client ==> server
|
||||||
this.text = mustBeString(data[1]);
|
this.text = mustBeString(data[1]);
|
||||||
break;
|
break;
|
||||||
case HELP: // player ==> client ==> server
|
case MessageType.HELP: // player ==> client ==> server
|
||||||
this.text = data[1] === undefined ? "" : mustBeString(data[1]).trim();
|
this.text = data[1] === undefined ? "" : mustBeString(data[1]).trim();
|
||||||
break;
|
break;
|
||||||
case COLON: // player ==> client ==> server
|
case MessageType.COLON: // player ==> client ==> server
|
||||||
this.command = mustMatch(data[1], /^[a-z0-9_]+$/);
|
this.command = mustMatch(data[1], /^[a-z0-9_]+$/);
|
||||||
this.argLine = data[2]; // parse??
|
this.args = mustBe(data[2], "any[]");
|
||||||
break;
|
break;
|
||||||
case DEBUG: // server ==> client
|
case MessageType.DEBUG: // server ==> client
|
||||||
case MsgContext.ERROR: // server ==> client ==> player
|
case MessageType.ERROR: // server ==> client ==> player
|
||||||
case QUIT: // player ==> client ==> server
|
case MessageType.QUIT: // player ==> client ==> server
|
||||||
case SYSTEM: // client <==> server
|
case MessageType.SYSTEM: // client <==> server
|
||||||
case PROMPT: // server ==> client ==> player
|
case MessageType.PROMPT: // server ==> client ==> player
|
||||||
case TEXT: // server ==> client ==> player
|
case MessageType.TEXT: // server ==> client ==> player
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unknown message type: >>${typeof this.type}<<`);
|
throw new Error(`Unknown message type: >>${typeof this.type}<<`);
|
||||||
@@ -159,27 +146,27 @@ export class WebsocketMessage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isQuit() {
|
isQuit() {
|
||||||
return this.type === QUIT;
|
return this.type === MessageType.QUIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
isHelp() {
|
isHelp() {
|
||||||
return this.type === HELP;
|
return this.type === MessageType.HELP;
|
||||||
}
|
}
|
||||||
|
|
||||||
isColon() {
|
isColon() {
|
||||||
return this.type === COLON;
|
return this.type === MessageType.COLON;
|
||||||
}
|
}
|
||||||
|
|
||||||
isReply() {
|
isReply() {
|
||||||
return this.type === MsgContext.REPLY;
|
return this.type === MessageType.REPLY;
|
||||||
}
|
}
|
||||||
|
|
||||||
isSysMessage() {
|
isSysMessage() {
|
||||||
return this.type === SYSTEM;
|
return this.type === MessageType.SYSTEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
isDebug() {
|
isDebug() {
|
||||||
return this.type === DEBUG;
|
return this.type === MessageType.DEBUG;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,6 +176,6 @@ export class WebsocketMessage {
|
|||||||
* @param {string} messageType
|
* @param {string} messageType
|
||||||
* @param {...any} args
|
* @param {...any} args
|
||||||
*/
|
*/
|
||||||
export function prepareToSend(messageType, ...args) {
|
export function formatMessage(messageType, ...args) {
|
||||||
return JSON.stringify([messageType, ...args]);
|
return JSON.stringify([messageType, ...args]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,8 +12,14 @@ export function mustBe(value, ...types) {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isArray = Array.isArray(value);
|
||||||
|
|
||||||
|
if (isArray && (types.includes("any[]") || types.includes("array"))) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
// NOTE: only checks first element of array if it's a string.
|
// NOTE: only checks first element of array if it's a string.
|
||||||
if (types.includes("strings[]") && Array.isArray(value) && (value.length === 0 || typeof value[0] === "string")) {
|
if (isArray && types.includes("strings[]") && (value.length === 0 || typeof value[0] === "string")) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,12 +30,6 @@ export function mustBeString(value) {
|
|||||||
return mustBe(value, "string");
|
return mustBe(value, "string");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function mustBeInteger(value) {
|
|
||||||
if (typeof value === "number" && Number.isSafeInteger(value)) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {string} str
|
* @param {string} str
|
||||||
|
|||||||
@@ -222,7 +222,7 @@ export function frameText(text, options) {
|
|||||||
let output = "";
|
let output = "";
|
||||||
|
|
||||||
//
|
//
|
||||||
// GENERATE THE MARGIN SPACE ABOVE THE FRAMED TEXT
|
// GENERATE THE MARGIN SPACE ABOVE THE FRAMED MsgType.TEXT
|
||||||
//
|
//
|
||||||
// ( we insert space characters even though )
|
// ( we insert space characters even though )
|
||||||
// ( they wouldn't normally be visible. But )
|
// ( they wouldn't normally be visible. But )
|
||||||
@@ -263,7 +263,7 @@ export function frameText(text, options) {
|
|||||||
).repeat(options.vPadding);
|
).repeat(options.vPadding);
|
||||||
|
|
||||||
//
|
//
|
||||||
// GENERATE FRAMED TEXT SEGMENT
|
// GENERATE FRAMED MsgType.TEXT SEGMENT
|
||||||
//
|
//
|
||||||
// ║ My pretty ║
|
// ║ My pretty ║
|
||||||
// ║ text here ║
|
// ║ text here ║
|
||||||
@@ -318,7 +318,7 @@ export function frameText(text, options) {
|
|||||||
"\n";
|
"\n";
|
||||||
|
|
||||||
//
|
//
|
||||||
// GENERATE THE MARGIN SPACE BELOW THE FRAMED TEXT
|
// GENERATE THE MARGIN SPACE BELOW THE FRAMED MsgType.TEXT
|
||||||
//
|
//
|
||||||
// ( we insert space characters even though )
|
// ( we insert space characters even though )
|
||||||
// ( they wouldn't normally be visible. But )
|
// ( they wouldn't normally be visible. But )
|
||||||
|
|||||||
Reference in New Issue
Block a user