From 3c6986acfe2a9d91ca3619e2901efa161ac619f9 Mon Sep 17 00:00:00 2001 From: Valerie Date: Fri, 18 Jun 2021 21:29:45 -0400 Subject: [PATCH 01/10] WIP, lots of things, doesnt compile --- src/index.ts | 4 + src/ui/Menu.ts | 155 ++++++++++----------------------- src/ui/Theme.ts | 4 +- src/ui/UI.ts | 3 +- src/ui/view/InventoryView.ts | 6 ++ src/ui/view/MultiplayerView.ts | 7 ++ src/ui/view/PawnsView.ts | 10 +++ 7 files changed, 77 insertions(+), 112 deletions(-) create mode 100644 src/ui/view/InventoryView.ts create mode 100644 src/ui/view/MultiplayerView.ts create mode 100644 src/ui/view/PawnsView.ts diff --git a/src/index.ts b/src/index.ts index 7f8644c..4b91094 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,5 +7,9 @@ const saveFile = process.argv[2] || 'data/world01.json'; ensureDirSync(parse(saveFile).dir); +// TODO move render logic into game, so that the ui doesnt exist until the game does... +// maybe, i mean, an argument could be made for not that, because the game +// isnt necessarily the entire thing, its just one instance of a save file. +// But probably the initial menu screens will be their own thing entirely. const game = Game.create(saveFile); render(game); diff --git a/src/ui/Menu.ts b/src/ui/Menu.ts index f900fbf..b20ab99 100644 --- a/src/ui/Menu.ts +++ b/src/ui/Menu.ts @@ -10,22 +10,30 @@ import { GiftPopup } from './GiftPopup.js'; import { PawnDetails } from './PawnDetails.js'; import { defaultTheme, getTheme } from './Theme.js'; import { inspect } from 'util'; +import PawnsView from './view/PawnsView.js'; +import InventoryView from './view/InventoryView.js'; +import MultiplayerView from './view/MultiplayerView.js'; -enum SubMenu { - NONE = 'NONE', - TREES = 'TREES' -}; +// TODO extract View +export abstract class View implements Renderable, KeypressAcceptor { + abstract render(): void; + abstract keypress(key: {full: string}): void; -enum View { - PAWNS = 'Pawns', - INVENTORY = 'Inventory', - MULTIPLAYER = 'Multiplayer', -}; + static PAWNS: View = new PawnsView(); + static INVENTORY: View = new InventoryView(); + static MULTIPLAYER: View = new MultiplayerView(); + + name: string +} + +// TODO move KeypressAcceptor to ui something idk +export interface KeypressAcceptor { + keypress(key: {full: string}): void +} export class Menu implements Renderable { trees: number = 10; - subMenu: SubMenu = SubMenu.NONE; view: View = View.PAWNS; constructor() { @@ -36,95 +44,43 @@ export class Menu implements Renderable { this.view = View[Object.keys(View)[Math.min(Math.max(Object.values(View).indexOf(this.view) - 1, 0), Object.keys(View).length - 1)]] } else if (key.full === 'right') { this.view = View[Object.keys(View)[Math.min(Math.max(Object.values(View).indexOf(this.view) + 1, 0), Object.keys(View).length - 1)]] - } else if (key.full === 'q') { - this.subMenu = SubMenu.TREES; + + // debugging hotkeys } else if (key.full === '1') { Popup.show(inspect(stats)); - } else if (key.full === '2') { - Popup.show('Etiam hendrerit elit sit amet metus congue dictum nec eu lacus. Sed aliquam in justo efficitur faucibus. Duis tellus diam, congue volutpat lorem et, semper consectetur erat. Nunc ac velit dignissim, tincidunt augue eget, tristique orci. Duis lacus sapien, bibendum id pharetra vel, semper et nunc. Vestibulum eu tellus imperdiet, lacinia ante ac, porta nisl. Donec at eleifend risus, ac dictum odio.'); - } else if (key.full === 'escape') { - this.subMenu = SubMenu.NONE; + } else if (key.full === 'z') { + Game.current.pawns.push(new Pawn()); + } else if (key.full === 'x') { + Game.current.board.clear(); } - if(this.view === View.PAWNS) { - if (key.full === 'delete') { - Game.current.removePawn(Game.current.selected); - } else if (key.full === 'up') { - Game.current.advanceSelection(-1); - } else if (key.full === 'down') { - Game.current.advanceSelection(1); - } else if (key.full === 'enter') { - new PawnDetails(Game.current.selected); - } - } + // if(this.view === View.PAWNS) { + // if (key.full === 'delete') { + // Game.current.removePawn(Game.current.selected); + // } else if (key.full === 'up') { + // Game.current.advanceSelection(-1); + // } else if (key.full === 'down') { + // Game.current.advanceSelection(1); + // } else if (key.full === 'enter') { + // new PawnDetails(Game.current.selected); + // } + // } - if(this.view === View.MULTIPLAYER) { - if (key.full === 'enter') { - new GiftPopup(mdns.players[this.multiplayerSelected]); - // mdns.players[this.multiplayerSelected].sendItem(null); - } else if (key.full === 'up') { - this.multiplayerSelected --; - } else if (key.full === 'down') { - this.multiplayerSelected ++; - } - } + // if(this.view === View.MULTIPLAYER) { + // if (key.full === 'enter') { + // new GiftPopup(mdns.players[this.multiplayerSelected]); + // // mdns.players[this.multiplayerSelected].sendItem(null); + // } else if (key.full === 'up') { + // this.multiplayerSelected --; + // } else if (key.full === 'down') { + // this.multiplayerSelected ++; + // } + // } - if(this.subMenu === SubMenu.TREES) { - if (key.full === '=') { - this.trees ++; - } else if (key.full === '-') { - this.trees --; - this.trees = Math.max(this.trees, 1); - } else if (key.full === '+') { - this.trees += 10; - } else if (key.full === '_') { - this.trees -= 10; - this.trees = Math.max(this.trees, 1); - } else if (key.full === 'enter') { - for(let i = 0; i < this.trees; i ++) { - Game.current.board.addTask(new ChopTreeTask(1)); - } - this.subMenu = SubMenu.NONE; - } - } else if(this.subMenu === SubMenu.NONE) { - if (key.full === 'z') { - Game.current.pawns.push(new Pawn()); - } else if (key.full === 'x') { - Game.current.board.clear(); - } - } - - // const pawn = new Pawn(); - // Game.current.pawns.push(pawn); Game.current.sync(); }); } - renderJobs() { - - const colSpace = ((menuPanel.width - 2) / 2); - - return (` ${getTheme().header('Menus')}${getTheme().normal(':')}${ - ' '.repeat(colSpace - 8) - }${getTheme().header('Actions')}${getTheme().normal(':')}\n ${ - getTheme().hotkey('q') - }${getTheme().normal(': ')}${ - (this.subMenu !== SubMenu.TREES ? getTheme().normal : getTheme().selected)('Chop Trees') - }${ - ' '.repeat(colSpace - 15) - }${getTheme().hotkey('z')}${getTheme().normal(': ')}${ - (this.subMenu !== SubMenu.NONE ? getTheme().normal : getTheme().selected)('Create Pawn') - - }\n${ - ' '.repeat(colSpace) - }${ - getTheme().hotkey('x') - }${getTheme().normal(': ')}${ - (this.subMenu !== SubMenu.NONE ? getTheme().normal : getTheme().selected)('Clear Tasks') - }`); - - } - renderTopBar() { const idlers = Game.current.pawns.filter(pawn => pawn.idle); return ` ${Game.current.clock.render()}{|}${getTheme().normal(`Idle: ${idlers.length}`)} `; @@ -160,11 +116,7 @@ export class Menu implements Renderable { } }).join(''); })()}{/center}\n\n${(() => { - switch(this.view) { - case View.PAWNS: return this.renderPawns(); - case View.INVENTORY: return this.renderInv(); - case View.MULTIPLAYER: return this.renderMultiplayer(); - } + this.view.view.render(); })()}` } @@ -182,17 +134,6 @@ export class Menu implements Renderable { return Game.current.inv.render(); } - renderSubMenu() { - return `${(() => { - switch(this.subMenu) { - case SubMenu.NONE: - return `{center}${getTheme().normal('* Select a menu above for options *')}{/center}`; - case SubMenu.TREES: - return this.renderTreesSubMenu(); - } - })()}`; - } - renderTreesSubMenu() { return [ `{center}Chop Trees`, @@ -209,10 +150,6 @@ export class Menu implements Renderable { this.renderTopBar(), hr, this.renderView(), - hr, - this.renderJobs(), - hr, - this.renderSubMenu() ].join('\n'); menuPanel.setContent(content); } diff --git a/src/ui/Theme.ts b/src/ui/Theme.ts index 6252cfc..792e709 100644 --- a/src/ui/Theme.ts +++ b/src/ui/Theme.ts @@ -35,8 +35,8 @@ export const defaultTheme: Theme = { selected: chalk.ansi256(250), hotkey: chalk.ansi256(40), tab: { - normal: chalk.ansi256(117).bgAnsi256(232), - selected: chalk.ansi256(232).bgAnsi256(117) + normal: chalk.ansi256(117), + selected: chalk.ansi256(117).inverse }, border: { focused: '#ffffff', diff --git a/src/ui/UI.ts b/src/ui/UI.ts index d7d374b..dc1f67b 100644 --- a/src/ui/UI.ts +++ b/src/ui/UI.ts @@ -9,9 +9,10 @@ export const screen = blessed.screen({ }); export interface Renderable { - render: () => void + render(): void } +// TODO move this to theme export const boxStyle = () => { return { style: { diff --git a/src/ui/view/InventoryView.ts b/src/ui/view/InventoryView.ts new file mode 100644 index 0000000..4b6fffc --- /dev/null +++ b/src/ui/view/InventoryView.ts @@ -0,0 +1,6 @@ +import { View } from "../Menu"; + +export default class InventoryView extends View { + keypress: (key: { full: string; }) => void; + render() { void 0 }; +} \ No newline at end of file diff --git a/src/ui/view/MultiplayerView.ts b/src/ui/view/MultiplayerView.ts new file mode 100644 index 0000000..ae7ee0b --- /dev/null +++ b/src/ui/view/MultiplayerView.ts @@ -0,0 +1,7 @@ +import { KeypressAcceptor, View } from "../Menu"; +import { Renderable } from "../UI"; + +export default class MultiplayerView extends View { + keypress: (key: { full: string; }) => void; + render() { void 0 }; +} \ No newline at end of file diff --git a/src/ui/view/PawnsView.ts b/src/ui/view/PawnsView.ts new file mode 100644 index 0000000..e6d19d4 --- /dev/null +++ b/src/ui/view/PawnsView.ts @@ -0,0 +1,10 @@ +import { View } from "../Menu.js"; + +export default class PawnsView extends View { + constructor() { + super(); + this.name = 'Pawns'; + } + keypress: (key: { full: string; }) => void; + render() { void 0 }; +} \ No newline at end of file From 8e38189560e750b576a4c1aa602fe6074f0d0b80 Mon Sep 17 00:00:00 2001 From: Bronwen Date: Sat, 19 Jun 2021 12:40:01 -0400 Subject: [PATCH 02/10] finally fixed colors in blessed! --- src/Pawn.ts | 211 +++++++++++----------- src/Time.ts | 317 +++++++++++++++++---------------- src/ui/Menu.ts | 47 ++--- src/ui/Popup.ts | 7 +- src/ui/Theme.ts | 136 +++++++------- src/ui/View.ts | 9 + src/ui/view/InventoryView.ts | 6 +- src/ui/view/MultiplayerView.ts | 7 +- src/ui/view/PawnsView.ts | 2 +- yarn.lock | 1 + 10 files changed, 391 insertions(+), 352 deletions(-) create mode 100644 src/ui/View.ts diff --git a/src/Pawn.ts b/src/Pawn.ts index 85f6b35..16ebf57 100644 --- a/src/Pawn.ts +++ b/src/Pawn.ts @@ -1,6 +1,5 @@ import { Serializable } from 'frigid'; import faker from 'faker'; -import chalk from 'chalk'; import log from './log.js'; import { Task } from './tasks/Task.js'; import Time, { Tickable } from './Time.js'; @@ -10,13 +9,13 @@ import { render } from './ui/UI.js'; import { Memory } from './Memory.js'; const LABORS = { - CUT_TREE: Symbol('CUT_TREE'), - MINING: Symbol('CUT_TREE'), + CUT_TREE: Symbol('CUT_TREE'), + MINING: Symbol('CUT_TREE'), } const SKILLS = { - PICKAXE: Symbol('PICKAXE'), - HATCHET: Symbol('HATCHET') + PICKAXE: Symbol('PICKAXE'), + HATCHET: Symbol('HATCHET') } // const STATUS = { @@ -26,121 +25,121 @@ const SKILLS = { const energyScale = 0.1; export class Pawn extends Serializable implements Tickable { - name: { - first: string, - last: string - }; - job: Task; - awake: boolean; - sex: number; + name: { + first: string, + last: string + }; + job: Task; + awake: boolean; + sex: number; - energy: number; - fun: number; + energy: number; + fun: number; - age: number; + age: number; - memories: Memory[]; + memories: Memory[]; - async tick() { - this.age ++; + async tick() { + this.age ++; - this.energy -= energyScale; + this.energy -= energyScale; - if(this.awake === false) { - this.energy += energyScale * 4; - if(this.energy >= 100) { - this.awake = true; - } - } else { - if(this.job) { - this.job.doWork(1, this); - this.energy -= energyScale; - if(this.job?.completed) { - this.stopWorking(); - } - } else { - const inactive = Game.current.board.tasks.filter(task => { - return task.worker === null; - }); - if(inactive.length > 0) { - const task = inactive[0]; - // const task = inactive[Math.floor(Math.random() * inactive.length)]; - this.assignJob(task); - } - } - if(this.energy <= 0) { - this.stopWorking(); - this.awake = false; - } - } + if(this.awake === false) { + this.energy += energyScale * 4; + if(this.energy >= 100) { + this.awake = true; + } + } else { + if(this.job) { + this.job.doWork(1, this); + this.energy -= energyScale; + if(this.job?.completed) { + this.stopWorking(); + } + } else { + const inactive = Game.current.board.tasks.filter(task => { + return task.worker === null; + }); + if(inactive.length > 0) { + const task = inactive[0]; + // const task = inactive[Math.floor(Math.random() * inactive.length)]; + this.assignJob(task); + } + } + if(this.energy <= 0) { + this.stopWorking(); + this.awake = false; + } + } - } + } - get idle() { - return !this.job && this.awake; - } + get idle() { + return !this.job && this.awake; + } - ctor() { - log.info('Pawn::ctor') - this.name ??= { - first: faker.name.firstName(), - last: faker.name.lastName() - }; - if(!this.sex) { - this.sex = Math.round(Math.random()); - this.name.first = faker.name.firstName(this.sex); - } - this.awake ??= true; - this.energy ??= 100; - this.memories ??= []; - if(!this.age) { - this.age = Math.floor(525600 * (16 + Math.random() * 9)); - this.memories.push({ - type: "birth", - location: Game.current.name, - time: { - age: 0, - locale: new Time(Game.current.clock.stamp - this.age).toString() - } - }) - } + ctor() { + log.info('Pawn::ctor') + this.name ??= { + first: faker.name.firstName(), + last: faker.name.lastName() + }; + if(!this.sex) { + this.sex = Math.round(Math.random()); + this.name.first = faker.name.firstName(this.sex); + } + this.awake ??= true; + this.energy ??= 100; + this.memories ??= []; + if(!this.age) { + this.age = Math.floor(525600 * (16 + Math.random() * 9)); + this.memories.push({ + type: "birth", + location: Game.current.name, + time: { + age: 0, + locale: new Time(Game.current.clock.stamp - this.age).toString() + } + }) + } - if(this.job?.completed) { - this.stopWorking(); - } - } + if(this.job?.completed) { + this.stopWorking(); + } + } - stopWorking() { - if(this.job) { - this.job.stopJob(); - this.job = null; - } - } + stopWorking() { + if(this.job) { + this.job.stopJob(); + this.job = null; + } + } - assignJob(task: Task) { - this.job?.stopJob() - this.job = task; - this.job.claim(this); - } + assignJob(task: Task) { + this.job?.stopJob() + this.job = task; + this.job.claim(this); + } - get status() { - if(this.job) { - return this.job.status; - } else { - return this.awake ? chalk.bold.black('IDLE') : chalk.blue('RESTING') - } - } + get status() { + if(this.job) { + return this.job.status; + } else { + return this.awake ? chalk.bold.black('IDLE') : chalk.blue('RESTING') + } + } - static serializationDependencies() { - return [Task, ChopTreeTask] - } + static serializationDependencies() { + return [Task, ChopTreeTask] + } - toString() { - if(this.name) { - return this.name.first + ' ' + this.name.last; - } else { - return '[Object Pawn]'; - } - } + toString() { + if(this.name) { + return this.name.first + ' ' + this.name.last; + } else { + return '[Object Pawn]'; + } + } } diff --git a/src/Time.ts b/src/Time.ts index 38be5bc..05fafd8 100644 --- a/src/Time.ts +++ b/src/Time.ts @@ -1,197 +1,198 @@ import chalk from "chalk"; import { Serializable } from "frigid"; -import { isThisTypeNode } from "typescript"; -import log from "./log.js"; import { getTheme } from "./ui/Theme.js"; import { Renderable } from "./ui/UI.js"; +type AbbreviatedMonthName = string; + + const daysInMonth = [ - 31, 28, 31, - 30, 31, 30, - 31, 31, 30, - 31, 30, 31 + 31, 28, 31, + 30, 31, 30, + 31, 31, 30, + 31, 30, 31 ]; -const months = [ - 'Jan', 'Feb', 'Mar', - 'Apr', 'May', 'Jun', - 'Jul', 'Aug', 'Sep', - 'Oct', 'Nov', 'Dec' +const months: AbbreviatedMonthName[] = [ + 'Jan', 'Feb', 'Mar', + 'Apr', 'May', 'Jun', + 'Jul', 'Aug', 'Sep', + 'Oct', 'Nov', 'Dec' ] export default class Time extends Serializable implements Renderable { - rate: number; - paused = true; + rate: number; + paused = true; - thing: Tickable; + thing: Tickable; - year: number; - month: number; - day: number; - hour: number; - minute: number; + year: number; + month: number; + day: number; + hour: number; + minute: number; - constructor(timestamp: number = 0) { - super(); - this.minute = timestamp; - this.normalize(); - } + constructor(timestamp: number = 0) { + super(); + this.minute = timestamp; + this.normalize(); + } - asAge() { - if(this.year > 1) { - return this.year + ' years old'; - } else { - if(this.month > 2) { - return this.month + ' months old'; - } else { - if(this.day > 1) { - return this.day + ' days old'; - } else if(this.day === 1) { - return '1 day old'; - } else { - return 'newborn'; - } - } - } - } + asAge() { + if(this.year > 1) { + return this.year + ' years old'; + } else { + if(this.month > 2) { + return this.month + ' months old'; + } else { + if(this.day > 1) { + return this.day + ' days old'; + } else if(this.day === 1) { + return '1 day old'; + } else { + return 'newborn'; + } + } + } + } - render() { - const sym = (this.hour >= 6 && this.hour < 20) ? - chalk.ansi256(226).bgAnsi256(27)(' ⬤ ') : - chalk.ansi256(254).bgAnsi256(17)(' ☾ ') + render() { + const sym = (this.hour >= 6 && this.hour < 20) ? + chalk.ansi256(226).bgAnsi256(27)(' ☀ ') : + chalk.ansi256(254).bgAnsi256(17)(' ☾ ') - return `${sym} ${ - getTheme().normal(`${ - this.hour.toString().padStart(2, ' ') - }:${ - this.minute.toString().padStart(2, '0') - } ${ - months[this.month] - } ${ - this.day + 1 - }, ${ - this.normalizedYear - }`) - }`; + return `${sym} ${ + getTheme().normal(`${ + this.hour.toString().padStart(2, ' ') + }:${ + this.minute.toString().padStart(2, '0') + } ${ + months[this.month] + } ${ + this.day + 1 + }, ${ + this.normalizedYear + }`) + }`; - // return '☾' || '☼'; - } + // return '☾' || '☼'; + } - toString() { - return `${this.hour}:${this.minute.toString().padStart(2, '0')} ${months[this.month]} ${this.day + 1}, ${this.normalizedYear}` - } + toString() { + return `${this.hour}:${this.minute.toString().padStart(2, '0')} ${months[this.month]} ${this.day + 1}, ${this.normalizedYear}` + } - ctor() { - this.rate = 60; - this.minute ??= 0; - this.hour ??= 0; - this.day ??= 0; - this.month ??= 0; - this.year ??= 0; - } + ctor() { + this.rate = 60; + this.minute ??= 0; + this.hour ??= 0; + this.day ??= 0; + this.month ??= 0; + this.year ??= 0; + } - get stamp() { - let minute = this.minute; - let hour = this.hour; - let day = this.day; - let month = this.month; - let year = this.year; + get stamp() { + let minute = this.minute; + let hour = this.hour; + let day = this.day; + let month = this.month; + let year = this.year; - const daysInYear = daysInMonth.reduce((a, b) => a+b, 0); + const daysInYear = daysInMonth.reduce((a, b) => a+b, 0); - day += daysInYear * year; - year = 0; - while(month > 0) { - day += daysInMonth[month]; - month --; - } + day += daysInYear * year; + year = 0; + while(month > 0) { + day += daysInMonth[month]; + month --; + } - hour += day * 24; - day = 0; + hour += day * 24; + day = 0; - minute += hour * 60; - hour = 0; + minute += hour * 60; + hour = 0; - return minute; - } + return minute; + } - pause() { - this.paused = true; - } + pause() { + this.paused = true; + } - start() { - this.paused = false; - setTimeout(this.doTick.bind(this), 0); - } - - advanceTime(minutes) { - this.minute ++; - this.normalize() - } + start() { + this.paused = false; + setTimeout(this.doTick.bind(this), 0); + } + + advanceTime(minutes) { + this.minute ++; + this.normalize() + } - get normalizedYear() { - if(this.year >= 0) { - return (this.year + 1).toString().padStart(4, '0') + ' CE'; - } else { - return Math.abs(this.year).toString().padStart(4, '0') + ' BCE'; - } - } + get normalizedYear() { + if(this.year >= 0) { + return (this.year + 1).toString().padStart(4, '0') + ' CE'; + } else { + return Math.abs(this.year).toString().padStart(4, '0') + ' BCE'; + } + } - normalize() { - while(this.minute >= 60) { - this.minute -= 60; - this.hour ++; - } - while(this.minute < 0) { - this.minute += 60; - this.hour --; - } + normalize() { + while(this.minute >= 60) { + this.minute -= 60; + this.hour ++; + } + while(this.minute < 0) { + this.minute += 60; + this.hour --; + } - while(this.hour >= 24) { - this.hour -= 24; - this.day ++; - } - while(this.hour < 0) { - this.hour += 24; - this.day --; - } + while(this.hour >= 24) { + this.hour -= 24; + this.day ++; + } + while(this.hour < 0) { + this.hour += 24; + this.day --; + } - while(this.day < 0) { - this.day += daysInMonth[ - ((this.month % months.length) + months.length) % months.length - ]; - this.month --; - } - while(this.day >= daysInMonth[this.month % months.length]) { - this.day -= daysInMonth[this.month % months.length]; - this.month ++; - } + while(this.day < 0) { + this.day += daysInMonth[ + ((this.month % months.length) + months.length) % months.length + ]; + this.month --; + } + while(this.day >= daysInMonth[this.month % months.length]) { + this.day -= daysInMonth[this.month % months.length]; + this.month ++; + } - while(this.month >= 12) { - this.month -= 12; - this.year ++; - } - while(this.month < 0) { - this.month += 12; - this.year --; - } - } + while(this.month >= 12) { + this.month -= 12; + this.year ++; + } + while(this.month < 0) { + this.month += 12; + this.year --; + } + } - async doTick() { - this.advanceTime(1); - const timeout = 1000 / this.rate; - const start = new Date().getTime(); - if(this.thing) { - await this.thing.tick(); - } - const elapsed = new Date().getTime() - start; - const wait = Math.max(timeout - elapsed, 0); - if(this.paused) return; - setTimeout(this.doTick.bind(this), wait) - } + async doTick() { + this.advanceTime(1); + const timeout = 1000 / this.rate; + const start = new Date().getTime(); + if(this.thing) { + await this.thing.tick(); + } + const elapsed = new Date().getTime() - start; + const wait = Math.max(timeout - elapsed, 0); + if(this.paused) return; + setTimeout(this.doTick.bind(this), wait) + } } export interface Tickable { - tick: () => Promise + tick: () => Promise } \ No newline at end of file diff --git a/src/ui/Menu.ts b/src/ui/Menu.ts index b20ab99..4a5cb4a 100644 --- a/src/ui/Menu.ts +++ b/src/ui/Menu.ts @@ -2,29 +2,17 @@ import { Pawn } from '../Pawn.js'; import log from '../log.js'; import { menuPanel, Renderable } from './UI.js'; import { Game } from '../Game.js'; -import { ChopTreeTask } from '../tasks/ChopTreeTask.js'; -import { progressbar, stats, barCache } from '../Progressbar.js'; +import { progressbar, stats } from '../Progressbar.js'; import { Popup } from './Popup.js'; import mdns from '../multiplayer/mDNS.js'; -import { GiftPopup } from './GiftPopup.js'; -import { PawnDetails } from './PawnDetails.js'; -import { defaultTheme, getTheme } from './Theme.js'; +import { getTheme } from './Theme.js'; import { inspect } from 'util'; import PawnsView from './view/PawnsView.js'; import InventoryView from './view/InventoryView.js'; import MultiplayerView from './view/MultiplayerView.js'; +import { View } from './View.js'; -// TODO extract View -export abstract class View implements Renderable, KeypressAcceptor { - abstract render(): void; - abstract keypress(key: {full: string}): void; - - static PAWNS: View = new PawnsView(); - static INVENTORY: View = new InventoryView(); - static MULTIPLAYER: View = new MultiplayerView(); - - name: string -} +const clamp = (min, max, value) => Math.min(Math.max(value, min), max); // TODO move KeypressAcceptor to ui something idk export interface KeypressAcceptor { @@ -34,16 +22,35 @@ export interface KeypressAcceptor { export class Menu implements Renderable { trees: number = 10; - view: View = View.PAWNS; + viewIndex: number = 0; + views: View[] = [ + new PawnsView(), + new InventoryView(), + new MultiplayerView() + ] + + get view() { + return this.views[this.viewIndex]; + } + + advanceView() { + this.viewIndex ++; + this.viewIndex = clamp(0, this.views.length - 1, this.viewIndex); + } + + regressView() { + this.viewIndex --; + this.viewIndex = clamp(0, this.views.length - 1, this.viewIndex); + } constructor() { menuPanel.on('keypress', (evt, key) => { log.info('keypress', key); if (key.full === 'left') { - this.view = View[Object.keys(View)[Math.min(Math.max(Object.values(View).indexOf(this.view) - 1, 0), Object.keys(View).length - 1)]] + this.regressView(); } else if (key.full === 'right') { - this.view = View[Object.keys(View)[Math.min(Math.max(Object.values(View).indexOf(this.view) + 1, 0), Object.keys(View).length - 1)]] + this.advanceView(); // debugging hotkeys } else if (key.full === '1') { @@ -116,7 +123,7 @@ export class Menu implements Renderable { } }).join(''); })()}{/center}\n\n${(() => { - this.view.view.render(); + this.view.render(); })()}` } diff --git a/src/ui/Popup.ts b/src/ui/Popup.ts index 2e2c4d0..ba2867b 100644 --- a/src/ui/Popup.ts +++ b/src/ui/Popup.ts @@ -15,12 +15,15 @@ export class Popup { this.box = blessed.box({ top: 'center', left: 'center', - width: 'shrink', + width: '100%', height: 'shrink', - content: getTheme().normal(content) + `\n\n{|}` + getTheme().hotkey('enter') + getTheme().normal(`: Okay `), + // content: getTheme().normal(content) + `\n\n{|}` + getTheme().hotkey('enter') + getTheme().normal(`: Okay `), tags: true, ...boxStyle(), }); + let stuff = ''; + for(let i = 16; i < 232; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%18===0?'\n':''}`) + this.box.setContent(stuff) this.box.on('keypress', (evt, key) => { if(key.full === 'escape' || key.full === 'enter') { Game.current.clock.start(); diff --git a/src/ui/Theme.ts b/src/ui/Theme.ts index 792e709..6eb2f38 100644 --- a/src/ui/Theme.ts +++ b/src/ui/Theme.ts @@ -1,77 +1,89 @@ -import chalk from "chalk"; +// blessed doesnt know QUITE how to deal with 16m color modes +// it will always downsample them to 256. which is fine, but +// blessed's algorithm sucks, and comes out with incorrect +// mappings for certain colors. Instead of dealing with that, +// here, we simply tell chalk to always output ansi256 codes +// instead of upsampling them to 16m codes. +import chalk from 'chalk'; +chalk.level = 2; type StyleFunction = (text: string) => string; export type Theme = { - header: StyleFunction, - subheader: StyleFunction, - normal: StyleFunction, - selected: StyleFunction, - hotkey: StyleFunction, - tab: { - normal: StyleFunction, - selected: StyleFunction - }, - border: { - focused: string, - normal: string - }, - progressBar: { - indicator: { - critical: StyleFunction, - warning: StyleFunction, - normal: StyleFunction, - excellent: StyleFunction, - buckets: [number, number, number] - }, - normal: StyleFunction - } + header: StyleFunction, + subheader: StyleFunction, + normal: StyleFunction, + selected: StyleFunction, + hotkey: StyleFunction, + tab: { + normal: StyleFunction, + selected: StyleFunction + }, + border: { + focused: string, + normal: string + }, + progressBar: { + indicator: { + critical: StyleFunction, + warning: StyleFunction, + normal: StyleFunction, + excellent: StyleFunction, + buckets: [number, number, number] + }, + normal: StyleFunction + }, + status: { + idle: StyleFunction, + self: StyleFunction, + + } } export const defaultTheme: Theme = { - header: chalk.ansi256(255).bold, - subheader: chalk.ansi256(243).bold, - normal: chalk.ansi256(243), - selected: chalk.ansi256(250), - hotkey: chalk.ansi256(40), - tab: { - normal: chalk.ansi256(117), - selected: chalk.ansi256(117).inverse - }, - border: { - focused: '#ffffff', - normal: '#222222' - }, - progressBar: { - indicator: { - critical: chalk.bgAnsi256(235).ansi256(88), - warning: chalk.bgAnsi256(235).ansi256(202), - normal: chalk.bgAnsi256(235).ansi256(70), - excellent: chalk.bgAnsi256(235).ansi256(87), - buckets: [.1, .25, .95] - }, - normal: chalk.bgAnsi256(235).ansi256(243) - } + header: chalk.ansi256(255).bold, + subheader: chalk.ansi256(243).bold, + normal: chalk.ansi256(243), + selected: chalk.ansi256(250), + hotkey: chalk.ansi256(40), + tab: { + normal: chalk.ansi256(117), + selected: chalk.ansi256(117).inverse + }, + border: { + focused: '#ffffff', + normal: '#222222' + }, + progressBar: { + indicator: { + critical: chalk.bgAnsi256(235).ansi256(88), + warning: chalk.bgAnsi256(235).ansi256(202), + normal: chalk.bgAnsi256(235).ansi256(70), + excellent: chalk.bgAnsi256(235).ansi256(87), + buckets: [.1, .25, .95] + }, + normal: chalk.bgAnsi256(235).ansi256(243) + } } const debugStyle = chalk.ansi256(213); export const debugTheme: Theme = { - header: debugStyle.inverse, - subheader: debugStyle, - normal: debugStyle, - selected: debugStyle.inverse, - hotkey: debugStyle, - tab: { - normal: debugStyle, - selected: debugStyle.inverse, - }, - border: { - focused: '#ff88ff', - normal: '#ff00ff' - }, - progressBar: defaultTheme.progressBar + header: debugStyle.inverse, + subheader: debugStyle, + normal: debugStyle, + selected: debugStyle.inverse, + hotkey: debugStyle, + tab: { + normal: debugStyle, + selected: debugStyle.inverse, + }, + border: { + focused: '#ff88ff', + normal: '#ff00ff' + }, + progressBar: defaultTheme.progressBar } export function getTheme(): Theme { - return defaultTheme; + return defaultTheme; } \ No newline at end of file diff --git a/src/ui/View.ts b/src/ui/View.ts new file mode 100644 index 0000000..d7b278e --- /dev/null +++ b/src/ui/View.ts @@ -0,0 +1,9 @@ +import { Renderable } from './UI.js'; +import { KeypressAcceptor } from './Menu.js'; + +export abstract class View implements Renderable, KeypressAcceptor { + abstract render(): void; + abstract keypress(key: { full: string; }): void; + + name: string; +} diff --git a/src/ui/view/InventoryView.ts b/src/ui/view/InventoryView.ts index 4b6fffc..77d2fe4 100644 --- a/src/ui/view/InventoryView.ts +++ b/src/ui/view/InventoryView.ts @@ -1,6 +1,10 @@ -import { View } from "../Menu"; +import { View } from "../View.js"; export default class InventoryView extends View { + constructor() { + super(); + this.name = 'Inventory'; + } keypress: (key: { full: string; }) => void; render() { void 0 }; } \ No newline at end of file diff --git a/src/ui/view/MultiplayerView.ts b/src/ui/view/MultiplayerView.ts index ae7ee0b..30b1929 100644 --- a/src/ui/view/MultiplayerView.ts +++ b/src/ui/view/MultiplayerView.ts @@ -1,7 +1,10 @@ -import { KeypressAcceptor, View } from "../Menu"; -import { Renderable } from "../UI"; +import { View } from "../View.js"; export default class MultiplayerView extends View { + constructor() { + super(); + this.name = 'Multiplayer'; + } keypress: (key: { full: string; }) => void; render() { void 0 }; } \ No newline at end of file diff --git a/src/ui/view/PawnsView.ts b/src/ui/view/PawnsView.ts index e6d19d4..b46f8c8 100644 --- a/src/ui/view/PawnsView.ts +++ b/src/ui/view/PawnsView.ts @@ -1,4 +1,4 @@ -import { View } from "../Menu.js"; +import { View } from "../View.js"; export default class PawnsView extends View { constructor() { diff --git a/yarn.lock b/yarn.lock index da32f0f..8618512 100644 --- a/yarn.lock +++ b/yarn.lock @@ -210,6 +210,7 @@ multicast-dns@^6.0.1: neo-blessed@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/neo-blessed/-/neo-blessed-0.2.0.tgz#30f9495fdd104494402b62c6273a9c9b82de4f2b" + integrity sha512-C2kC4K+G2QnNQFXUIxTQvqmrdSIzGTX1ZRKeDW6ChmvPRw8rTkTEJzbEQHiHy06d36PCl/yMOCjquCRV8SpSQw== object-is@^1.0.1: version "1.1.5" From b697856c4ea9f50b2c17d92df3c4c907271c36c8 Mon Sep 17 00:00:00 2001 From: Valerie Date: Sat, 19 Jun 2021 18:23:44 -0400 Subject: [PATCH 03/10] themes registration, starting extensions API --- .vscode/tasks.json | 25 +++++++++++++ content/core/themes/ashe.ts | 0 content/core/themes/standard.ts | 8 +++++ lib/aliases.mjs | 33 +++++++++++++++++ package.json | 5 ++- src/Pawn.ts | 3 +- src/Progressbar.ts | 14 +++++++- src/Time.ts | 4 +-- src/index.ts | 29 +++++++++++---- src/ui/Theme.ts | 44 +++++++++++++---------- test.js | 0 tsconfig.json | 8 +++-- yarn.lock | 63 +++++++++++++++++++++++++++++++++ 13 files changed, 202 insertions(+), 34 deletions(-) create mode 100644 .vscode/tasks.json create mode 100644 content/core/themes/ashe.ts create mode 100644 content/core/themes/standard.ts create mode 100644 lib/aliases.mjs create mode 100644 test.js diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..aecda74 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,25 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "tsc watch", + "type": "npm", + "script": "compile:watch", + "isBackground": true, + "group": { + "kind": "build", + "isDefault": true + }, + "presentation": { + "reveal": "never", + "echo": false, + "focus": false, + "panel": "dedicated" + }, + "problemMatcher": { + "base": "$tsc-watch", + "applyTo": "allDocuments" + } + } + ] +} \ No newline at end of file diff --git a/content/core/themes/ashe.ts b/content/core/themes/ashe.ts new file mode 100644 index 0000000..e69de29 diff --git a/content/core/themes/standard.ts b/content/core/themes/standard.ts new file mode 100644 index 0000000..16fd29b --- /dev/null +++ b/content/core/themes/standard.ts @@ -0,0 +1,8 @@ +import { registerTheme } from '@theme'; +import chalk from 'chalk' + +registerTheme("default", {}); + +registerTheme("high contrast", { + selected: chalk.ansi256(250).inverse +}); \ No newline at end of file diff --git a/lib/aliases.mjs b/lib/aliases.mjs new file mode 100644 index 0000000..baca07c --- /dev/null +++ b/lib/aliases.mjs @@ -0,0 +1,33 @@ +import path from 'path'; + +const moduleAliases = { + "@theme": "./out/src/ui/Theme.js" +}; + +const getAliases = () => { + const base = process.cwd(); + const aliases = moduleAliases || {}; + const absoluteAliases = Object.keys(aliases).reduce((acc, key) => + aliases[key][0] === '/' + ? acc + : { ...acc, [key]: 'file:///' + path.join(base, aliases[key]) }, + aliases) + return absoluteAliases; +} + +const isAliasInSpecifier = (path, alias) => { + return path.indexOf(alias) === 0 + && (path.length === alias.length || path[alias.length] === '/') +} + +const aliases = getAliases(); + +export const resolve = (specifier, parentModuleURL, defaultResolve) => { + const alias = Object.keys(aliases).find((key) => isAliasInSpecifier(specifier, key)); + + const newSpecifier = alias === undefined + ? specifier + : path.join(aliases[alias], specifier.substr(alias.length)); + + return defaultResolve(newSpecifier, parentModuleURL); +} \ No newline at end of file diff --git a/package.json b/package.json index ffa6d61..5409b79 100644 --- a/package.json +++ b/package.json @@ -11,22 +11,25 @@ "@types/uuid": "^8.3.0", "bonjour": "^3.5.0", "chalk": "^4.1.1", + "deepmerge": "^4.2.2", "faker": "^5.5.3", "frigid": "^1.3.8", "fs-extra": "^10.0.0", "get-port": "^5.1.1", "logger": "^0.0.1", + "module-alias": "^2.2.2", "neo-blessed": "^0.2.0", "printable-characters": "^1.0.42", "sisteransi": "^1.0.5", "typescript": "^4.3.2", "uuid": "^8.3.2", + "walk-sync": "^3.0.0", "ws": "^7.4.6", "yarn": "^1.22.10" }, "scripts": { "compile:watch": "tsc --watch", - "start": "node --enable-source-maps out/index.js", + "start": "node --loader ./lib/aliases.mjs --enable-source-maps out/src/index.js", "dev": "supervisor -w out -n exit -t -k --exec yarn -- start", "prod": "git fetch && git pull && yarn && tsc && yarn start" } diff --git a/src/Pawn.ts b/src/Pawn.ts index 16ebf57..81317ab 100644 --- a/src/Pawn.ts +++ b/src/Pawn.ts @@ -7,6 +7,7 @@ import { ChopTreeTask } from './tasks/ChopTreeTask.js'; import { Game } from './Game.js'; import { render } from './ui/UI.js'; import { Memory } from './Memory.js'; +import { getTheme } from './ui/Theme.js'; const LABORS = { CUT_TREE: Symbol('CUT_TREE'), @@ -127,7 +128,7 @@ export class Pawn extends Serializable implements Tickable { if(this.job) { return this.job.status; } else { - return this.awake ? chalk.bold.black('IDLE') : chalk.blue('RESTING') + return this.awake ? getTheme().status.idle('IDLE') : getTheme().status.self('RESTING') } } diff --git a/src/Progressbar.ts b/src/Progressbar.ts index ae4d720..a715cfe 100644 --- a/src/Progressbar.ts +++ b/src/Progressbar.ts @@ -23,7 +23,19 @@ export function progressbar(completion: number, width: number, style: Progressba } else if(style === ProgressbarStyle.progress) { chalkFn = getTheme().progressBar.normal; } - const chars = [' ', '▏', '▎', '▍', '▌', '▋', '▊', '▉', '█']; + + const chars = [ + '\u0020', + '\u258f', + '\u258e', + '\u258d', + '\u258c', + '\u258b', + '\u258a', + '\u2589', + '\u2588' + ]; + let str = ''; for(let i = 0; i < width; i ++) { const remainder = Math.floor(Math.min(Math.max(0, (completion * width) - i), 1) * 8); diff --git a/src/Time.ts b/src/Time.ts index 05fafd8..25cf313 100644 --- a/src/Time.ts +++ b/src/Time.ts @@ -58,7 +58,7 @@ export default class Time extends Serializable implements Renderable { render() { const sym = (this.hour >= 6 && this.hour < 20) ? - chalk.ansi256(226).bgAnsi256(27)(' ☀ ') : + chalk.ansi256(226).bgAnsi256(27)(' ☼ ') : chalk.ansi256(254).bgAnsi256(17)(' ☾ ') return `${sym} ${ @@ -74,8 +74,6 @@ export default class Time extends Serializable implements Renderable { this.normalizedYear }`) }`; - - // return '☾' || '☼'; } toString() { diff --git a/src/index.ts b/src/index.ts index 4b91094..fe35d88 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,15 +1,30 @@ import { Game } from './Game.js'; import { render } from './ui/UI.js'; import { ensureDirSync } from 'fs-extra'; -import { parse } from 'path'; +import { lstatSync } from 'fs'; +import { parse, resolve } from 'path'; +import walkSync from 'walk-sync'; +import { fileURLToPath } from 'url'; const saveFile = process.argv[2] || 'data/world01.json'; ensureDirSync(parse(saveFile).dir); -// TODO move render logic into game, so that the ui doesnt exist until the game does... -// maybe, i mean, an argument could be made for not that, because the game -// isnt necessarily the entire thing, its just one instance of a save file. -// But probably the initial menu screens will be their own thing entirely. -const game = Game.create(saveFile); -render(game); +const extensionsPath = resolve(parse(fileURLToPath(import.meta.url)).dir, '../content'); + +const extensions = walkSync(extensionsPath) + .map(path => resolve(extensionsPath, path)) + .filter(path => lstatSync(path).isFile()) + .filter(path => parse(path).ext === '.js') + .map(path => import(path)); + +Promise.all(extensions).then((extensions) => { + + // TODO move render logic into game, so that the ui doesnt exist until the game does... + // maybe, i mean, an argument could be made for not that, because the game + // isnt necessarily the entire thing, its just one instance of a save file. + // But probably the initial menu screens will be their own thing entirely. + const game = Game.create(saveFile); + render(game); + +}); \ No newline at end of file diff --git a/src/ui/Theme.ts b/src/ui/Theme.ts index 6eb2f38..d1d8436 100644 --- a/src/ui/Theme.ts +++ b/src/ui/Theme.ts @@ -6,6 +6,8 @@ // instead of upsampling them to 16m codes. import chalk from 'chalk'; chalk.level = 2; +import merge from 'deepmerge'; +import log from '../log.js'; type StyleFunction = (text: string) => string; @@ -36,11 +38,11 @@ export type Theme = { status: { idle: StyleFunction, self: StyleFunction, - + work: StyleFunction } } -export const defaultTheme: Theme = { +export const backupTheme: Theme = { header: chalk.ansi256(255).bold, subheader: chalk.ansi256(243).bold, normal: chalk.ansi256(243), @@ -63,27 +65,31 @@ export const defaultTheme: Theme = { buckets: [.1, .25, .95] }, normal: chalk.bgAnsi256(235).ansi256(243) + }, + status: { + idle: chalk.ansi256(243), + self: chalk.ansi256(45), + work: chalk.ansi256(208) } } -const debugStyle = chalk.ansi256(213); -export const debugTheme: Theme = { - header: debugStyle.inverse, - subheader: debugStyle, - normal: debugStyle, - selected: debugStyle.inverse, - hotkey: debugStyle, - tab: { - normal: debugStyle, - selected: debugStyle.inverse, - }, - border: { - focused: '#ff88ff', - normal: '#ff00ff' - }, - progressBar: defaultTheme.progressBar +export type ThemeName = string; + +let currentTheme = backupTheme; +const themes: Map = new Map(); + +export function registerTheme(name: ThemeName, theme: Partial) { + log.info('registering theme', name) + themes.set(name, merge(backupTheme, theme)); +} + +export function setTheme(name: ThemeName): void { + if(!themes.has(name)) return; + currentTheme = themes.get(name); + + // TODO reset borders and other weird shit that wont just update on a re-render } export function getTheme(): Theme { - return defaultTheme; + return currentTheme; } \ No newline at end of file diff --git a/test.js b/test.js new file mode 100644 index 0000000..e69de29 diff --git a/tsconfig.json b/tsconfig.json index 64a23ae..49ad934 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,9 +6,13 @@ "allowSyntheticDefaultImports": true, "outDir": "out", "declaration": true, - "sourceMap": true + "sourceMap": true, + "paths": { + "@theme": ["./src/ui/Theme"] + } }, "include": [ - "src/**/*.ts" + "src/**/*.ts", + "content/**/*.ts" ] } \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 8618512..92e3e54 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18,6 +18,11 @@ version "5.5.6" resolved "https://registry.yarnpkg.com/@types/faker/-/faker-5.5.6.tgz#039b700a9d8ad9150ecc842bf5e717e2027b6f75" +"@types/minimatch@^3.0.3", "@types/minimatch@^3.0.4": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.4.tgz#f0ec25dbf2f0e4b18647313ac031134ca5b24b21" + integrity sha512-1z8k4wzFnNjVK/tlxvrWuK5WMt6mydWWP7+zvH5eFep4oj+UkrfiJTRtjCeBXNpwaA/FYqqtb4/QS4ianFpIRA== + "@types/node@*": version "15.12.2" resolved "https://registry.npmjs.org/@types/node/-/node-15.12.2.tgz" @@ -36,6 +41,11 @@ array-flatten@^2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + bonjour@^3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/bonjour/-/bonjour-3.5.0.tgz#8e890a183d8ee9a2393b3844c691a42bcf7bc9f5" @@ -47,6 +57,14 @@ bonjour@^3.5.0: multicast-dns "^6.0.1" multicast-dns-service-types "^1.1.0" +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + buffer-indexof@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c" @@ -75,6 +93,11 @@ color-name@~1.1.4: version "1.1.4" resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + deep-equal@^1.0.1: version "1.1.1" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" @@ -86,6 +109,11 @@ deep-equal@^1.0.1: object-keys "^1.1.1" regexp.prototype.flags "^1.2.0" +deepmerge@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" + integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== + define-properties@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" @@ -109,6 +137,11 @@ dns-txt@^2.0.2: dependencies: buffer-indexof "^1.0.0" +ensure-posix-path@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ensure-posix-path/-/ensure-posix-path-1.1.1.tgz#3c62bdb19fa4681544289edb2b382adc029179ce" + integrity sha512-VWU0/zXzVbeJNXvME/5EmLuEj2TauvoaTz6aFYK1Z92JCBlDlZ3Gu0tuGR42kpW1754ywTs+QB0g5TP0oj9Zaw== + faker@^5.5.3: version "5.5.3" resolved "https://registry.npmjs.org/faker/-/faker-5.5.3.tgz" @@ -196,6 +229,26 @@ logger@^0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/logger/-/logger-0.0.1.tgz#cb08171f8a6f6f674b8499dadf50bed4befb72c4" +matcher-collection@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/matcher-collection/-/matcher-collection-2.0.1.tgz#90be1a4cf58d6f2949864f65bb3b0f3e41303b29" + integrity sha512-daE62nS2ZQsDg9raM0IlZzLmI2u+7ZapXBwdoeBUKAYERPDDIc0qNqA8E0Rp2D+gspKR7BgIFP52GeujaGXWeQ== + dependencies: + "@types/minimatch" "^3.0.3" + minimatch "^3.0.2" + +minimatch@^3.0.2, minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +module-alias@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/module-alias/-/module-alias-2.2.2.tgz#151cdcecc24e25739ff0aa6e51e1c5716974c0e0" + integrity sha512-A/78XjoX2EmNvppVWEhM2oGk3x4lLxnkEA4jTbaK97QKSDjkIoOsKQlfylt/d3kKKi596Qy3NP5XrXJ6fZIC9Q== + multicast-dns-service-types@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901" @@ -265,6 +318,16 @@ uuid@^8.3.2: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" +walk-sync@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/walk-sync/-/walk-sync-3.0.0.tgz#67f882925021e20569a1edd560b8da31da8d171c" + integrity sha512-41TvKmDGVpm2iuH7o+DAOt06yyu/cSHpX3uzAwetzASvlNtVddgIjXIb2DfB/Wa20B1Jo86+1Dv1CraSU7hWdw== + dependencies: + "@types/minimatch" "^3.0.4" + ensure-posix-path "^1.1.0" + matcher-collection "^2.0.1" + minimatch "^3.0.4" + ws@^7.4.6: version "7.4.6" resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" From 29b407de75b2da8bb93e3ac8f5f9da7a33f337a4 Mon Sep 17 00:00:00 2001 From: Valerie Date: Sat, 19 Jun 2021 21:22:28 -0400 Subject: [PATCH 04/10] STUFF --- src/multiplayer/mDNS.ts | 6 ++- src/ui/Menu.ts | 74 +++++----------------------------- src/ui/Popup.ts | 18 ++++++++- src/ui/view/InventoryView.ts | 8 +++- src/ui/view/MultiplayerView.ts | 28 +++++++++++-- src/ui/view/PawnsView.ts | 35 +++++++++++++++- 6 files changed, 95 insertions(+), 74 deletions(-) diff --git a/src/multiplayer/mDNS.ts b/src/multiplayer/mDNS.ts index 884cb30..b3352c2 100644 --- a/src/multiplayer/mDNS.ts +++ b/src/multiplayer/mDNS.ts @@ -30,7 +30,7 @@ export type GiftMessage = { export default network; -export async function ready(name, onThing?) { +export async function ready(name) { const port = await getPort({port: getPort.makeRange(52300, 52399)}); mdns.publish({ type: 'dfi', @@ -73,4 +73,6 @@ mdns.find({ p.port = service.port; log.info('Found player', p); devices.push(p); -}); \ No newline at end of file +}).on("down", (service) => { + // TODO remove player from MP +}) \ No newline at end of file diff --git a/src/ui/Menu.ts b/src/ui/Menu.ts index 4a5cb4a..5312b86 100644 --- a/src/ui/Menu.ts +++ b/src/ui/Menu.ts @@ -59,19 +59,7 @@ export class Menu implements Renderable { Game.current.pawns.push(new Pawn()); } else if (key.full === 'x') { Game.current.board.clear(); - } - - // if(this.view === View.PAWNS) { - // if (key.full === 'delete') { - // Game.current.removePawn(Game.current.selected); - // } else if (key.full === 'up') { - // Game.current.advanceSelection(-1); - // } else if (key.full === 'down') { - // Game.current.advanceSelection(1); - // } else if (key.full === 'enter') { - // new PawnDetails(Game.current.selected); - // } - // } + } else this.view.keypress(key); // if(this.view === View.MULTIPLAYER) { // if (key.full === 'enter') { @@ -84,6 +72,8 @@ export class Menu implements Renderable { // } // } + // TODO add colortest debug screen! + Game.current.sync(); }); } @@ -93,61 +83,19 @@ export class Menu implements Renderable { return ` ${Game.current.clock.render()}{|}${getTheme().normal(`Idle: ${idlers.length}`)} `; } - renderPawns() { - return `${ - Game.current.pawns.map(pawn => `${(function() { - const selected = pawn === Game.current.selected; - let str = ''; - if(selected) { - str += ` ${getTheme().selected(` ❯ ${pawn.toString()}`)}{|}${pawn.status} \n`; - str += ` ${getTheme().normal('Energy')}{|}${progressbar(pawn.energy / 100, (menuPanel.width - 4) / 2)} \n`; - } else { - str += ` ${getTheme().normal(pawn.toString())}{|}${pawn.status} `; - } - return str; - })()}`).join('\n') - }`; - } - renderView() { const colSpace = ((menuPanel.width - 2) / 2); - return `${ - // ' '.repeat(colSpace - 20) - '{center}' - }${(() => { - return Object.values(View).map(view => { - if(view === this.view) { - return getTheme().tab.selected(` ${view} `); + return `{center}${(() => { + return Object.values(this.views).map((view, idx) => { + if(idx === this.viewIndex) { + return getTheme().tab.selected(` ${view.name} `); } else { - return getTheme().tab.normal(` ${view} `); + return getTheme().tab.normal(` ${view.name} `); } }).join(''); - })()}{/center}\n\n${(() => { - this.view.render(); - })()}` - } - - multiplayerSelected = 0; - - renderMultiplayer() { - if(mdns.players.length === 0) return `{center}${getTheme().normal('No friends online')}{/center}`; - return mdns.players.map((player, i) => { - if(i === this.multiplayerSelected) return ' ' + getTheme().selected(' ❯ ' + player.toString()); - else return ' ' + getTheme().normal(player.toString()); - }).join('\n'); - } - - renderInv() { - return Game.current.inv.render(); - } - - renderTreesSubMenu() { - return [ - `{center}Chop Trees`, - `{left} ${getTheme().hotkey('-=_+')}: ${this.trees}`, - `{left} ${getTheme().hotkey('enter')}: Create Task`, - `{left} ${getTheme().hotkey('escape')}: Cancel` - ].join('\n'); + })()}{/center}\n\n${ + this.view.render() + }`; } render() { diff --git a/src/ui/Popup.ts b/src/ui/Popup.ts index ba2867b..8cdbfa5 100644 --- a/src/ui/Popup.ts +++ b/src/ui/Popup.ts @@ -21,8 +21,22 @@ export class Popup { tags: true, ...boxStyle(), }); - let stuff = ''; - for(let i = 16; i < 232; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%18===0?'\n':''}`) + let stuff = ' '; + for(let i = 16; i < 34; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; + for(let i = 52; i < 70; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; + for(let i = 88; i < 106; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; + for(let i = 124; i < 142; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; + for(let i = 160; i < 178; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; + for(let i = 196; i < 214; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; + stuff += '\n '; + for(let i = 34; i < 52; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; + for(let i = 70; i < 88; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; + for(let i = 106; i < 124; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; + for(let i = 142; i < 160; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; + for(let i = 178; i < 196; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; + for(let i = 214; i < 232; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; + stuff += '\n'; + for(let i = 232; i < 256; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%18===0?'\n':''}`) this.box.setContent(stuff) this.box.on('keypress', (evt, key) => { if(key.full === 'escape' || key.full === 'enter') { diff --git a/src/ui/view/InventoryView.ts b/src/ui/view/InventoryView.ts index 77d2fe4..d58f6b4 100644 --- a/src/ui/view/InventoryView.ts +++ b/src/ui/view/InventoryView.ts @@ -1,3 +1,4 @@ +import { Game } from "../../Game.js"; import { View } from "../View.js"; export default class InventoryView extends View { @@ -5,6 +6,9 @@ export default class InventoryView extends View { super(); this.name = 'Inventory'; } - keypress: (key: { full: string; }) => void; - render() { void 0 }; + keypress(key: { full: string; }) {} + + render() { + return Game.current.inv.render(); + }; } \ No newline at end of file diff --git a/src/ui/view/MultiplayerView.ts b/src/ui/view/MultiplayerView.ts index 30b1929..7d770a5 100644 --- a/src/ui/view/MultiplayerView.ts +++ b/src/ui/view/MultiplayerView.ts @@ -1,10 +1,32 @@ -import { View } from "../View.js"; +import { GiftPopup } from "../GiftPopup.js"; +import { View } from "../View.js" +import mdns from '../../multiplayer/mDNS.js'; +import { getTheme } from "@theme"; export default class MultiplayerView extends View { + + selected: number = 0; + constructor() { super(); this.name = 'Multiplayer'; } - keypress: (key: { full: string; }) => void; - render() { void 0 }; + + keypress(key: { full: string; }) { + if (key.full === 'enter') { + new GiftPopup(mdns.players[this.selected]); + } else if (key.full === 'up') { + this.selected --; + } else if (key.full === 'down') { + this.selected ++; + } + } + + render() { + if(mdns.players.length === 0) return `{center}${getTheme().normal('No friends online')}{/center}`; + return mdns.players.map((player, i) => { + if(i === this.selected) return ' ' + getTheme().selected(' ❯ ' + player.toString()); + else return ' ' + getTheme().normal(player.toString()); + }).join('\n'); + }; } \ No newline at end of file diff --git a/src/ui/view/PawnsView.ts b/src/ui/view/PawnsView.ts index b46f8c8..118010b 100644 --- a/src/ui/view/PawnsView.ts +++ b/src/ui/view/PawnsView.ts @@ -1,3 +1,8 @@ +import { getTheme } from "@theme"; +import { Game } from "../../Game.js"; +import { progressbar } from "../../Progressbar.js"; +import { PawnDetails } from "../PawnDetails.js"; +import { menuPanel } from "../UI.js"; import { View } from "../View.js"; export default class PawnsView extends View { @@ -5,6 +10,32 @@ export default class PawnsView extends View { super(); this.name = 'Pawns'; } - keypress: (key: { full: string; }) => void; - render() { void 0 }; + + keypress(key: { full: string; }) { + if (key.full === 'delete') { + Game.current.removePawn(Game.current.selected); + } else if (key.full === 'up') { + Game.current.advanceSelection(-1); + } else if (key.full === 'down') { + Game.current.advanceSelection(1); + } else if (key.full === 'enter') { + new PawnDetails(Game.current.selected); + } + } + + render() { + return `${ + Game.current.pawns.map(pawn => `${(function() { + const selected = pawn === Game.current.selected; + let str = ''; + if(selected) { + str += ` ${getTheme().selected(` ❯ ${pawn.toString()}`)}{|}${pawn.status} \n`; + str += ` ${getTheme().normal('Energy')}{|}${progressbar(pawn.energy / 100, (menuPanel.width - 4) / 2)} \n`; + } else { + str += ` ${getTheme().normal(pawn.toString())}{|}${pawn.status} `; + } + return str; + })()}`).join('\n') + }`; + } } \ No newline at end of file From ca16c7d783f1dac685ce2b70f9fcc353f36a926b Mon Sep 17 00:00:00 2001 From: Bronwen Date: Tue, 22 Jun 2021 19:25:41 -0400 Subject: [PATCH 05/10] almost done! --- .mocharc.json | 5 + .vscode/tasks.json | 5 +- content/core/actions/FetchSticksAction.ts | 9 + content/core/actions/GatherRocksAction.ts | 9 + content/core/items/Items.ts | 18 + content/core/tasks/ChopTreeTask.ts | 25 + content/core/tasks/FetchSticksTask.ts | 21 + content/core/tasks/GatherRocksTask.ts | 22 + content/core/themes/standard.ts | 2 +- lib/aliases.mjs | 6 +- package.json | 11 +- src/Game.ts | 117 +++-- src/Inventory.ts | 76 ++- src/Item.ts | 47 -- src/Pawn.ts | 11 +- src/Progressbar.ts | 4 +- src/Reflection.ts | 1 + test.js => src/Task.ts | 0 src/TaskList.ts | 28 +- src/Time.test.ts | 31 ++ src/Time.ts | 27 +- src/index.ts | 34 +- src/log.ts | 15 - src/multiplayer/Player.ts | 2 +- src/multiplayer/mDNS.ts | 4 +- src/registries/Actions.ts | 20 + src/registries/Items.ts | 57 +++ src/registries/Tasks.ts | 75 +++ src/{ui/Theme.ts => registries/Themes.ts} | 3 +- src/tasks/ChopTreeTask.ts | 31 -- src/tasks/Task.ts | 66 --- src/ui/GiftPopup.ts | 12 +- src/ui/Menu.ts | 162 +++--- src/ui/PawnDetails.ts | 8 +- src/ui/Popup.ts | 44 +- src/ui/UI.ts | 149 +++--- src/ui/view/ActionsView.ts | 33 ++ src/ui/view/MultiplayerView.ts | 2 +- src/ui/view/PawnsView.ts | 6 +- tsconfig.json | 8 +- yarn.lock | 568 +++++++++++++++++++++- 41 files changed, 1288 insertions(+), 486 deletions(-) create mode 100644 .mocharc.json create mode 100644 content/core/actions/FetchSticksAction.ts create mode 100644 content/core/actions/GatherRocksAction.ts create mode 100644 content/core/items/Items.ts create mode 100644 content/core/tasks/ChopTreeTask.ts create mode 100644 content/core/tasks/FetchSticksTask.ts create mode 100644 content/core/tasks/GatherRocksTask.ts delete mode 100644 src/Item.ts create mode 100644 src/Reflection.ts rename test.js => src/Task.ts (100%) create mode 100644 src/Time.test.ts delete mode 100644 src/log.ts create mode 100644 src/registries/Actions.ts create mode 100644 src/registries/Items.ts create mode 100644 src/registries/Tasks.ts rename src/{ui/Theme.ts => registries/Themes.ts} (97%) delete mode 100644 src/tasks/ChopTreeTask.ts delete mode 100644 src/tasks/Task.ts create mode 100644 src/ui/view/ActionsView.ts diff --git a/.mocharc.json b/.mocharc.json new file mode 100644 index 0000000..88808c5 --- /dev/null +++ b/.mocharc.json @@ -0,0 +1,5 @@ +{ + "extension": ["test.js"], + "spec": "out/**/*.test.js", + "watch-files": ["out/**/*.test.js"] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index aecda74..0c07599 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -2,7 +2,7 @@ "version": "2.0.0", "tasks": [ { - "label": "tsc watch", + "label": "build", "type": "npm", "script": "compile:watch", "isBackground": true, @@ -10,6 +10,9 @@ "kind": "build", "isDefault": true }, + "runOptions": { + "runOn": "folderOpen" + }, "presentation": { "reveal": "never", "echo": false, diff --git a/content/core/actions/FetchSticksAction.ts b/content/core/actions/FetchSticksAction.ts new file mode 100644 index 0000000..e7801e9 --- /dev/null +++ b/content/core/actions/FetchSticksAction.ts @@ -0,0 +1,9 @@ +import { registerAction } from '@actions'; +import { Game } from '@game'; + +registerAction('Fetch Sticks', (qty) => { + Game.current.board.addTask({ + taskId: "core:fetch-sticks", + options: {} + }) +}); \ No newline at end of file diff --git a/content/core/actions/GatherRocksAction.ts b/content/core/actions/GatherRocksAction.ts new file mode 100644 index 0000000..c0f0ba5 --- /dev/null +++ b/content/core/actions/GatherRocksAction.ts @@ -0,0 +1,9 @@ +import { registerAction } from '@actions'; +import { Game } from '@game'; + +registerAction('Gather Rocks', (qty) => { + Game.current.board.addTask({ + taskId: 'core:gather-rocks', + options: {} + }) +}); diff --git a/content/core/items/Items.ts b/content/core/items/Items.ts new file mode 100644 index 0000000..6bb224f --- /dev/null +++ b/content/core/items/Items.ts @@ -0,0 +1,18 @@ +import { Item } from '@items'; + +export const LOG = new Item() + .setName("Log") + .setId('core:resources/log'); + +export const ROCK = new Item() + .setName("Rock") + .setId('core:resources/rock'); + +export const STICK = new Item() + .setName("Stick") + .setId('core:resources/stick'); + + +// slate, flint X normal, flake +// limestone: large, small +// shale \ No newline at end of file diff --git a/content/core/tasks/ChopTreeTask.ts b/content/core/tasks/ChopTreeTask.ts new file mode 100644 index 0000000..8e97a5c --- /dev/null +++ b/content/core/tasks/ChopTreeTask.ts @@ -0,0 +1,25 @@ +import chalk from 'chalk'; +import { Game } from '@game'; +import { registerTask, Task } from '@tasks'; +import { LOG } from '../items/Items.js'; + +// TODO cleanup imports, use aliases + +class ChopTreeTask extends Task { + work = 100; + + reward() { + Game.current.inv.add(LOG, 1); + } + + get title() { + return chalk.yellow('Chop Trees'); + } + + get status() { + return chalk.yellow('LOGGING'); + } +} + + +registerTask('core:chop-trees', ChopTreeTask); \ No newline at end of file diff --git a/content/core/tasks/FetchSticksTask.ts b/content/core/tasks/FetchSticksTask.ts new file mode 100644 index 0000000..5440356 --- /dev/null +++ b/content/core/tasks/FetchSticksTask.ts @@ -0,0 +1,21 @@ +import { Task, registerTask } from "@tasks"; +import chalk from 'chalk'; +import { Game } from '@game'; +import { LOG, STICK } from '../items/Items.js'; + +class FetchSticksTask extends Task { + work = 100; + reward(): void { + Game.current.inv.add(STICK, 1); + } + + get title() { + return chalk.yellow('Chop Trees'); + } + + get status() { + return chalk.yellow('LOGGING'); + } +} + +registerTask('core:fetch-sticks', FetchSticksTask); \ No newline at end of file diff --git a/content/core/tasks/GatherRocksTask.ts b/content/core/tasks/GatherRocksTask.ts new file mode 100644 index 0000000..02d3160 --- /dev/null +++ b/content/core/tasks/GatherRocksTask.ts @@ -0,0 +1,22 @@ +import { Task, registerTask } from "@tasks"; +import chalk from 'chalk'; +import { Game } from '@game'; +import { ROCK } from '../items/Items.js'; + +class GatherRocksTask extends Task { + work = 100; + + reward(): void { + Game.current.inv.add(ROCK, 1); + } + + get title() { + return chalk.yellow('Chop Trees'); + } + + get status() { + return chalk.yellow('LOGGING'); + } +} + +registerTask('core:gather-rocks', GatherRocksTask); \ No newline at end of file diff --git a/content/core/themes/standard.ts b/content/core/themes/standard.ts index 16fd29b..16524ad 100644 --- a/content/core/themes/standard.ts +++ b/content/core/themes/standard.ts @@ -1,4 +1,4 @@ -import { registerTheme } from '@theme'; +import { registerTheme } from '@themes'; import chalk from 'chalk' registerTheme("default", {}); diff --git a/lib/aliases.mjs b/lib/aliases.mjs index baca07c..1c7f461 100644 --- a/lib/aliases.mjs +++ b/lib/aliases.mjs @@ -1,7 +1,11 @@ import path from 'path'; const moduleAliases = { - "@theme": "./out/src/ui/Theme.js" + "@themes": "./out/src/registries/Themes.js", + "@actions": "./out/src/registries/Actions.js", + "@tasks": "./out/src/registries/Tasks.js", + "@items": "./out/src/registries/Items.js", + "@game": "./out/src/Game.js" }; const getAliases = () => { diff --git a/package.json b/package.json index 5409b79..71dd1a9 100644 --- a/package.json +++ b/package.json @@ -7,16 +7,19 @@ "dependencies": { "@types/blessed": "^0.1.17", "@types/bonjour": "^3.5.8", + "@types/chai": "^4.2.19", "@types/faker": "^5.5.6", + "@types/mocha": "^8.2.2", "@types/uuid": "^8.3.0", "bonjour": "^3.5.0", + "chai": "^4.3.4", "chalk": "^4.1.1", "deepmerge": "^4.2.2", "faker": "^5.5.3", "frigid": "^1.3.8", "fs-extra": "^10.0.0", "get-port": "^5.1.1", - "logger": "^0.0.1", + "mocha": "^9.0.1", "module-alias": "^2.2.2", "neo-blessed": "^0.2.0", "printable-characters": "^1.0.42", @@ -29,8 +32,10 @@ }, "scripts": { "compile:watch": "tsc --watch", - "start": "node --loader ./lib/aliases.mjs --enable-source-maps out/src/index.js", + "start": "node --no-warnings --loader ./lib/aliases.mjs --enable-source-maps out/src/index.js", "dev": "supervisor -w out -n exit -t -k --exec yarn -- start", - "prod": "git fetch && git pull && yarn && tsc && yarn start" + "prod": "git fetch && git pull && yarn && tsc && yarn start", + "test": "mocha", + "lint": "eslint src/**/*.ts" } } diff --git a/src/Game.ts b/src/Game.ts index 64cf726..25c4472 100644 --- a/src/Game.ts +++ b/src/Game.ts @@ -5,78 +5,77 @@ import { TaskList } from './TaskList.js'; import { Inventory } from './Inventory.js'; import { Menu } from './ui/Menu.js'; import Time, { Tickable } from './Time.js'; -import { render, Renderable, setTitle } from './ui/UI.js'; -import log from './log.js'; -import { ChopTreeTask } from './tasks/ChopTreeTask.js'; -import { Task } from './tasks/Task.js'; +import { render, Renderable, setTitle, start } from './ui/UI.js'; import { ready } from './multiplayer/mDNS.js'; import faker from 'faker'; let game = null; export class Game extends Frigid implements Tickable, Renderable { - pawns: Pawn[] = []; - selected: Pawn; - inventory: Inventory; - board: TaskList; - menu: Menu; - clock: Time; - name: string; + pawns: Pawn[] = []; + selected: Pawn; + inventory: Inventory; + board: TaskList; + menu: Menu; + clock: Time; + name: string; - [DEBUG] = true; + [DEBUG] = true; - static get current(): Game { - if (!game) throw new Error('Somehow called a game before it existed?'); - return game; - } + static get current(): Game { + if (!game) throw new Error('Somehow called a game before it existed?'); + return game; + } - async tick() { - for(const pawn of this.pawns) { - pawn.tick(); - } - render(); - } + async tick() { + for(const pawn of this.pawns) { + pawn.tick(); + } + render(); + } - get inv() { return this.inventory; } + get inv() { return this.inventory; } - removePawn(pawn: Pawn) { - if(pawn === this.selected) { - if(this.pawns.indexOf(this.selected) === this.pawns.length - 1) this.advanceSelection(-1); - else this.advanceSelection(1); - } + removePawn(pawn: Pawn) { + if(pawn === this.selected) { + if(this.pawns.indexOf(this.selected) === this.pawns.length - 1) this.advanceSelection(-1); + else this.advanceSelection(1); + } - this.pawns = this.pawns.filter(testPawn => { - return pawn !== testPawn; - }); - } + this.pawns = this.pawns.filter(testPawn => { + return pawn !== testPawn; + }); + } - advanceSelection(number) { - let index = this.pawns.indexOf(this.selected); - this.selected = this.pawns[Math.min(Math.max(index + number, 0), this.pawns.length - 1)]; - } - - ctor () { - game = this; - this.name ??= faker.address.city(); - setTitle(this.name); - this.pawns ??= []; - this.selected ??= this.pawns[0] || null; - this.menu = new Menu(); - this.board ??= new TaskList(); - this.inventory ??= new Inventory(); - this.clock ??= new Time(); - this.clock.thing = this; - this.clock.start(); - ready(this.name); - render(this); - } + advanceSelection(number) { + let index = this.pawns.indexOf(this.selected); + this.selected = this.pawns[Math.min(Math.max(index + number, 0), this.pawns.length - 1)]; + } + + ctor () { + game = this; + start(); + this.name ??= faker.address.city(); + setTitle(this.name); + this.pawns ??= []; + this.selected ??= this.pawns[0] || null; + this.menu = new Menu(); + this.board ??= new TaskList(); + this.inventory ??= new Inventory(); + this.inventory.validate(); + this.clock ??= new Time(); + this.clock.thing = this; + this.clock.start(); + ready(this.name); + render(this); + } - static serializationDependencies() { - return [Pawn, Inventory, TaskList, Time, ChopTreeTask, Task]; - } + static serializationDependencies() { + return [ Pawn, Inventory, TaskList, Time ]; + } - render() { - this.menu.render(); - this.board.render(); - } + render() { + this.menu.render(); + this.board.render(); + } } \ No newline at end of file diff --git a/src/Inventory.ts b/src/Inventory.ts index 0ee90c5..137ff65 100644 --- a/src/Inventory.ts +++ b/src/Inventory.ts @@ -1,37 +1,59 @@ import { Serializable } from 'frigid'; import { Game } from './Game.js'; -import { Item, ItemState } from './Item.js'; +import { Item, ItemState } from './registries/Items.js'; +import { Popup } from './ui/Popup.js'; import { Renderable } from './ui/UI.js'; export class Inventory extends Serializable implements Renderable { - items: ItemState[]; + items: ItemState[]; - ctor() { - this.items ??= []; - } + ctor() { + this.items ??= []; + } - static serializationDependencies() { - return [ItemState]; - } + validate() { + const invalid: ItemState[] = []; + for(const itemState of this.items) { + try { + itemState.item; + } catch { + invalid.push(itemState); + } + } + if(invalid.length === 0) return; + + for(const itemState of invalid) { + this.remove(itemState); + } + Popup.show('Invalid ItemStates removed:\n\n' + invalid.map(itemState => itemState.qty + 'x ' + itemState.itemId).join('\n')); + } - add(item: Item, qty: number = 1) { - const id = item.id; - const existingArr = this.items.filter(itemState => { - return itemState.itemId === id; - }); - let existing: ItemState = null; - if(existingArr.length === 1) { - existing = existingArr[0]; - } - if(existing) { - existing.qty += qty; - } else { - this.items.push(new ItemState(item, qty, {})); - } - Game.current.sync(); - } + static serializationDependencies() { + return [ItemState]; + } - render() { - return this.items.map(item => item.render()).join('\n'); - } + remove(itemState: ItemState) { + this.items = this.items.filter(test => test !== itemState); + } + + add(item: Item, qty: number = 1) { + const id = item.id; + const existingArr = this.items.filter(itemState => { + return itemState.itemId === id; + }); + let existing: ItemState = null; + if(existingArr.length === 1) { + existing = existingArr[0]; + } + if(existing) { + existing.qty += qty; + } else { + this.items.push(new ItemState(item, qty, {})); + } + Game.current.sync(); + } + + render() { + return this.items.map(item => item.render()).join('\n'); + } } diff --git a/src/Item.ts b/src/Item.ts deleted file mode 100644 index 58859d3..0000000 --- a/src/Item.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { Serializable } from 'frigid'; -import { getTheme } from './ui/Theme.js'; -import { Renderable } from './ui/UI.js'; - -export type ItemID = string; - -const items = new Map(); - -// ITEMS SHALL BE SINGULAR -export class Item extends Serializable { - static LOG = new Item().setName("Log").setId('resources:log'); - - name = ''; - id: ItemID = ''; - - setName(name) { - this.name = name; - return this; - } - - setId(id: ItemID) { - this.id = id; - items.set(this.id, this); - return this; - } -} - -export class ItemState extends Serializable implements Renderable { - qty: number; - itemId: ItemID; - data: any; - - get item() { - return items.get(this.itemId); - } - - constructor(item: Item, amount: number, data: any) { - super(); - this.qty = amount; - this.itemId = item.id; - this.data = data; - } - - render() { - return getTheme().normal(` ${this.item.name}{|}${this.qty} `); - } -} \ No newline at end of file diff --git a/src/Pawn.ts b/src/Pawn.ts index 81317ab..338310b 100644 --- a/src/Pawn.ts +++ b/src/Pawn.ts @@ -1,13 +1,11 @@ import { Serializable } from 'frigid'; import faker from 'faker'; -import log from './log.js'; -import { Task } from './tasks/Task.js'; +import { Task } from './registries/Tasks.js'; import Time, { Tickable } from './Time.js'; -import { ChopTreeTask } from './tasks/ChopTreeTask.js'; import { Game } from './Game.js'; import { render } from './ui/UI.js'; import { Memory } from './Memory.js'; -import { getTheme } from './ui/Theme.js'; +import { getTheme } from './registries/Themes.js'; const LABORS = { CUT_TREE: Symbol('CUT_TREE'), @@ -81,7 +79,6 @@ export class Pawn extends Serializable implements Tickable { } ctor() { - log.info('Pawn::ctor') this.name ??= { first: faker.name.firstName(), last: faker.name.lastName() @@ -132,8 +129,8 @@ export class Pawn extends Serializable implements Tickable { } } - static serializationDependencies() { - return [Task, ChopTreeTask] + static serializationDependencies(): (typeof Serializable)[] { + return [Task] } toString() { diff --git a/src/Progressbar.ts b/src/Progressbar.ts index a715cfe..c386b5d 100644 --- a/src/Progressbar.ts +++ b/src/Progressbar.ts @@ -1,5 +1,5 @@ import chalk from "chalk"; -import { getTheme } from "./ui/Theme.js"; +import { getTheme } from "./registries/Themes.js"; export enum ProgressbarStyle { indicator = 'indicator', @@ -9,7 +9,7 @@ export enum ProgressbarStyle { export const barCache: Map = new Map(); export function progressbar(completion: number, width: number, style: ProgressbarStyle = ProgressbarStyle.indicator) { - const cacheKey = `${completion}-${width}-${style}`; + const cacheKey = `${Math.round(completion * width * 8)}-${width}-${style}`; if(barCache.has(cacheKey)) { stats.cacheHits ++; return barCache.get(cacheKey); diff --git a/src/Reflection.ts b/src/Reflection.ts new file mode 100644 index 0000000..2c8772e --- /dev/null +++ b/src/Reflection.ts @@ -0,0 +1 @@ +export type Class = new() => T; \ No newline at end of file diff --git a/test.js b/src/Task.ts similarity index 100% rename from test.js rename to src/Task.ts diff --git a/src/TaskList.ts b/src/TaskList.ts index 1717703..49ef4f0 100644 --- a/src/TaskList.ts +++ b/src/TaskList.ts @@ -1,8 +1,6 @@ import { Serializable } from 'frigid'; -import { ChopTreeTask } from "./tasks/ChopTreeTask.js"; -import { Game } from './Game.js'; -import { Task } from "./tasks/Task.js"; -import { render, Renderable, tasksPanel } from './ui/UI.js'; +import { Task, taskClasses } from './registries/Tasks.js'; +import { render, Renderable, panels } from './ui/UI.js'; export class TaskList extends Serializable implements Renderable { tasks: Task[] = []; @@ -14,10 +12,16 @@ export class TaskList extends Serializable implements Renderable { } static serializationDependencies() { - return [ChopTreeTask, Task]; + return Array.from(taskClasses.values()); } - addTask(task) { + addTask({taskId, options}: TaskOptions) { + if(!taskClasses.has(taskId)) + throw new Error('unknown task: ' + taskId); + + const taskClass = taskClasses.get(taskId); + const task = new taskClass(); + this.tasks = [...this.tasks, task]; } @@ -27,9 +31,19 @@ export class TaskList extends Serializable implements Renderable { render() { // const width = tasksPanel.width; - tasksPanel.setContent(`${this.tasks.map(task => { + panels.left.setContent(`${this.tasks.map(task => { return task.toString(); }).join('\n')}`); // return this.tasks.map(task => task.toString()).join('\n'); } } + +const taskTypes = {}; +export function registerTask(name, clazz) { + taskTypes[name] = clazz; +} + +export type TaskOptions = { + taskId: string, + options: any +} \ No newline at end of file diff --git a/src/Time.test.ts b/src/Time.test.ts new file mode 100644 index 0000000..338f8c9 --- /dev/null +++ b/src/Time.test.ts @@ -0,0 +1,31 @@ +// TODO pull in full test framework and coverage shit from vogue +import { expect } from 'chai'; +import Time from './Time.js'; + +describe('Time', () => { + describe('normalize timestamps correctly', () => { + it('0', () => { + const time = new Time(0); + expect(time.toString()).to.equal("0:00 Jan 1, 0001 CE"); + }) + it('-1', () => { + const time = new Time(-1); + expect(time.toString()).to.equal("23:59 Dec 31, 0001 BCE"); + }) + it('1', () => { + const time = new Time(1); + expect(time.toString()).to.equal("0:01 Jan 1, 0001 CE"); + expect(time) + }) + it('0.25', () => { + const time = new Time(0.25); + expect(time.toString()).to.equal("0:00 Jan 1, 0001 CE"); + expect(time.second).to.equal(15); + }) + it('-0.25', () => { + const time = new Time(-0.25); + expect(time.toString()).to.equal("23:59 Dec 31, 0001 BCE"); + expect(time.second).to.equal(45); + }) + }) +}); \ No newline at end of file diff --git a/src/Time.ts b/src/Time.ts index 25cf313..63b6534 100644 --- a/src/Time.ts +++ b/src/Time.ts @@ -1,11 +1,10 @@ import chalk from "chalk"; import { Serializable } from "frigid"; -import { getTheme } from "./ui/Theme.js"; +import { getTheme } from "./registries/Themes.js"; import { Renderable } from "./ui/UI.js"; type AbbreviatedMonthName = string; - const daysInMonth = [ 31, 28, 31, 30, 31, 30, @@ -63,21 +62,13 @@ export default class Time extends Serializable implements Renderable { return `${sym} ${ getTheme().normal(`${ - this.hour.toString().padStart(2, ' ') - }:${ - this.minute.toString().padStart(2, '0') - } ${ - months[this.month] - } ${ - this.day + 1 - }, ${ - this.normalizedYear + this.toString() }`) }`; } toString() { - return `${this.hour}:${this.minute.toString().padStart(2, '0')} ${months[this.month]} ${this.day + 1}, ${this.normalizedYear}` + return `${this.hour}:${Math.floor(this.minute).toString().padStart(2, '0')} ${months[this.month]} ${this.day + 1}, ${this.normalizedYear}` } ctor() { @@ -89,6 +80,10 @@ export default class Time extends Serializable implements Renderable { this.year ??= 0; } + get second() { + return Math.floor((this.minute % 1) * 60) + } + get stamp() { let minute = this.minute; let hour = this.hour; @@ -123,8 +118,8 @@ export default class Time extends Serializable implements Renderable { setTimeout(this.doTick.bind(this), 0); } - advanceTime(minutes) { - this.minute ++; + advanceTime(seconds) { + this.minute += seconds / 60; this.normalize() } @@ -136,7 +131,10 @@ export default class Time extends Serializable implements Renderable { } } + + normalize() { + // while(t) while(this.minute >= 60) { this.minute -= 60; this.hour ++; @@ -145,7 +143,6 @@ export default class Time extends Serializable implements Renderable { this.minute += 60; this.hour --; } - while(this.hour >= 24) { this.hour -= 24; this.day ++; diff --git a/src/index.ts b/src/index.ts index fe35d88..7fe35bd 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,30 +1,36 @@ -import { Game } from './Game.js'; import { render } from './ui/UI.js'; import { ensureDirSync } from 'fs-extra'; import { lstatSync } from 'fs'; import { parse, resolve } from 'path'; import walkSync from 'walk-sync'; import { fileURLToPath } from 'url'; +import { Game } from '@game'; const saveFile = process.argv[2] || 'data/world01.json'; ensureDirSync(parse(saveFile).dir); + +// TODO extract extension loading into separate file +console.log('df-idle: Loading extensions'); const extensionsPath = resolve(parse(fileURLToPath(import.meta.url)).dir, '../content'); const extensions = walkSync(extensionsPath) - .map(path => resolve(extensionsPath, path)) - .filter(path => lstatSync(path).isFile()) - .filter(path => parse(path).ext === '.js') - .map(path => import(path)); + .map(path => resolve(extensionsPath, path)) + .filter(path => lstatSync(path).isFile()) + .filter(path => parse(path).ext === '.js'); + // .map(path => import(path)); -Promise.all(extensions).then((extensions) => { - - // TODO move render logic into game, so that the ui doesnt exist until the game does... - // maybe, i mean, an argument could be made for not that, because the game - // isnt necessarily the entire thing, its just one instance of a save file. - // But probably the initial menu screens will be their own thing entirely. - const game = Game.create(saveFile); - render(game); +console.log('found', extensions.length, 'extensions'); -}); \ No newline at end of file +for(const path of extensions) { + console.log('=== [', path, '] ==='); + await import(path); + console.log(); +} + +// TODO move render logic into game, so that the ui doesnt exist until the game does... +// maybe, i mean, an argument could be made for not that, because the game +// isnt necessarily the entire thing, its just one instance of a save file. +// But probably the initial menu screens will be their own thing entirely. +const game = Game.create(saveFile); \ No newline at end of file diff --git a/src/log.ts b/src/log.ts deleted file mode 100644 index 9641e7b..0000000 --- a/src/log.ts +++ /dev/null @@ -1,15 +0,0 @@ -import logger from 'logger'; - -const log: { - fatal: (...args) => void, - error: (...args) => void, - warn: (...args) => void, - info: (...args) => void, - debug: (...args) => void, -} = logger.createLogger('debug.log'); - -(log as any).format = function(level, date, message) { - return `${date.getTime()} [${level}]${message}`; -}; - -export default log; \ No newline at end of file diff --git a/src/multiplayer/Player.ts b/src/multiplayer/Player.ts index 641e8e1..c1e99fa 100644 --- a/src/multiplayer/Player.ts +++ b/src/multiplayer/Player.ts @@ -1,4 +1,4 @@ -import { ItemState } from '../Item.js'; +import { ItemState } from '../registries/Items.js'; import WebSocket from 'ws'; import { Pawn } from '../Pawn.js'; import { Game } from '../Game.js'; diff --git a/src/multiplayer/mDNS.ts b/src/multiplayer/mDNS.ts index b3352c2..26e9bad 100644 --- a/src/multiplayer/mDNS.ts +++ b/src/multiplayer/mDNS.ts @@ -1,11 +1,10 @@ import bonjour from 'bonjour'; -import log from '../log.js'; import getPort from 'get-port'; import os from 'os' import * as uuid from 'uuid'; import faker from 'faker'; import chalk from 'chalk'; -import { Item } from '../Item.js'; +import { Item } from '../registries/Items.js'; import WebSocket from 'ws'; import { Popup } from '../ui/Popup.js'; import { inspect } from 'util' @@ -71,7 +70,6 @@ mdns.find({ p.name = service.name; p.host = service.host; p.port = service.port; - log.info('Found player', p); devices.push(p); }).on("down", (service) => { // TODO remove player from MP diff --git a/src/registries/Actions.ts b/src/registries/Actions.ts new file mode 100644 index 0000000..7f69640 --- /dev/null +++ b/src/registries/Actions.ts @@ -0,0 +1,20 @@ +import { getTheme } from "@themes"; +import { Renderable } from "../ui/UI.js"; + +export const actions: Action[] = []; + +export function registerAction(name: string, invoke: (qty: number) => void) { + console.log('Registered action', name); + actions.push(new Action(name, invoke)) +} + +export class Action { + name: string; + qty: number; + invoke: (qty: number) => void; + + constructor(name: string, done: (qty: number) => void) { + this.name = name; + this.invoke = done; + } +} \ No newline at end of file diff --git a/src/registries/Items.ts b/src/registries/Items.ts new file mode 100644 index 0000000..471515d --- /dev/null +++ b/src/registries/Items.ts @@ -0,0 +1,57 @@ +import { Serializable } from 'frigid'; +import { getTheme } from './Themes.js'; +import { Renderable } from '../ui/UI.js'; + +export type ItemID = string; + +const items = new Map(); + +// ITEMS SHALL BE SINGULAR +export class Item extends Serializable { + + name = ''; + id: ItemID = ''; + + setName(name) { + this.name = name; + this.register(false); + return this; + } + + setId(id: ItemID) { + this.id = id; + this.register(false); + return this; + } + + register(force = true) { + if((!this.id || !this.name) && !force) return; + console.log('Added item', (this.name ?? "[No Name]").padStart(20, ' '), `| (${this.id})`) + items.set(this.id, this); + return this; + } +} + +export class ItemState extends Serializable implements Renderable { + qty: number; + itemId: ItemID; + data: any; + + get item() { + if(!items.has(this.itemId)) + throw new Error('unknown item: ' + this.itemId); + return items.get(this.itemId); + } + + constructor(item: Item, amount: number, data: any) { + super(); + this.qty = amount; + this.itemId = item.id; + this.data = data; + } + + render() { + return getTheme().normal(` ${this.item.name}{|}${this.qty} `); + } +} + diff --git a/src/registries/Tasks.ts b/src/registries/Tasks.ts new file mode 100644 index 0000000..cf0abd4 --- /dev/null +++ b/src/registries/Tasks.ts @@ -0,0 +1,75 @@ +import { Serializable } from 'frigid'; +import EventEmitter from 'events'; +import chalk from 'chalk'; +import { Pawn } from '../Pawn.js'; +import { Game } from '../Game.js'; +import { panels } from '../ui/UI.js'; +import { progressbar, ProgressbarStyle } from '../Progressbar.js'; +import { Class } from '../Reflection.js'; + +export const taskClasses: Map> = new Map(); + +export abstract class Task extends Serializable { + progress = 0; + worker: Pawn; + data: any; + + ctor() { + this.worker ??= null; + this.testCompletion(); + } + + abstract reward(): void; + abstract work: number; + + get completed() { + return this.completion >= 1; + } + + stopJob() { + this.worker = null; + } + + doWork(work = 1, pawn: Pawn) { + this.worker = pawn; + this.progress += work; + this.testCompletion(); + } + + testCompletion() { + if (this.progress >= this.work) { + this.reward(); + Game.current.board.removeTask(this); + } + } + + claim(pawn: Pawn) { + this.worker = pawn; + } + + get completion() { + return Math.min(1, this.progress / this.work); + } + + toString() { + // HACK magic number 2 here, is the border + // of the panel + const width = panels.left.width - 2; + const left = ' ' + this.title + ' ' + (this.worker?.toString() || chalk.bold.black('Queued')); + const bar = width - 2; + return `${left}\n ${progressbar(this.completion, bar, ProgressbarStyle.progress)}\n`; + } + + get title() { + return chalk.bgRedBright.black('[Abstract Task]'); + } + + get status() { + return chalk.bgRedBright.black('DOING A TASK'); + } +} + +export function registerTask(id: string, taskClass: Class) { + console.log('Registered task', id); + taskClasses.set(id, taskClass) +} \ No newline at end of file diff --git a/src/ui/Theme.ts b/src/registries/Themes.ts similarity index 97% rename from src/ui/Theme.ts rename to src/registries/Themes.ts index d1d8436..74b1a49 100644 --- a/src/ui/Theme.ts +++ b/src/registries/Themes.ts @@ -7,7 +7,6 @@ import chalk from 'chalk'; chalk.level = 2; import merge from 'deepmerge'; -import log from '../log.js'; type StyleFunction = (text: string) => string; @@ -79,7 +78,7 @@ let currentTheme = backupTheme; const themes: Map = new Map(); export function registerTheme(name: ThemeName, theme: Partial) { - log.info('registering theme', name) + console.log('Registered theme', name); themes.set(name, merge(backupTheme, theme)); } diff --git a/src/tasks/ChopTreeTask.ts b/src/tasks/ChopTreeTask.ts deleted file mode 100644 index 91f8c63..0000000 --- a/src/tasks/ChopTreeTask.ts +++ /dev/null @@ -1,31 +0,0 @@ -import chalk from 'chalk'; -import { Game } from '../Game.js'; -import { Item } from '../Item.js'; -import { Pawn } from '../Pawn.js'; -import { Task } from './Task.js'; - - -export class ChopTreeTask extends Task { - work = 100; - - constructor(count) { - super(); - - } - - reward() { - Game.current.inv.add(Item.LOG, 1); - } - - static serializationDependencies() { - return [Pawn]; - } - - get title() { - return chalk.yellow('Chop Trees'); - } - - get status() { - return chalk.yellow('LOGGING'); - } -} diff --git a/src/tasks/Task.ts b/src/tasks/Task.ts deleted file mode 100644 index 2c8b1c0..0000000 --- a/src/tasks/Task.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { Serializable } from 'frigid'; -import EventEmitter from 'events'; -import chalk from 'chalk'; -import { Pawn } from '../Pawn.js'; -import { render, tasksPanel } from '../ui/UI.js'; -import { Game } from '../Game.js'; -import { progressbar, ProgressbarStyle } from '../Progressbar.js'; - -export class Task extends Serializable { - work = 0; - progress = 0; - worker: Pawn; - - ctor() { - this.worker ??= null; - this.testCompletion(); - } - - reward() {} - - get completed() { - return this.completion >= 1; - } - - stopJob() { - this.worker = null; - } - - doWork(work = 1, pawn: Pawn) { - this.worker = pawn; - this.progress += work; - this.testCompletion(); - } - - testCompletion() { - if (this.progress >= this.work) { - this.reward(); - Game.current.board.removeTask(this); - } - } - - claim(pawn: Pawn) { - this.worker = pawn; - } - - get completion() { - return Math.min(1, this.progress / this.work); - } - - toString() { - // HACK magic number 2 here, is the border - // of the panel - const width = tasksPanel.width - 2; - const left = ' ' + this.title + ' ' + (this.worker?.toString() || chalk.bold.black('Queued')); - const bar = width - 2; - return `${left}\n ${progressbar(this.completion, bar, ProgressbarStyle.progress)}\n`; - } - - get title() { - return chalk.bgRedBright.black('[Abstract Task]'); - } - - get status() { - return chalk.bgRedBright.black('DOING A TASK'); - } -} \ No newline at end of file diff --git a/src/ui/GiftPopup.ts b/src/ui/GiftPopup.ts index 4baeaf0..c5379e6 100644 --- a/src/ui/GiftPopup.ts +++ b/src/ui/GiftPopup.ts @@ -1,11 +1,11 @@ import chalk from 'chalk'; import blessed from 'neo-blessed'; import { Game } from '../Game.js'; -import { ItemState } from '../Item.js'; +import { ItemState } from '../registries/Items.js'; import { Player } from "../multiplayer/Player"; import { Pawn } from '../Pawn.js'; -import { getTheme } from './Theme.js'; -import { boxStyle, screen } from './UI.js'; +import { getTheme } from '../registries/Themes.js'; +import { boxStyle, panels } from './UI.js'; export class GiftPopup { box; @@ -30,7 +30,7 @@ export class GiftPopup { this.send(); } if(key.full === 'escape' || key.full === 'enter') { Game.current.clock.start(); - screen.remove(this.box); + panels.screen.remove(this.box); } else if (key.full === 'up') { this.selected --; } else if (key.full === 'down') { @@ -44,7 +44,7 @@ export class GiftPopup { }); this.render(); for(const pawn of Game.current.pawns) this.pawns.set(pawn, 0); - screen.append(this.box); + panels.screen.append(this.box); this.box.focus(); Game.current.clock.pause(); } @@ -80,6 +80,6 @@ export class GiftPopup { } return pawns.join('\n') })()}\n\n{|}${getTheme().hotkey('escape')}${getTheme().normal(': Cancel ')}\n{|}${getTheme().hotkey('enter')}${getTheme().normal(': Okay ')}`); - screen.render(); + panels.screen.render(); } } \ No newline at end of file diff --git a/src/ui/Menu.ts b/src/ui/Menu.ts index 5312b86..46667a4 100644 --- a/src/ui/Menu.ts +++ b/src/ui/Menu.ts @@ -1,111 +1,111 @@ import { Pawn } from '../Pawn.js'; -import log from '../log.js'; -import { menuPanel, Renderable } from './UI.js'; +import { panels, Renderable } from './UI.js'; import { Game } from '../Game.js'; import { progressbar, stats } from '../Progressbar.js'; import { Popup } from './Popup.js'; import mdns from '../multiplayer/mDNS.js'; -import { getTheme } from './Theme.js'; +import { getTheme } from '@themes'; import { inspect } from 'util'; import PawnsView from './view/PawnsView.js'; import InventoryView from './view/InventoryView.js'; import MultiplayerView from './view/MultiplayerView.js'; import { View } from './View.js'; +import { ActionsView } from './view/ActionsView.js'; const clamp = (min, max, value) => Math.min(Math.max(value, min), max); // TODO move KeypressAcceptor to ui something idk export interface KeypressAcceptor { - keypress(key: {full: string}): void + keypress(key: {full: string}): void } export class Menu implements Renderable { - trees: number = 10; - viewIndex: number = 0; - views: View[] = [ - new PawnsView(), - new InventoryView(), - new MultiplayerView() - ] + trees: number = 10; + viewIndex: number = 0; + views: View[] = [ + new PawnsView(), + new InventoryView(), + new MultiplayerView(), + new ActionsView() + ] - get view() { - return this.views[this.viewIndex]; - } + get view() { + return this.views[this.viewIndex]; + } - advanceView() { - this.viewIndex ++; - this.viewIndex = clamp(0, this.views.length - 1, this.viewIndex); - } + advanceView() { + this.viewIndex ++; + this.viewIndex = clamp(0, this.views.length - 1, this.viewIndex); + } - regressView() { - this.viewIndex --; - this.viewIndex = clamp(0, this.views.length - 1, this.viewIndex); - } + regressView() { + this.viewIndex --; + this.viewIndex = clamp(0, this.views.length - 1, this.viewIndex); + } - constructor() { - menuPanel.on('keypress', (evt, key) => { - log.info('keypress', key); - - if (key.full === 'left') { - this.regressView(); - } else if (key.full === 'right') { - this.advanceView(); - - // debugging hotkeys - } else if (key.full === '1') { - Popup.show(inspect(stats)); - } else if (key.full === 'z') { - Game.current.pawns.push(new Pawn()); - } else if (key.full === 'x') { - Game.current.board.clear(); - } else this.view.keypress(key); + constructor() { + panels.right.on('keypress', (evt, key) => { + + if (key.full === 'left') { + this.regressView(); + } else if (key.full === 'right') { + this.advanceView(); + + // debugging hotkeys + } else if (key.full === '1') { + Popup.show(inspect(stats)); + } else if (key.full === 'z') { + Game.current.pawns.push(new Pawn()); + } else if (key.full === 'x') { + Game.current.board.clear(); + } else this.view.keypress(key); - // if(this.view === View.MULTIPLAYER) { - // if (key.full === 'enter') { - // new GiftPopup(mdns.players[this.multiplayerSelected]); - // // mdns.players[this.multiplayerSelected].sendItem(null); - // } else if (key.full === 'up') { - // this.multiplayerSelected --; - // } else if (key.full === 'down') { - // this.multiplayerSelected ++; - // } - // } + // if(this.view === View.MULTIPLAYER) { + // if (key.full === 'enter') { + // new GiftPopup(mdns.players[this.multiplayerSelected]); + // // mdns.players[this.multiplayerSelected].sendItem(null); + // } else if (key.full === 'up') { + // this.multiplayerSelected --; + // } else if (key.full === 'down') { + // this.multiplayerSelected ++; + // } + // } - // TODO add colortest debug screen! + // TODO add colortest debug screen! - Game.current.sync(); - }); - } + Game.current.sync(); + }); + } - renderTopBar() { - const idlers = Game.current.pawns.filter(pawn => pawn.idle); - return ` ${Game.current.clock.render()}{|}${getTheme().normal(`Idle: ${idlers.length}`)} `; - } + renderTopBar() { + const idlers = Game.current.pawns.filter(pawn => pawn.idle); + return ` ${Game.current.clock.render()}{|}${getTheme().normal(`Idle: ${idlers.length}`)} `; + } - renderView() { - const colSpace = ((menuPanel.width - 2) / 2); - return `{center}${(() => { - return Object.values(this.views).map((view, idx) => { - if(idx === this.viewIndex) { - return getTheme().tab.selected(` ${view.name} `); - } else { - return getTheme().tab.normal(` ${view.name} `); - } - }).join(''); - })()}{/center}\n\n${ - this.view.render() - }`; - } + renderView() { + const colSpace = ((panels.right.width - 2) / 2); + return `{center}${(() => { + return Object.values(this.views).map((view, idx) => { + if(idx === this.viewIndex) { + return getTheme().tab.selected(` ${view.name} `); + } else { + return getTheme().tab.normal(` ${view.name} `); + } + }).join(''); + })()}{/center}\n\n${ + this.view.render() + }`; + } - render() { - const width = menuPanel.width - 2; - const hr = getTheme().normal('━'.repeat(width)); - const content = [ - this.renderTopBar(), - hr, - this.renderView(), - ].join('\n'); - menuPanel.setContent(content); - } + render() { + const width = panels.right.width - 2; + const hr = getTheme().normal('━'.repeat(width)); + const content = [ + this.renderTopBar(), + hr, + this.renderView(), + ].join('\n'); + panels.right.setContent(content); + } } \ No newline at end of file diff --git a/src/ui/PawnDetails.ts b/src/ui/PawnDetails.ts index 9f21e6a..69a63f3 100644 --- a/src/ui/PawnDetails.ts +++ b/src/ui/PawnDetails.ts @@ -4,7 +4,7 @@ import { Game } from '../Game.js'; import { stringify } from '../Memory.js'; import { Pawn } from '../Pawn.js'; import Time from '../Time.js'; -import { boxStyle, screen } from './UI.js'; +import { boxStyle, panels } from './UI.js'; export class PawnDetails { box; @@ -23,7 +23,7 @@ export class PawnDetails { this.box.on('keypress', (evt, key) => { if(key.full === 'escape' || key.full === 'enter') { Game.current.clock.start(); - screen.remove(this.box); + panels.screen.remove(this.box); } else if (key.full === 'up') { // this.selected --; } else if (key.full === 'down') { @@ -36,7 +36,7 @@ export class PawnDetails { this.render(); }); this.render(); - screen.append(this.box); + panels.screen.append(this.box); this.box.focus(); Game.current.clock.pause(); } @@ -55,6 +55,6 @@ export class PawnDetails { }: Cancel \n{|}${ chalk.green('enter') }: Okay `); - screen.render(); + panels.screen.render(); } } \ No newline at end of file diff --git a/src/ui/Popup.ts b/src/ui/Popup.ts index 8cdbfa5..bd152cb 100644 --- a/src/ui/Popup.ts +++ b/src/ui/Popup.ts @@ -1,8 +1,8 @@ import chalk from 'chalk'; import blessed from 'neo-blessed'; import { Game } from '../Game.js'; -import { getTheme } from './Theme.js'; -import { boxStyle, screen } from './UI.js'; +import { getTheme } from '@themes'; +import { boxStyle, panels } from './UI.js'; export class Popup { box; @@ -17,34 +17,34 @@ export class Popup { left: 'center', width: '100%', height: 'shrink', - // content: getTheme().normal(content) + `\n\n{|}` + getTheme().hotkey('enter') + getTheme().normal(`: Okay `), + content: getTheme().normal(content) + `\n\n{right}` + getTheme().hotkey('enter') + getTheme().normal(`: Okay `) + '{/right}', tags: true, ...boxStyle(), }); - let stuff = ' '; - for(let i = 16; i < 34; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; - for(let i = 52; i < 70; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; - for(let i = 88; i < 106; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; - for(let i = 124; i < 142; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; - for(let i = 160; i < 178; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; - for(let i = 196; i < 214; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; - stuff += '\n '; - for(let i = 34; i < 52; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; - for(let i = 70; i < 88; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; - for(let i = 106; i < 124; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; - for(let i = 142; i < 160; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; - for(let i = 178; i < 196; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; - for(let i = 214; i < 232; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; - stuff += '\n'; - for(let i = 232; i < 256; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%18===0?'\n':''}`) - this.box.setContent(stuff) + // let stuff = ' '; + // for(let i = 16; i < 34; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; + // for(let i = 52; i < 70; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; + // for(let i = 88; i < 106; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; + // for(let i = 124; i < 142; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; + // for(let i = 160; i < 178; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; + // for(let i = 196; i < 214; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; + // stuff += '\n '; + // for(let i = 34; i < 52; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; + // for(let i = 70; i < 88; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; + // for(let i = 106; i < 124; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; + // for(let i = 142; i < 160; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; + // for(let i = 178; i < 196; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; + // for(let i = 214; i < 232; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; + // stuff += '\n'; + // for(let i = 232; i < 256; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%18===0?'\n':''}`) + // this.box.setContent(stuff) this.box.on('keypress', (evt, key) => { if(key.full === 'escape' || key.full === 'enter') { Game.current.clock.start(); - screen.remove(this.box); + panels.screen.remove(this.box); } }); - screen.append(this.box); + panels.screen.append(this.box); this.box.focus(); Game.current.clock.pause(); } diff --git a/src/ui/UI.ts b/src/ui/UI.ts index dc1f67b..cf5d122 100644 --- a/src/ui/UI.ts +++ b/src/ui/UI.ts @@ -1,12 +1,7 @@ import blessed from 'neo-blessed'; import ansi from 'sisteransi'; -import { getTheme } from './Theme.js'; - -export const screen = blessed.screen({ - smartCSR: true, - terminal: 'xterm-256color' -}); +import { getTheme } from '../registries/Themes.js'; export interface Renderable { render(): void @@ -31,64 +26,108 @@ export const boxStyle = () => { }; }; -let currentRenderable = null; +let leftPanel: any; +let rightPanel: any; +let titleBar: any; +let screen: any; +let currentRenderable: Renderable = null; +let started = false; + +function assertStarted() { + if(!started) throw new Error('Attempted accessing UI before starting it!'); +} + +function assertNotStarted() { + if(started) throw new Error('Attempted starting UI when already started!'); +} + +export function isStarted() { + return started; +} + +export const panels = { + get left() { + assertStarted() + return leftPanel; + }, + get right() { + assertStarted() + return rightPanel; + }, + get screen() { + assertStarted() + return screen; + } +} + +export function setTitle(title: string) { + assertStarted(); + titleBar.setContent(` ${getTheme().header(title)}{|}${getTheme().subheader('v0.1.0')} {/}`); +} + export function render(thing?: Renderable) { - if(!!thing) currentRenderable = thing; - currentRenderable.render(); - screen.render(); + assertStarted(); + if(!!thing) currentRenderable = thing; + + currentRenderable.render(); + screen.render(); } -export const tasksPanel = blessed.box({ - top: 1, - left: 0, - width: '50%+1', - height: '100%-1', - ...boxStyle(), - tags: true -}); +export function start() { + assertNotStarted(); + screen = blessed.screen({ + smartCSR: true, + terminal: 'xterm-256color' + }); -export const menuPanel = blessed.box({ - top: 1, - left: '50%+1', - width: '50%', - height: '100%-1', - ...boxStyle(), - tags: true -}); + leftPanel = blessed.box({ + top: 1, + left: 0, + width: '50%', + height: '100%-1', + ...boxStyle(), + tags: true + }); -const titleBar = blessed.box({ - top: 0, - left: 0, - width: '100%', - height: 1, - tags: true, -}); + rightPanel = blessed.box({ + top: 1, + right: 0, + width: '50%', + height: '100%-1', + ...boxStyle(), + tags: true + }); -export function setTitle(title) { - titleBar.setContent(` ${getTheme().header(title)}{|}${getTheme().subheader('v0.1.0')} {/}`); -} + titleBar = blessed.box({ + top: 0, + left: 0, + width: '100%', + height: 1, + tags: true, + }); -setTitle(''); + screen.append(leftPanel); + screen.append(rightPanel); + screen.append(titleBar); + rightPanel.focus(); -menuPanel.focus(); + process.stdout.write(ansi.cursor.hide); -screen.append(tasksPanel); -screen.append(menuPanel); -screen.append(titleBar); + screen.key(['C-c'], function(ch, key) { + process.stdout.write(ansi.cursor.show); + setTimeout(_ => { + process.exit(0); + }) + }); -process.stdout.write(ansi.cursor.hide); + screen.key('f2', () => { + rightPanel.focus(); + }); -screen.key(['C-c'], function(ch, key) { - process.stdout.write(ansi.cursor.show); - setTimeout(_ => { - process.exit(0); - }) -}); + screen.key('f1', () => { + leftPanel.focus(); + }); -tasksPanel.key('f2', () => { - menuPanel.focus(); -}); - -menuPanel.key('f1', () => { - tasksPanel.focus(); -}); \ No newline at end of file + started = true; + setTitle(''); +} \ No newline at end of file diff --git a/src/ui/view/ActionsView.ts b/src/ui/view/ActionsView.ts new file mode 100644 index 0000000..896657b --- /dev/null +++ b/src/ui/view/ActionsView.ts @@ -0,0 +1,33 @@ +import { getTheme } from "../../registries/Themes.js"; +import { Game } from "../../Game.js"; +import { Renderable } from "../UI.js"; +import { View } from "../View.js"; +import { actions } from "@actions"; + +export class ActionsView extends View { + actionIdx: number = 0; + + constructor() { + super(); + this.name = 'Actions'; + } + + keypress(key) { + if(key.full === 'up') { + this.actionIdx --; + } else if (key.full === 'down') { + this.actionIdx ++; + } else if (key.full === 'enter') { + actions[this.actionIdx].invoke(1); + } + } + render() { + return actions.map((action, idx) => `${(() => { + if(this.actionIdx === idx) { + return getTheme().selected(' ❯ ' + action.name); + } else { + return getTheme().normal(' ' + action.name); + } + })()}`).join('\n'); + } +} \ No newline at end of file diff --git a/src/ui/view/MultiplayerView.ts b/src/ui/view/MultiplayerView.ts index 7d770a5..2bce850 100644 --- a/src/ui/view/MultiplayerView.ts +++ b/src/ui/view/MultiplayerView.ts @@ -1,7 +1,7 @@ import { GiftPopup } from "../GiftPopup.js"; import { View } from "../View.js" import mdns from '../../multiplayer/mDNS.js'; -import { getTheme } from "@theme"; +import { getTheme } from "@themes"; export default class MultiplayerView extends View { diff --git a/src/ui/view/PawnsView.ts b/src/ui/view/PawnsView.ts index 118010b..c9b7c9b 100644 --- a/src/ui/view/PawnsView.ts +++ b/src/ui/view/PawnsView.ts @@ -1,8 +1,8 @@ -import { getTheme } from "@theme"; +import { getTheme } from "@themes"; import { Game } from "../../Game.js"; import { progressbar } from "../../Progressbar.js"; import { PawnDetails } from "../PawnDetails.js"; -import { menuPanel } from "../UI.js"; +import { panels } from "../UI.js"; import { View } from "../View.js"; export default class PawnsView extends View { @@ -30,7 +30,7 @@ export default class PawnsView extends View { let str = ''; if(selected) { str += ` ${getTheme().selected(` ❯ ${pawn.toString()}`)}{|}${pawn.status} \n`; - str += ` ${getTheme().normal('Energy')}{|}${progressbar(pawn.energy / 100, (menuPanel.width - 4) / 2)} \n`; + str += ` ${getTheme().normal('Energy')}{|}${progressbar(pawn.energy / 100, (panels.right.width - 4) / 2)} \n`; } else { str += ` ${getTheme().normal(pawn.toString())}{|}${pawn.status} `; } diff --git a/tsconfig.json b/tsconfig.json index 49ad934..4977fa7 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,14 +1,18 @@ { "compilerOptions": { "target": "ES2020", - "module": "ES2020", + "module": "ESNext", "moduleResolution": "Node", "allowSyntheticDefaultImports": true, "outDir": "out", "declaration": true, "sourceMap": true, "paths": { - "@theme": ["./src/ui/Theme"] + "@themes": ["./src/registries/Themes"], + "@actions": ["./src/registries/Actions"], + "@tasks": ["./src/registries/Tasks"], + "@items": ["./src/registries/Items"], + "@game": ["./src/Game"] } }, "include": [ diff --git a/yarn.lock b/yarn.lock index 92e3e54..4a1b4c5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14,6 +14,11 @@ dependencies: "@types/node" "*" +"@types/chai@^4.2.19": + version "4.2.19" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.19.tgz#80f286b515897413c7a35bdda069cc80f2344233" + integrity sha512-jRJgpRBuY+7izT7/WNXP/LsMO9YonsstuL+xuvycDyESpoDoIAsMd7suwpB4h9oEWB+ZlPTqJJ8EHomzNhwTPQ== + "@types/faker@^5.5.6": version "5.5.6" resolved "https://registry.yarnpkg.com/@types/faker/-/faker-5.5.6.tgz#039b700a9d8ad9150ecc842bf5e717e2027b6f75" @@ -23,6 +28,11 @@ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.4.tgz#f0ec25dbf2f0e4b18647313ac031134ca5b24b21" integrity sha512-1z8k4wzFnNjVK/tlxvrWuK5WMt6mydWWP7+zvH5eFep4oj+UkrfiJTRtjCeBXNpwaA/FYqqtb4/QS4ianFpIRA== +"@types/mocha@^8.2.2": + version "8.2.2" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.2.2.tgz#91daa226eb8c2ff261e6a8cbf8c7304641e095e0" + integrity sha512-Lwh0lzzqT5Pqh6z61P3c3P5nm6fzQK/MMHl9UKeneAeInVflBSz1O2EkX6gM6xfJd7FBXBY5purtLx7fUiZ7Hw== + "@types/node@*": version "15.12.2" resolved "https://registry.npmjs.org/@types/node/-/node-15.12.2.tgz" @@ -31,21 +41,64 @@ version "8.3.0" resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.0.tgz#215c231dff736d5ba92410e6d602050cce7e273f" -ansi-styles@^4.1.0: +"@ungap/promise-all-settled@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" + integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q== + +ansi-colors@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + +ansi-regex@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" + integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" dependencies: color-convert "^2.0.1" +anymatch@~3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" + integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + array-flatten@^2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" +assertion-error@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" + integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + bonjour@^3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/bonjour/-/bonjour-3.5.0.tgz#8e890a183d8ee9a2393b3844c691a42bcf7bc9f5" @@ -65,6 +118,18 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" +braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + buffer-indexof@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c" @@ -76,13 +141,59 @@ call-bind@^1.0.0, call-bind@^1.0.2: function-bind "^1.1.1" get-intrinsic "^1.0.2" -chalk@^4.1.1: +camelcase@^6.0.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" + integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== + +chai@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.4.tgz#b55e655b31e1eac7099be4c08c21964fce2e6c49" + integrity sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA== + dependencies: + assertion-error "^1.1.0" + check-error "^1.0.2" + deep-eql "^3.0.1" + get-func-name "^2.0.0" + pathval "^1.1.1" + type-detect "^4.0.5" + +chalk@^4.1.0, chalk@^4.1.1: version "4.1.1" resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz" dependencies: ansi-styles "^4.1.0" supports-color "^7.1.0" +check-error@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" + integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= + +chokidar@3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a" + integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw== + dependencies: + anymatch "~3.1.1" + braces "~3.0.2" + glob-parent "~5.1.0" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.5.0" + optionalDependencies: + fsevents "~2.3.1" + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + color-convert@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" @@ -98,6 +209,25 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= +debug@4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" + integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== + dependencies: + ms "2.1.2" + +decamelize@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" + integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== + +deep-eql@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" + integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw== + dependencies: + type-detect "^4.0.0" + deep-equal@^1.0.1: version "1.1.1" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" @@ -120,6 +250,11 @@ define-properties@^1.1.3: dependencies: object-keys "^1.0.12" +diff@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" + integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== + dns-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" @@ -137,19 +272,54 @@ dns-txt@^2.0.2: dependencies: buffer-indexof "^1.0.0" +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + ensure-posix-path@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/ensure-posix-path/-/ensure-posix-path-1.1.1.tgz#3c62bdb19fa4681544289edb2b382adc029179ce" integrity sha512-VWU0/zXzVbeJNXvME/5EmLuEj2TauvoaTz6aFYK1Z92JCBlDlZ3Gu0tuGR42kpW1754ywTs+QB0g5TP0oj9Zaw== +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escape-string-regexp@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + faker@^5.5.3: version "5.5.3" resolved "https://registry.npmjs.org/faker/-/faker-5.5.3.tgz" +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +find-up@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + frigid@^1.3.8: - version "1.3.8" - resolved "https://registry.yarnpkg.com/frigid/-/frigid-1.3.8.tgz#a16919821e5426344bc98d301099f7631d2bae8a" - integrity sha512-i3HgB/5hQsALyumWoRlBvEpAXfTmM3Xw+Ica6E9mTASUVYtqZQ8mzUX8/3zscTUM4bCKhSa7MSvXl9L7pt5ICg== + version "1.3.9" + resolved "https://registry.yarnpkg.com/frigid/-/frigid-1.3.9.tgz#f9353b3d0ea5e38f69a2bb7c3fac8a8426f755b1" + integrity sha512-4s+5YWu4s7UblZVd6RQ+4foMs1km+QVdP04DtXNyja/5od9312EgLlgNOXszmbbw+7t/y7XkTBGA8ADtcpOdMQ== fs-extra@^10.0.0: version "10.0.0" @@ -160,10 +330,30 @@ fs-extra@^10.0.0: jsonfile "^6.0.1" universalify "^2.0.0" +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +fsevents@~2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-func-name@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" + integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= + get-intrinsic@^1.0.2: version "1.1.1" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" @@ -176,11 +366,35 @@ get-port@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/get-port/-/get-port-5.1.1.tgz#0469ed07563479de6efb986baf053dcd7d4e3193" +glob-parent@~5.1.0: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob@7.1.7: + version "7.1.7" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" + integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + graceful-fs@^4.1.6, graceful-fs@^4.2.0: version "4.2.6" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee" integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ== +growl@1.10.5: + version "1.10.5" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" + integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== + has-flag@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" @@ -195,6 +409,24 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" +he@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + ip@^1.1.0: version "1.1.5" resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" @@ -205,10 +437,49 @@ is-arguments@^1.0.4: dependencies: call-bind "^1.0.0" +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + is-date-object@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.4.tgz#550cfcc03afada05eea3dd30981c7b09551f73e5" +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + dependencies: + is-extglob "^2.1.1" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + is-regex@^1.0.4: version "1.1.3" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.3.tgz#d029f9aff6448b93ebbe3f33dac71511fdcbef9f" @@ -216,6 +487,23 @@ is-regex@^1.0.4: call-bind "^1.0.2" has-symbols "^1.0.2" +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +js-yaml@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + jsonfile@^6.0.1: version "6.1.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" @@ -225,9 +513,20 @@ jsonfile@^6.0.1: optionalDependencies: graceful-fs "^4.1.6" -logger@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/logger/-/logger-0.0.1.tgz#cb08171f8a6f6f674b8499dadf50bed4befb72c4" +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +log-symbols@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" matcher-collection@^2.0.1: version "2.0.1" @@ -237,18 +536,59 @@ matcher-collection@^2.0.1: "@types/minimatch" "^3.0.3" minimatch "^3.0.2" -minimatch@^3.0.2, minimatch@^3.0.4: +minimatch@3.0.4, minimatch@^3.0.2, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== dependencies: brace-expansion "^1.1.7" +mocha@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-9.0.1.tgz#01e66b7af0012330c0a38c4b6eaa6d92b8a81bf9" + integrity sha512-9zwsavlRO+5csZu6iRtl3GHImAbhERoDsZwdRkdJ/bE+eVplmoxNKE901ZJ9LdSchYBjSCPbjKc5XvcAri2ylw== + dependencies: + "@ungap/promise-all-settled" "1.1.2" + ansi-colors "4.1.1" + browser-stdout "1.3.1" + chokidar "3.5.1" + debug "4.3.1" + diff "5.0.0" + escape-string-regexp "4.0.0" + find-up "5.0.0" + glob "7.1.7" + growl "1.10.5" + he "1.2.0" + js-yaml "4.1.0" + log-symbols "4.1.0" + minimatch "3.0.4" + ms "2.1.3" + nanoid "3.1.23" + serialize-javascript "5.0.1" + strip-json-comments "3.1.1" + supports-color "8.1.1" + which "2.0.2" + wide-align "1.1.3" + workerpool "6.1.4" + yargs "16.2.0" + yargs-parser "20.2.4" + yargs-unparser "2.0.0" + module-alias@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/module-alias/-/module-alias-2.2.2.tgz#151cdcecc24e25739ff0aa6e51e1c5716974c0e0" integrity sha512-A/78XjoX2EmNvppVWEhM2oGk3x4lLxnkEA4jTbaK97QKSDjkIoOsKQlfylt/d3kKKi596Qy3NP5XrXJ6fZIC9Q== +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + multicast-dns-service-types@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901" @@ -260,11 +600,21 @@ multicast-dns@^6.0.1: dns-packet "^1.3.1" thunky "^1.0.2" +nanoid@3.1.23: + version "3.1.23" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.23.tgz#f744086ce7c2bc47ee0a8472574d5c78e4183a81" + integrity sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw== + neo-blessed@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/neo-blessed/-/neo-blessed-0.2.0.tgz#30f9495fdd104494402b62c6273a9c9b82de4f2b" integrity sha512-C2kC4K+G2QnNQFXUIxTQvqmrdSIzGTX1ZRKeDW6ChmvPRw8rTkTEJzbEQHiHy06d36PCl/yMOCjquCRV8SpSQw== +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + object-is@^1.0.1: version "1.1.5" resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" @@ -276,10 +626,65 @@ object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +pathval@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" + integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== + +picomatch@^2.0.4, picomatch@^2.2.1: + version "2.3.0" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" + integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== + printable-characters@^1.0.42: version "1.0.42" resolved "https://registry.yarnpkg.com/printable-characters/-/printable-characters-1.0.42.tgz#3f18e977a9bd8eb37fcc4ff5659d7be90868b3d8" +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +readdirp@~3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e" + integrity sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ== + dependencies: + picomatch "^2.2.1" + regexp.prototype.flags@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz#7ef352ae8d159e758c0eadca6f8fcb4eef07be26" @@ -287,14 +692,69 @@ regexp.prototype.flags@^1.2.0: call-bind "^1.0.2" define-properties "^1.1.3" -safe-buffer@^5.0.1: +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +safe-buffer@^5.0.1, safe-buffer@^5.1.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" +serialize-javascript@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-5.0.1.tgz#7886ec848049a462467a97d3d918ebb2aaf934f4" + integrity sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA== + dependencies: + randombytes "^2.1.0" + sisteransi@^1.0.5: version "1.0.5" resolved "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz" +"string-width@^1.0.2 || 2": + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string-width@^4.1.0, string-width@^4.2.0: + version "4.2.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5" + integrity sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + dependencies: + ansi-regex "^3.0.0" + +strip-ansi@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" + integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== + dependencies: + ansi-regex "^5.0.0" + +strip-json-comments@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +supports-color@8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + supports-color@^7.1.0: version "7.2.0" resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" @@ -305,6 +765,18 @@ thunky@^1.0.2: version "1.1.0" resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +type-detect@^4.0.0, type-detect@^4.0.5: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + typescript@^4.3.2: version "4.3.2" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.3.2.tgz#399ab18aac45802d6f2498de5054fcbbe716a805" @@ -328,11 +800,87 @@ walk-sync@^3.0.0: matcher-collection "^2.0.1" minimatch "^3.0.4" +which@2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wide-align@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + dependencies: + string-width "^1.0.2 || 2" + +workerpool@6.1.4: + version "6.1.4" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.1.4.tgz#6a972b6df82e38d50248ee2820aa98e2d0ad3090" + integrity sha512-jGWPzsUqzkow8HoAvqaPWTUPCrlPJaJ5tY8Iz7n1uCz3tTp6s3CDG0FF1NsX42WNlkRSW6Mr+CDZGnNoSsKa7g== + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + ws@^7.4.6: version "7.4.6" resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yargs-parser@20.2.4: + version "20.2.4" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" + integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== + +yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + +yargs-unparser@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" + integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== + dependencies: + camelcase "^6.0.0" + decamelize "^4.0.0" + flat "^5.0.2" + is-plain-obj "^2.1.0" + +yargs@16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + yarn@^1.22.10: version "1.22.10" resolved "https://registry.yarnpkg.com/yarn/-/yarn-1.22.10.tgz#c99daa06257c80f8fa2c3f1490724e394c26b18c" + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== From cbc2cec5f40235d5892a7df9f4fd19925547c147 Mon Sep 17 00:00:00 2001 From: Valerie Date: Tue, 22 Jun 2021 19:42:00 -0400 Subject: [PATCH 06/10] what... --- src/ui/Popup.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/Popup.ts b/src/ui/Popup.ts index bd152cb..ffe28a1 100644 --- a/src/ui/Popup.ts +++ b/src/ui/Popup.ts @@ -35,7 +35,7 @@ export class Popup { // for(let i = 142; i < 160; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; // for(let i = 178; i < 196; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; // for(let i = 214; i < 232; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; - // stuff += '\n'; + // stuff += '\n'; // for(let i = 232; i < 256; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%18===0?'\n':''}`) // this.box.setContent(stuff) this.box.on('keypress', (evt, key) => { From f8a966956a48ae353c7ca85fd4e86ffc53a617a7 Mon Sep 17 00:00:00 2001 From: Valerie Date: Tue, 22 Jun 2021 22:38:49 -0400 Subject: [PATCH 07/10] minor shit to debug frigid and TS ugh-i-ness --- package.json | 2 +- src/Pawn.ts | 2 +- src/Reflection.ts | 1 - src/TaskList.ts | 9 ++++-- src/registries/Tasks.ts | 5 ++-- src/ui/Popup.ts | 65 +++++++++++++++-------------------------- src/ui/UI.ts | 25 +++++++++++++++- yarn.lock | 8 ++--- 8 files changed, 63 insertions(+), 54 deletions(-) delete mode 100644 src/Reflection.ts diff --git a/package.json b/package.json index 71dd1a9..f8c38a8 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "chalk": "^4.1.1", "deepmerge": "^4.2.2", "faker": "^5.5.3", - "frigid": "^1.3.8", + "frigid": "^1.3.12", "fs-extra": "^10.0.0", "get-port": "^5.1.1", "mocha": "^9.0.1", diff --git a/src/Pawn.ts b/src/Pawn.ts index 338310b..1adbae8 100644 --- a/src/Pawn.ts +++ b/src/Pawn.ts @@ -129,7 +129,7 @@ export class Pawn extends Serializable implements Tickable { } } - static serializationDependencies(): (typeof Serializable)[] { + static serializationDependencies() { return [Task] } diff --git a/src/Reflection.ts b/src/Reflection.ts deleted file mode 100644 index 2c8772e..0000000 --- a/src/Reflection.ts +++ /dev/null @@ -1 +0,0 @@ -export type Class = new() => T; \ No newline at end of file diff --git a/src/TaskList.ts b/src/TaskList.ts index 49ef4f0..1e27348 100644 --- a/src/TaskList.ts +++ b/src/TaskList.ts @@ -12,14 +12,19 @@ export class TaskList extends Serializable implements Renderable { } static serializationDependencies() { - return Array.from(taskClasses.values()); + let a = Array.from(taskClasses.values()) + return a as unknown as (typeof Serializable)[]; } addTask({taskId, options}: TaskOptions) { if(!taskClasses.has(taskId)) throw new Error('unknown task: ' + taskId); - const taskClass = taskClasses.get(taskId); + // this is any because TS doesnt understand that + // static references and constructors are the + // SAME THING. + // in TS, they're MAGICALLY incompatible... + const taskClass: any = taskClasses.get(taskId); const task = new taskClass(); this.tasks = [...this.tasks, task]; diff --git a/src/registries/Tasks.ts b/src/registries/Tasks.ts index cf0abd4..2daf0b4 100644 --- a/src/registries/Tasks.ts +++ b/src/registries/Tasks.ts @@ -5,9 +5,8 @@ import { Pawn } from '../Pawn.js'; import { Game } from '../Game.js'; import { panels } from '../ui/UI.js'; import { progressbar, ProgressbarStyle } from '../Progressbar.js'; -import { Class } from '../Reflection.js'; -export const taskClasses: Map> = new Map(); +export const taskClasses: Map = new Map(); export abstract class Task extends Serializable { progress = 0; @@ -69,7 +68,7 @@ export abstract class Task extends Serializable { } } -export function registerTask(id: string, taskClass: Class) { +export function registerTask(id: string, taskClass: typeof Task) { console.log('Registered task', id); taskClasses.set(id, taskClass) } \ No newline at end of file diff --git a/src/ui/Popup.ts b/src/ui/Popup.ts index ffe28a1..824567a 100644 --- a/src/ui/Popup.ts +++ b/src/ui/Popup.ts @@ -5,47 +5,30 @@ import { getTheme } from '@themes'; import { boxStyle, panels } from './UI.js'; export class Popup { - box; + box; - static show(content) { - new Popup(content) - } + static show(content) { + new Popup(content) + } - private constructor(content) { - this.box = blessed.box({ - top: 'center', - left: 'center', - width: '100%', - height: 'shrink', - content: getTheme().normal(content) + `\n\n{right}` + getTheme().hotkey('enter') + getTheme().normal(`: Okay `) + '{/right}', - tags: true, - ...boxStyle(), - }); - // let stuff = ' '; - // for(let i = 16; i < 34; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; - // for(let i = 52; i < 70; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; - // for(let i = 88; i < 106; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; - // for(let i = 124; i < 142; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; - // for(let i = 160; i < 178; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; - // for(let i = 196; i < 214; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; - // stuff += '\n '; - // for(let i = 34; i < 52; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; - // for(let i = 70; i < 88; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; - // for(let i = 106; i < 124; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; - // for(let i = 142; i < 160; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; - // for(let i = 178; i < 196; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; - // for(let i = 214; i < 232; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; - // stuff += '\n'; - // for(let i = 232; i < 256; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%18===0?'\n':''}`) - // this.box.setContent(stuff) - this.box.on('keypress', (evt, key) => { - if(key.full === 'escape' || key.full === 'enter') { - Game.current.clock.start(); - panels.screen.remove(this.box); - } - }); - panels.screen.append(this.box); - this.box.focus(); - Game.current.clock.pause(); - } + private constructor(content) { + this.box = blessed.box({ + top: 'center', + left: 'center', + width: '100%', + height: 'shrink', + content: getTheme().normal(content) + `\n\n{right}` + getTheme().hotkey('enter') + getTheme().normal(`: Okay `) + '{/right}', + tags: true, + ...boxStyle(), + }); + this.box.on('keypress', (evt, key) => { + if(key.full === 'escape' || key.full === 'enter') { + Game.current.clock.start(); + panels.screen.remove(this.box); + } + }); + panels.screen.append(this.box); + this.box.focus(); + Game.current.clock.pause(); + } } \ No newline at end of file diff --git a/src/ui/UI.ts b/src/ui/UI.ts index cf5d122..03fa1f1 100644 --- a/src/ui/UI.ts +++ b/src/ui/UI.ts @@ -1,4 +1,5 @@ +import chalk from 'chalk'; import blessed from 'neo-blessed'; import ansi from 'sisteransi'; import { getTheme } from '../registries/Themes.js'; @@ -130,4 +131,26 @@ export function start() { started = true; setTitle(''); -} \ No newline at end of file +} + +let ansiTestCard = '{center}'; +for(let i = 16; i < 34; i ++) ansiTestCard += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); ansiTestCard += '\n'; +for(let i = 52; i < 70; i ++) ansiTestCard += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); ansiTestCard += '\n'; +for(let i = 88; i < 106; i ++) ansiTestCard += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); ansiTestCard += '\n'; +for(let i = 124; i < 142; i ++) ansiTestCard += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); ansiTestCard += '\n'; +for(let i = 160; i < 178; i ++) ansiTestCard += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); ansiTestCard += '\n'; +for(let i = 196; i < 214; i ++) ansiTestCard += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); ansiTestCard += '\n'; +ansiTestCard += '\n'; +for(let i = 34; i < 52; i ++) ansiTestCard += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); ansiTestCard += '\n'; +for(let i = 70; i < 88; i ++) ansiTestCard += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); ansiTestCard += '\n'; +for(let i = 106; i < 124; i ++) ansiTestCard += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); ansiTestCard += '\n'; +for(let i = 142; i < 160; i ++) ansiTestCard += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); ansiTestCard += '\n'; +for(let i = 178; i < 196; i ++) ansiTestCard += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); ansiTestCard += '\n'; +for(let i = 214; i < 232; i ++) ansiTestCard += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); ansiTestCard += '\n'; +ansiTestCard += '\n'; +for(let i = 232; i < 256; i ++) ansiTestCard += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} `) +ansiTestCard += '{/center}'; + +export { + ansiTestCard +}; \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 4a1b4c5..93b9a85 100644 --- a/yarn.lock +++ b/yarn.lock @@ -316,10 +316,10 @@ flat@^5.0.2: resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== -frigid@^1.3.8: - version "1.3.9" - resolved "https://registry.yarnpkg.com/frigid/-/frigid-1.3.9.tgz#f9353b3d0ea5e38f69a2bb7c3fac8a8426f755b1" - integrity sha512-4s+5YWu4s7UblZVd6RQ+4foMs1km+QVdP04DtXNyja/5od9312EgLlgNOXszmbbw+7t/y7XkTBGA8ADtcpOdMQ== +frigid@^1.3.12: + version "1.3.13" + resolved "https://registry.yarnpkg.com/frigid/-/frigid-1.3.13.tgz#27d8592ec1aeb72964fbc4014e38e6c366c5e3b7" + integrity sha512-suwEa7JuMvNqIlVpc848wIptC8o3Ztvadv8a1HojbaNcYdowOlqWi/ieSgQZkBVCpmrBOq7IeuaB6p4BvCUdHQ== fs-extra@^10.0.0: version "10.0.0" From d7aca31c8c74d1365552059e047f9c3b19675da6 Mon Sep 17 00:00:00 2001 From: Bronwen Date: Wed, 23 Jun 2021 01:28:06 -0400 Subject: [PATCH 08/10] add some content! --- content/core/actions/CoreActions.ts | 16 ++++++++++++++ content/core/items/Items.ts | 21 +++++++------------ content/core/tasks/GatherRocksTask.ts | 30 ++++++++++++++++++++------- package.json | 2 +- src/Pawn.ts | 17 +++++---------- yarn.lock | 2 +- 6 files changed, 53 insertions(+), 35 deletions(-) create mode 100644 content/core/actions/CoreActions.ts diff --git a/content/core/actions/CoreActions.ts b/content/core/actions/CoreActions.ts new file mode 100644 index 0000000..63ec66c --- /dev/null +++ b/content/core/actions/CoreActions.ts @@ -0,0 +1,16 @@ +import { registerAction } from '@actions'; +import { Game } from '@game'; + +registerAction('Gather Flint', (qty) => { + Game.current.board.addTask({ + taskId: 'core:gather-flint', + options: {} + }) +}); + +registerAction('Gather Slate', (qty) => { + Game.current.board.addTask({ + taskId: 'core:gather-slate', + options: {} + }) +}); diff --git a/content/core/items/Items.ts b/content/core/items/Items.ts index 6bb224f..9b29d29 100644 --- a/content/core/items/Items.ts +++ b/content/core/items/Items.ts @@ -1,18 +1,13 @@ import { Item } from '@items'; -export const LOG = new Item() - .setName("Log") - .setId('core:resources/log'); - -export const ROCK = new Item() - .setName("Rock") - .setId('core:resources/rock'); - -export const STICK = new Item() - .setName("Stick") - .setId('core:resources/stick'); +export const LOG = new Item().setName("Log").setId('core:resources/log'); +export const STICK = new Item().setName("Stick").setId('core:resources/stick'); +export const FLINT_NORMAL = new Item().setName("Flint").setId('core:flint'); +export const FLINT_FLAKE = new Item().setName("Flint Flake").setId('core:flint-flake'); +export const SANDSTONE_NORMAL = new Item().setName("Sandstone").setId('core:sandstone'); +export const SLATE_NORMAL = new Item().setName("Slate").setId('core:slate'); // slate, flint X normal, flake -// limestone: large, small -// shale \ No newline at end of file +// limestone, shale, sandstone: large, small +// shale - igneous. metamorphasis => slate \ No newline at end of file diff --git a/content/core/tasks/GatherRocksTask.ts b/content/core/tasks/GatherRocksTask.ts index 02d3160..794fdf7 100644 --- a/content/core/tasks/GatherRocksTask.ts +++ b/content/core/tasks/GatherRocksTask.ts @@ -1,22 +1,36 @@ import { Task, registerTask } from "@tasks"; import chalk from 'chalk'; import { Game } from '@game'; -import { ROCK } from '../items/Items.js'; +import { FLINT_NORMAL, SLATE_NORMAL } from '../items/Items.js'; -class GatherRocksTask extends Task { - work = 100; +registerTask('core:gather-flint', class GatherFlintTask extends Task { + work = 1000; reward(): void { - Game.current.inv.add(ROCK, 1); + Game.current.inv.add(FLINT_NORMAL, 1); } get title() { - return chalk.yellow('Chop Trees'); + return 'Gather Flint'; } get status() { - return chalk.yellow('LOGGING'); + return 'SCAVENGING'; } -} +}); -registerTask('core:gather-rocks', GatherRocksTask); \ No newline at end of file +registerTask('core:gather-slate', class GatherSlateTask extends Task { + work = 1000; + + reward(): void { + Game.current.inv.add(SLATE_NORMAL, 1); + } + + get title() { + return 'Gather Slate'; + } + + get status() { + return 'SCAVENGING'; + } +}); \ No newline at end of file diff --git a/package.json b/package.json index f8c38a8..f1cc8b2 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "chalk": "^4.1.1", "deepmerge": "^4.2.2", "faker": "^5.5.3", - "frigid": "^1.3.12", + "frigid": "^1.3.13", "fs-extra": "^10.0.0", "get-port": "^5.1.1", "mocha": "^9.0.1", diff --git a/src/Pawn.ts b/src/Pawn.ts index 1adbae8..237fc8f 100644 --- a/src/Pawn.ts +++ b/src/Pawn.ts @@ -7,21 +7,14 @@ import { render } from './ui/UI.js'; import { Memory } from './Memory.js'; import { getTheme } from './registries/Themes.js'; -const LABORS = { - CUT_TREE: Symbol('CUT_TREE'), - MINING: Symbol('CUT_TREE'), -} - -const SKILLS = { - PICKAXE: Symbol('PICKAXE'), - HATCHET: Symbol('HATCHET') -} - // const STATUS = { // IDLE: Symbol('IDLE') // } const energyScale = 0.1; +const MAX_ENERGY = 100; + +// TODO add stats getter to return % of all stats export class Pawn extends Serializable implements Tickable { name: { @@ -46,7 +39,7 @@ export class Pawn extends Serializable implements Tickable { if(this.awake === false) { this.energy += energyScale * 4; - if(this.energy >= 100) { + if(this.energy >= MAX_ENERGY) { this.awake = true; } } else { @@ -88,7 +81,7 @@ export class Pawn extends Serializable implements Tickable { this.name.first = faker.name.firstName(this.sex); } this.awake ??= true; - this.energy ??= 100; + this.energy ??= MAX_ENERGY; this.memories ??= []; if(!this.age) { this.age = Math.floor(525600 * (16 + Math.random() * 9)); diff --git a/yarn.lock b/yarn.lock index 93b9a85..7f38f58 100644 --- a/yarn.lock +++ b/yarn.lock @@ -316,7 +316,7 @@ flat@^5.0.2: resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== -frigid@^1.3.12: +frigid@^1.3.13: version "1.3.13" resolved "https://registry.yarnpkg.com/frigid/-/frigid-1.3.13.tgz#27d8592ec1aeb72964fbc4014e38e6c366c5e3b7" integrity sha512-suwEa7JuMvNqIlVpc848wIptC8o3Ztvadv8a1HojbaNcYdowOlqWi/ieSgQZkBVCpmrBOq7IeuaB6p4BvCUdHQ== From 6ab8874432a5b43f001e41b428e30b8f8e4ba5f8 Mon Sep 17 00:00:00 2001 From: Bronwen Date: Wed, 23 Jun 2021 18:53:49 -0400 Subject: [PATCH 09/10] content! --- content/core/actions/CoreActions.ts | 7 +++++++ content/core/actions/FetchSticksAction.ts | 9 +-------- content/core/actions/GatherRocksAction.ts | 7 ------- content/core/items/Items.ts | 24 +++++++++++++++++++++-- 4 files changed, 30 insertions(+), 17 deletions(-) diff --git a/content/core/actions/CoreActions.ts b/content/core/actions/CoreActions.ts index 63ec66c..e60a699 100644 --- a/content/core/actions/CoreActions.ts +++ b/content/core/actions/CoreActions.ts @@ -14,3 +14,10 @@ registerAction('Gather Slate', (qty) => { options: {} }) }); + +registerAction('Fetch Sticks', (qty) => { + Game.current.board.addTask({ + taskId: "core:fetch-sticks", + options: {} + }) +}); \ No newline at end of file diff --git a/content/core/actions/FetchSticksAction.ts b/content/core/actions/FetchSticksAction.ts index e7801e9..fe9ee92 100644 --- a/content/core/actions/FetchSticksAction.ts +++ b/content/core/actions/FetchSticksAction.ts @@ -1,9 +1,2 @@ import { registerAction } from '@actions'; -import { Game } from '@game'; - -registerAction('Fetch Sticks', (qty) => { - Game.current.board.addTask({ - taskId: "core:fetch-sticks", - options: {} - }) -}); \ No newline at end of file +import { Game } from '@game'; \ No newline at end of file diff --git a/content/core/actions/GatherRocksAction.ts b/content/core/actions/GatherRocksAction.ts index c0f0ba5..0183670 100644 --- a/content/core/actions/GatherRocksAction.ts +++ b/content/core/actions/GatherRocksAction.ts @@ -1,9 +1,2 @@ import { registerAction } from '@actions'; import { Game } from '@game'; - -registerAction('Gather Rocks', (qty) => { - Game.current.board.addTask({ - taskId: 'core:gather-rocks', - options: {} - }) -}); diff --git a/content/core/items/Items.ts b/content/core/items/Items.ts index 9b29d29..695f2d9 100644 --- a/content/core/items/Items.ts +++ b/content/core/items/Items.ts @@ -2,12 +2,32 @@ import { Item } from '@items'; export const LOG = new Item().setName("Log").setId('core:resources/log'); export const STICK = new Item().setName("Stick").setId('core:resources/stick'); +export const PLANT_FIBRES = new Item().setName("Stick").setId('core:plant-fibres'); export const FLINT_NORMAL = new Item().setName("Flint").setId('core:flint'); export const FLINT_FLAKE = new Item().setName("Flint Flake").setId('core:flint-flake'); export const SANDSTONE_NORMAL = new Item().setName("Sandstone").setId('core:sandstone'); +export const SANDSTONE_PEBBLE = new Item().setName("Sandstone Pebble").setId('core:sandstone-pebble'); export const SLATE_NORMAL = new Item().setName("Slate").setId('core:slate'); +export const SLATE_FLAKE = new Item().setName("Slate Flake").setId('core:slate-flake'); +export const LIMESTONE_NORMAL = new Item().setName("Limestone").setId('core:limestone'); +export const LIMESTONE_PEBBLE = new Item().setName("Limestone Pebble").setId('core:limestone-pebble'); +export const SHALE_NORMAL = new Item().setName("Shale").setId('core:shale'); +export const SHALE_PEBBLE = new Item().setName("Shale Pebble").setId('core:shale-pebble'); +export const OBSIDIAN_NORMAL = new Item().setName("Obsidian").setId('core:obsidian') +export const OBSIDIAN_FLAKE = new Item().setName("Obsidian Flake").setId('core:obsidian-flake'); -// slate, flint X normal, flake -// limestone, shale, sandstone: large, small +export const FLINT_HATCHET = new Item().setName("Flint Hatchet").setId('core:flint-hatchet'); +export const FLINT_ARROWHEAD = new Item().setName("Flint Arrowhead").setId('core:flint-arrowhead'); +export const FLINT_SPEAR = new Item().setName("Flint Spear").setId('core:flint-spear'); +export const SLATE_HATCHET = new Item().setName("Slate Hatchet").setId('core:slate-hatchet'); +export const SLATE_ARROWHEAD = new Item().setName("Slate Arrowhead").setId('core:slate-arrowhead'); +export const SLATE_SPEAR = new Item().setName("Slate Spear").setId('core:slate-spear'); +export const OBSIDIAN_HATCHET = new Item().setName("Obsidian Hatchet").setId('core:obsidian-hatchet'); +export const OBSIDIAN_ARROWHEAD = new Item().setName("Obsidian Arrowhead").setId('core:obsidian-arrowhead'); +export const OBSIDIAN_SPEAR = new Item().setName("Obsidian Spear").setId('core:obsidian-spear'); + + + +// tools: plant fibres = rope, flint hatchet // shale - igneous. metamorphasis => slate \ No newline at end of file From 6bab735b9689670e73c26ab7db5539f88025d993 Mon Sep 17 00:00:00 2001 From: Bronwen Date: Wed, 23 Jun 2021 20:37:56 -0400 Subject: [PATCH 10/10] language --- content/core/items/Items.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/content/core/items/Items.ts b/content/core/items/Items.ts index 695f2d9..af6aa65 100644 --- a/content/core/items/Items.ts +++ b/content/core/items/Items.ts @@ -2,7 +2,7 @@ import { Item } from '@items'; export const LOG = new Item().setName("Log").setId('core:resources/log'); export const STICK = new Item().setName("Stick").setId('core:resources/stick'); -export const PLANT_FIBRES = new Item().setName("Stick").setId('core:plant-fibres'); +export const PLANT_FIBRES = new Item().setName("Plant Fibres").setId('core:plant-fibres'); export const FLINT_NORMAL = new Item().setName("Flint").setId('core:flint'); export const FLINT_FLAKE = new Item().setName("Flint Flake").setId('core:flint-flake'); @@ -27,7 +27,5 @@ export const OBSIDIAN_HATCHET = new Item().setName("Obsidian Hatchet").setId('co export const OBSIDIAN_ARROWHEAD = new Item().setName("Obsidian Arrowhead").setId('core:obsidian-arrowhead'); export const OBSIDIAN_SPEAR = new Item().setName("Obsidian Spear").setId('core:obsidian-spear'); - - // tools: plant fibres = rope, flint hatchet // shale - igneous. metamorphasis => slate \ No newline at end of file