Merge branch 'materials'

master
Bronwen 2021-07-10 23:23:24 -04:00
commit f0d42316bc
27 changed files with 242 additions and 100 deletions

View File

@ -2,16 +2,10 @@ import { registerAction } from '@actions';
import { Game } from '@game'; import { Game } from '@game';
import { ItemState } from '@items'; import { ItemState } from '@items';
import { TaskState } from '@tasks'; import { TaskState } from '@tasks';
import { SelectItem } from '../../../src/ui/SelectItem.js';
import { FLINT_NORMAL } from '../items/CoreItems.js'; import { FLINT_NORMAL } from '../items/CoreItems.js';
import { GATHER_FLINT, MAKE_ARROWHEAD } from '../tasks/CoreTasks.js'; import { GATHER_FLINT, MAKE_ARROWHEAD } from '../tasks/CoreTasks.js';
// registerAction('Gather Flint', (qty) => {
// Game.current.board.addTask({
// taskId: 'core:gather-flint',
// options: {}
// })
// });
// registerAction('Gather Slate', (qty) => { // registerAction('Gather Slate', (qty) => {
// Game.current.board.addTask({ // Game.current.board.addTask({
// taskId: 'core:gather-slate', // taskId: 'core:gather-slate',
@ -24,8 +18,11 @@ registerAction('Gather Flint', () => {
Game.current.board.addTask(taskState); Game.current.board.addTask(taskState);
}); });
registerAction('Create Arrowhead', (qty) => { registerAction('Create Arrowhead', async () => {
const rock = new ItemState(FLINT_NORMAL, 1, null); // const rock = new ItemState(FLINT_NORMAL, 1, null);
const item = await SelectItem.show((itemState) => {
return true;
});
const task = new TaskState(MAKE_ARROWHEAD, { const task = new TaskState(MAKE_ARROWHEAD, {
baseMaterial: rock baseMaterial: rock
}); });

View File

@ -1,8 +1,23 @@
import { Item, ItemFilter, ItemProperty, ItemState } from '@items' import { Item, ItemFilter, ItemProperty, ItemState } from '@items'
class Material {
name: string;
hardness: number;
setName(name: string) {
this.name = name;
return this;
}
setHardness(n: number) {
this.hardness = n;
}
}
// #region properties! // #region properties!
export const ROCK = new ItemProperty('core:rock') export const ROCK = new ItemProperty('core:rock')
export const ROCK_HARDNESS = new ItemProperty('core:mohs-hardness') export const MATERIAL = new ItemProperty('core:material')
export const ROCK_SIZE = new ItemProperty('core:rock-size')
export const SEDIMENTARY = new ItemProperty('core:sedimentary') export const SEDIMENTARY = new ItemProperty('core:sedimentary')
export const IGNEOUS = new ItemProperty('core:igneous') export const IGNEOUS = new ItemProperty('core:igneous')
export const METAMORPHIC = new ItemProperty('core:metamorphic') export const METAMORPHIC = new ItemProperty('core:metamorphic')
@ -26,7 +41,12 @@ export const PLANT_FIBRES = new Item()
export const FLINT_NORMAL = new Item() export const FLINT_NORMAL = new Item()
.setName("Flint") .setName("Flint")
.setId('core:flint') .setId('core:flint')
.setProperty(ROCK_HARDNESS, 7) .setProperty(MATERIAL, new Material()
.setName('Flint')
.setHardness(7)
)
.setProperty(ROCK, true)
.setProperty(IGNEOUS, true)
export const SANDSTONE_NORMAL = new Item() export const SANDSTONE_NORMAL = new Item()
.setName("Sandstone") .setName("Sandstone")
@ -104,9 +124,13 @@ export const OBSIDIAN_SPEAR = new Item()
// #endregion // #endregion
// export function FILTER_CRAFTABLE_ROCK(item: ItemState<any>) { export function FILTER_CRAFTABLE_ROCK(itemState: ItemState<any>) {
// return if(!itemState.item.getProperty(MATERIAL)) return false;
// } const mat: Material = itemState.item.getProperty(MATERIAL) as Material;
return itemState.item.getProperty(ROCK)
&& mat.hardness >= 6
&& mat.hardness < 10
}
// tools: plant fibres = rope, flint hatchet // tools: plant fibres = rope, flint hatchet
// shale - igneous. metamorphasis => slate // shale - igneous. metamorphasis => slate

View File

@ -4,5 +4,5 @@ import chalk from 'chalk'
registerTheme("default", {}); registerTheme("default", {});
registerTheme("high contrast", { registerTheme("high contrast", {
selected: chalk.ansi256(250).inverse bright: chalk.ansi256(250).inverse
}); });

View File

@ -5,6 +5,7 @@ const moduleAliases = {
"@actions": "./out/src/registries/Actions.js", "@actions": "./out/src/registries/Actions.js",
"@tasks": "./out/src/registries/Tasks.js", "@tasks": "./out/src/registries/Tasks.js",
"@items": "./out/src/registries/Items.js", "@items": "./out/src/registries/Items.js",
"@ui": "./out/src/ui/UI.js",
"@game": "./out/src/Game.js" "@game": "./out/src/Game.js"
}; };

View File

@ -9,8 +9,10 @@
"@types/bonjour": "^3.5.8", "@types/bonjour": "^3.5.8",
"@types/chai": "^4.2.19", "@types/chai": "^4.2.19",
"@types/faker": "^5.5.6", "@types/faker": "^5.5.6",
"@types/fs-extra": "^9.0.11",
"@types/mocha": "^8.2.2", "@types/mocha": "^8.2.2",
"@types/uuid": "^8.3.0", "@types/uuid": "^8.3.0",
"@types/ws": "^7.4.6",
"bonjour": "^3.5.0", "bonjour": "^3.5.0",
"chai": "^4.3.4", "chai": "^4.3.4",
"chalk": "^4.1.1", "chalk": "^4.1.1",

15
perf.js 100644
View File

@ -0,0 +1,15 @@
console.clear();
const n = 10 ** 8;
// const map = new Map();
console.log('sequential insertion');
for(let run = 0; run < 10; run ++) {
const arr = [];
console.time('array');
for(let i = 0; i < n; i ++) {
arr.push(133769420)
}
console.timeEnd('array')
}

View File

@ -9,7 +9,7 @@ import { render, Renderable, setTitle, start } from './ui/UI.js';
import { ready } from './multiplayer/mDNS.js'; import { ready } from './multiplayer/mDNS.js';
import faker from 'faker'; import faker from 'faker';
let game = null; let game: Game = null;
export class Game extends Frigid implements Tickable, Renderable { export class Game extends Frigid implements Tickable, Renderable {
pawns: Pawn[] = []; pawns: Pawn[] = [];
@ -47,7 +47,7 @@ export class Game extends Frigid implements Tickable, Renderable {
}); });
} }
advanceSelection(number) { advanceSelection(number: number) {
let index = this.pawns.indexOf(this.selected); let index = this.pawns.indexOf(this.selected);
this.selected = this.pawns[Math.min(Math.max(index + number, 0), this.pawns.length - 1)]; this.selected = this.pawns[Math.min(Math.max(index + number, 0), this.pawns.length - 1)];
} }

View File

@ -42,29 +42,23 @@ export class Inventory extends Serializable implements Renderable {
} }
private reduceInv() { private reduceInv() {
// TODO deduplicate itemstates... this.items = this.items.reduce((items, itemState) => {
// use a reduce to reconstruct the array.
// REMEMBER TO MAINTAIN THE OBJECTs!
// dont do immutability to it, as the objects
// may have crossreferences! (maybe)
}
// add(item: Item, qty: number = 1) { // TODO at some point, be able to merge data items?
// const id = item.id;
// const existingArr = this.items.filter(itemState => { const existing = items.find(testItemState => {
// return itemState.itemId === id; return itemState.itemId === testItemState.itemId
// }); && itemState.data === testItemState.data;
// let existing: ItemState = null; });
// if(existingArr.length === 1) {
// existing = existingArr[0]; if(existing) {
// } existing.qty += itemState.qty;
// if(existing) { } else {
// existing.qty += qty; items.push(itemState);
// } else { }
// this.items.push(new ItemState(item, qty, {})); return items
// } }, [] as ItemState<any>[])
// Game.current.sync(); }
// }
render() { render() {
return this.items.map(item => item.render()).join('\n'); return this.items.map(item => item.render()).join('\n');

View File

@ -21,7 +21,7 @@ export class TaskList extends Serializable implements Renderable {
this.tasks = [...this.tasks, task]; this.tasks = [...this.tasks, task];
} }
removeTask(task) { removeTask(task: TaskState<any>) {
this.tasks = this.tasks.filter(v => v !== task); this.tasks = this.tasks.filter(v => v !== task);
} }

View File

@ -118,7 +118,7 @@ export default class Time extends Serializable implements Renderable {
setTimeout(this.doTick.bind(this), 0); setTimeout(this.doTick.bind(this), 0);
} }
advanceTime(seconds) { advanceTime(seconds: number) {
this.minute += seconds / 60; this.minute += seconds / 60;
this.normalize() this.normalize()
} }

View File

@ -1,5 +1,14 @@
import { ItemState } from "@items";
import { Serializable } from "frigid"; import { Serializable } from "frigid";
export class World extends Serializable { export class World extends Serializable {
}
class WorldItemState {
itemState: ItemState<any>
constructor() {
}
} }

View File

@ -29,7 +29,7 @@ export type GiftMessage = {
export default network; export default network;
export async function ready(name) { export async function ready(name: string) {
const port = await getPort({port: getPort.makeRange(52300, 52399)}); const port = await getPort({port: getPort.makeRange(52300, 52399)});
mdns.publish({ mdns.publish({
type: 'dfi', type: 'dfi',
@ -39,7 +39,7 @@ export async function ready(name) {
const wss = new WebSocket.Server({ port }); const wss = new WebSocket.Server({ port });
wss.on('connection', function connection(ws) { wss.on('connection', function connection(ws) {
ws.on('message', function incoming(message) { ws.on('message', function incoming(message) {
const {pawns: pawnJsons, from} = JSON.parse(message); const {pawns: pawnJsons, from} = JSON.parse(message.toString());
const pawns = []; const pawns = [];
for(const pawnJson of pawnJsons) { for(const pawnJson of pawnJsons) {
const pawn: Pawn = Pawn.fromJson(pawnJson); const pawn: Pawn = Pawn.fromJson(pawnJson);

View File

@ -3,7 +3,7 @@ import { Renderable } from "../ui/UI.js";
export const actions: Action[] = []; export const actions: Action[] = [];
export function registerAction(name: string, invoke: (qty: number) => void) { export function registerAction(name: string, invoke: () => void) {
console.log('Registered action', name); console.log('Registered action', name);
actions.push(new Action(name, invoke)) actions.push(new Action(name, invoke))
} }

View File

@ -6,16 +6,14 @@ export type ItemID = string;
const items = new Map<ItemID, Item<any>>(); const items = new Map<ItemID, Item<any>>();
export type PropertyValue = number | boolean;
// ITEMS SHALL BE SINGULAR // ITEMS SHALL BE SINGULAR
export class Item<Data> extends Serializable { export class Item<Data> extends Serializable {
name = ''; name = '';
id: ItemID = ''; id: ItemID = '';
props: Map<string, PropertyValue> = new Map(); props: Map<string, any> = new Map();
setName(name) { setName(name: string) {
this.name = name; this.name = name;
this.register(false); this.register(false);
return this; return this;
@ -35,7 +33,7 @@ export class Item<Data> extends Serializable {
} }
setProperty(prop: ItemProperty, value: any) { setProperty(prop: ItemProperty, value: any) {
this.props[prop.name] = value; this.props.set(prop.name, value);
return this; return this;
} }
@ -50,6 +48,12 @@ export class ItemState<Data> extends Serializable implements Renderable {
itemId: ItemID; itemId: ItemID;
data: Data; data: Data;
take(qty: number) {
if(this.qty < qty) throw new Error('cant split more than stack from stack...');
this.qty -= qty;
return new ItemState<Data>(this.item, qty, this.data);
}
get item() { get item() {
if(!items.has(this.itemId)) if(!items.has(this.itemId))
throw new Error('unknown item: ' + this.itemId); throw new Error('unknown item: ' + this.itemId);

View File

@ -13,8 +13,9 @@ type StyleFunction = (text: string) => string;
export type Theme = { export type Theme = {
header: StyleFunction, header: StyleFunction,
subheader: StyleFunction, subheader: StyleFunction,
bright: StyleFunction,
normal: StyleFunction, normal: StyleFunction,
selected: StyleFunction, dimmed: StyleFunction,
hotkey: StyleFunction, hotkey: StyleFunction,
tab: { tab: {
normal: StyleFunction, normal: StyleFunction,
@ -42,10 +43,11 @@ export type Theme = {
} }
export const backupTheme: Theme = { export const backupTheme: Theme = {
header: chalk.ansi256(255).bold, header: chalk.ansi256(255),
subheader: chalk.ansi256(243).bold, subheader: chalk.ansi256(250),
normal: chalk.ansi256(243), bright: chalk.ansi256(255),
selected: chalk.ansi256(250), normal: chalk.ansi256(250),
dimmed: chalk.ansi256(245),
hotkey: chalk.ansi256(40), hotkey: chalk.ansi256(40),
tab: { tab: {
normal: chalk.ansi256(117), normal: chalk.ansi256(117),
@ -53,7 +55,7 @@ export const backupTheme: Theme = {
}, },
border: { border: {
focused: '#ffffff', focused: '#ffffff',
normal: '#222222' normal: '#888888'
}, },
progressBar: { progressBar: {
indicator: { indicator: {

1
src/types.d.ts vendored 100644
View File

@ -0,0 +1 @@
declare module "neo-blessed";

View File

@ -25,7 +25,7 @@ export class GiftPopup {
tags: true, tags: true,
...boxStyle(), ...boxStyle(),
}); });
this.box.on('keypress', (evt, key) => { this.box.on('keypress', (evt: {}, key: {full: string}) => {
if(key.full === 'enter') { if(key.full === 'enter') {
this.send(); this.send();
} if(key.full === 'escape' || key.full === 'enter') { } if(key.full === 'escape' || key.full === 'enter') {
@ -69,7 +69,7 @@ export class GiftPopup {
this.box.setContent(`${(() => { this.box.setContent(`${(() => {
let pawns = []; let pawns = [];
for (const [pawn, qty] of this.pawns.entries()) { for (const [pawn, qty] of this.pawns.entries()) {
const style = i === this.selected ? getTheme().selected : getTheme().normal; const style = i === this.selected ? getTheme().bright : getTheme().normal;
if(qty > 0) { if(qty > 0) {
pawns.push(style(`{|}${pawn.toString()} `)) pawns.push(style(`{|}${pawn.toString()} `))
} else { } else {

View File

@ -13,7 +13,7 @@ import { View } from './View.js';
import { ActionsView } from './view/ActionsView.js'; import { ActionsView } from './view/ActionsView.js';
import { tasks } from '@tasks'; import { tasks } from '@tasks';
const clamp = (min, max, value) => Math.min(Math.max(value, min), max); const clamp = (min: number, max: number, value: number) => Math.min(Math.max(value, min), max);
// TODO move KeypressAcceptor to ui something idk // TODO move KeypressAcceptor to ui something idk
export interface KeypressAcceptor { export interface KeypressAcceptor {
@ -46,7 +46,7 @@ export class Menu implements Renderable {
} }
constructor() { constructor() {
panels.right.on('keypress', (evt, key) => { panels.right.on('keypress', (evt: {}, key: {full: string}) => {
if (key.full === 'left') { if (key.full === 'left') {
this.regressView(); this.regressView();

View File

@ -21,7 +21,7 @@ export class PawnDetails {
tags: true, tags: true,
...boxStyle(), ...boxStyle(),
}); });
this.box.on('keypress', (evt, key) => { this.box.on('keypress', (evt: {}, key: {full: string}) => {
if(key.full === 'escape' || key.full === 'enter') { if(key.full === 'escape' || key.full === 'enter') {
Game.current.clock.start(); Game.current.clock.start();
panels.screen.remove(this.box); panels.screen.remove(this.box);

View File

@ -7,11 +7,11 @@ import { panels } from './UI.js';
export class Popup { export class Popup {
box; box;
static show(content) { static show(content: string) {
new Popup(content) new Popup(content)
} }
private constructor(content) { private constructor(content: string) {
this.box = blessed.box({ this.box = blessed.box({
top: 'center', top: 'center',
left: 'center', left: 'center',
@ -21,7 +21,7 @@ export class Popup {
tags: true, tags: true,
...boxStyle(), ...boxStyle(),
}); });
this.box.on('keypress', (evt, key) => { this.box.on('keypress', (evt: {}, key: {full: string}) => {
if(key.full === 'escape' || key.full === 'enter') { if(key.full === 'escape' || key.full === 'enter') {
Game.current.clock.start(); Game.current.clock.start();
panels.screen.remove(this.box); panels.screen.remove(this.box);

View File

@ -0,0 +1,77 @@
import { Game } from "@game";
import { ItemState } from "@items";
import { boxStyle, getTheme } from "@themes";
import { panels } from "@ui";
import EventEmitter from "events";
import blessed from 'neo-blessed';
type ItemFilterFunction = (itemState: ItemState<any>) => boolean;
export class SelectItem {
box: any;
emitter: EventEmitter;
qty: number;
items: ItemState<any>[];
selectedIdx: number;
static show(filter: ItemFilterFunction, qty: number = 1): Promise<ItemState<any>> {
const si = new SelectItem(filter, qty);
return new Promise(res => {
si.emitter.on('selected', (itemState: ItemState<any>) => {
res(itemState);
});
si.emitter.on('cancel', () => {
res(null);
})
});
}
private open() {
panels.screen.append(this.box);
this.box.focus();
Game.current.clock.pause();
}
private close() {
Game.current.clock.start();
panels.screen.remove(this.box);
}
get selectedItem(): ItemState<any> {
return null;
}
private constructor(filter: ItemFilterFunction, qty: number) {
this.emitter = new EventEmitter();
this.qty = qty;
this.box = blessed.box({
top: 'center',
left: 'center',
width: 'shrink',
height: 'shrink',
tags: true,
...boxStyle(),
});
this.box.on('keypress', (evt: {}, key: {full: string}) => {
if(key.full === 'escape') {
this.emitter.emit('cancel');
this.close();
} else if(key.full === 'enter') {
this.emitter.emit('selected', this.selectedItem.take(this.qty));
this.close();
} else if(key.full === 'down') {
}
});
this.items = Game.current.inv.items.filter(filter);
this.update();
this.open();
}
update() {
this.box.setContent('test');
panels.screen.render();
}
}

View File

@ -1,4 +1,3 @@
import chalk from 'chalk'; import chalk from 'chalk';
import blessed from 'neo-blessed'; import blessed from 'neo-blessed';
import ansi from 'sisteransi'; import ansi from 'sisteransi';
@ -99,7 +98,8 @@ export function start() {
process.stdout.write(ansi.cursor.hide); process.stdout.write(ansi.cursor.hide);
screen.key(['C-c'], function(ch, key) { // todo make a real menu
screen.key(['C-c'], function() {
process.stdout.write(ansi.cursor.show); process.stdout.write(ansi.cursor.show);
setTimeout(_ => { setTimeout(_ => {
process.exit(0); process.exit(0);

View File

@ -12,7 +12,7 @@ export class ActionsView extends View {
this.name = 'Actions'; this.name = 'Actions';
} }
keypress(key) { keypress(key: {full: string}) {
if(key.full === 'up') { if(key.full === 'up') {
this.actionIdx --; this.actionIdx --;
} else if (key.full === 'down') { } else if (key.full === 'down') {
@ -24,7 +24,7 @@ export class ActionsView extends View {
render() { render() {
return actions.map((action, idx) => `${(() => { return actions.map((action, idx) => `${(() => {
if(this.actionIdx === idx) { if(this.actionIdx === idx) {
return getTheme().selected(' ' + action.name); return getTheme().bright(' ' + action.name);
} else { } else {
return getTheme().normal(' ' + action.name); return getTheme().normal(' ' + action.name);
} }

View File

@ -25,7 +25,7 @@ export default class MultiplayerView extends View {
render() { render() {
if(mdns.players.length === 0) return `{center}${getTheme().normal('No friends online')}{/center}`; if(mdns.players.length === 0) return `{center}${getTheme().normal('No friends online')}{/center}`;
return mdns.players.map((player, i) => { return mdns.players.map((player, i) => {
if(i === this.selected) return ' ' + getTheme().selected(' ' + player.toString()); if(i === this.selected) return ' ' + getTheme().bright(' ' + player.toString());
else return ' ' + getTheme().normal(player.toString()); else return ' ' + getTheme().normal(player.toString());
}).join('\n'); }).join('\n');
}; };

View File

@ -6,36 +6,36 @@ import { panels } from "../UI.js";
import { View } from "../View.js"; import { View } from "../View.js";
export default class PawnsView extends View { export default class PawnsView extends View {
constructor() { constructor() {
super(); super();
this.name = 'Pawns'; this.name = 'Pawns';
} }
keypress(key: { full: string; }) { keypress(key: { full: string; }) {
if (key.full === 'delete') { if (key.full === 'delete') {
Game.current.removePawn(Game.current.selected); Game.current.removePawn(Game.current.selected);
} else if (key.full === 'up') { } else if (key.full === 'up') {
Game.current.advanceSelection(-1); Game.current.advanceSelection(-1);
} else if (key.full === 'down') { } else if (key.full === 'down') {
Game.current.advanceSelection(1); Game.current.advanceSelection(1);
} else if (key.full === 'enter') { } else if (key.full === 'enter') {
new PawnDetails(Game.current.selected); new PawnDetails(Game.current.selected);
} }
} }
render() { render() {
return `${ return `${
Game.current.pawns.map(pawn => `${(function() { Game.current.pawns.map(pawn => `${(function() {
const selected = pawn === Game.current.selected; const selected = pawn === Game.current.selected;
let str = ''; let str = '';
if(selected) { if(selected) {
str += ` ${getTheme().selected(` ${pawn.toString()}`)}{|}${pawn.status} \n`; str += ` ${getTheme().bright(` ${pawn.toString()}`)}{|}${pawn.status} \n`;
str += ` ${getTheme().normal('Energy')}{|}${progressbar(pawn.energy / 100, (panels.right.width - 4) / 2)} \n`; str += ` ${getTheme().normal('Energy')}{|}${progressbar(pawn.energy / 100, (panels.right.width - 4) / 2)} \n`;
} else { } else {
str += ` ${getTheme().normal(pawn.toString())}{|}${pawn.status} `; str += ` ${getTheme().normal(pawn.toString())}{|}${pawn.status} `;
} }
return str; return str;
})()}`).join('\n') })()}`).join('\n')
}`; }`;
} }
} }

View File

@ -12,8 +12,10 @@
"@actions": ["./src/registries/Actions"], "@actions": ["./src/registries/Actions"],
"@tasks": ["./src/registries/Tasks"], "@tasks": ["./src/registries/Tasks"],
"@items": ["./src/registries/Items"], "@items": ["./src/registries/Items"],
"@ui": ["./src/ui/UI"],
"@game": ["./src/Game"] "@game": ["./src/Game"]
} },
"noImplicitAny": true
}, },
"include": [ "include": [
"src/**/*.ts", "src/**/*.ts",

View File

@ -35,6 +35,13 @@
version "5.5.6" version "5.5.6"
resolved "https://registry.yarnpkg.com/@types/faker/-/faker-5.5.6.tgz#039b700a9d8ad9150ecc842bf5e717e2027b6f75" resolved "https://registry.yarnpkg.com/@types/faker/-/faker-5.5.6.tgz#039b700a9d8ad9150ecc842bf5e717e2027b6f75"
"@types/fs-extra@^9.0.11":
version "9.0.11"
resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-9.0.11.tgz#8cc99e103499eab9f347dbc6ca4e99fb8d2c2b87"
integrity sha512-mZsifGG4QeQ7hlkhO56u7zt/ycBgGxSVsFI/6lGTU34VtwkiqrrSDgw0+ygs8kFGWcXnFQWMrzF2h7TtDFNixA==
dependencies:
"@types/node" "*"
"@types/minimatch@^3.0.3", "@types/minimatch@^3.0.4": "@types/minimatch@^3.0.3", "@types/minimatch@^3.0.4":
version "3.0.4" version "3.0.4"
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.4.tgz#f0ec25dbf2f0e4b18647313ac031134ca5b24b21" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.4.tgz#f0ec25dbf2f0e4b18647313ac031134ca5b24b21"
@ -53,6 +60,13 @@
version "8.3.0" version "8.3.0"
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.0.tgz#215c231dff736d5ba92410e6d602050cce7e273f" resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.0.tgz#215c231dff736d5ba92410e6d602050cce7e273f"
"@types/ws@^7.4.6":
version "7.4.6"
resolved "https://registry.yarnpkg.com/@types/ws/-/ws-7.4.6.tgz#c4320845e43d45a7129bb32905e28781c71c1fff"
integrity sha512-ijZ1vzRawI7QoWnTNL8KpHixd2b2XVb9I9HAqI3triPsh1EC0xH0Eg6w2O3TKbDCgiNNlJqfrof6j4T2I+l9vw==
dependencies:
"@types/node" "*"
"@ungap/promise-all-settled@1.1.2": "@ungap/promise-all-settled@1.1.2":
version "1.1.2" version "1.1.2"
resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44"