Merge branch 'materials'
commit
f0d42316bc
|
|
@ -2,16 +2,10 @@ import { registerAction } from '@actions';
|
||||||
import { Game } from '@game';
|
import { Game } from '@game';
|
||||||
import { ItemState } from '@items';
|
import { ItemState } from '@items';
|
||||||
import { TaskState } from '@tasks';
|
import { TaskState } from '@tasks';
|
||||||
|
import { SelectItem } from '../../../src/ui/SelectItem.js';
|
||||||
import { FLINT_NORMAL } from '../items/CoreItems.js';
|
import { FLINT_NORMAL } from '../items/CoreItems.js';
|
||||||
import { GATHER_FLINT, MAKE_ARROWHEAD } from '../tasks/CoreTasks.js';
|
import { GATHER_FLINT, MAKE_ARROWHEAD } from '../tasks/CoreTasks.js';
|
||||||
|
|
||||||
// registerAction('Gather Flint', (qty) => {
|
|
||||||
// Game.current.board.addTask({
|
|
||||||
// taskId: 'core:gather-flint',
|
|
||||||
// options: {}
|
|
||||||
// })
|
|
||||||
// });
|
|
||||||
|
|
||||||
// registerAction('Gather Slate', (qty) => {
|
// registerAction('Gather Slate', (qty) => {
|
||||||
// Game.current.board.addTask({
|
// Game.current.board.addTask({
|
||||||
// taskId: 'core:gather-slate',
|
// taskId: 'core:gather-slate',
|
||||||
|
|
@ -24,8 +18,11 @@ registerAction('Gather Flint', () => {
|
||||||
Game.current.board.addTask(taskState);
|
Game.current.board.addTask(taskState);
|
||||||
});
|
});
|
||||||
|
|
||||||
registerAction('Create Arrowhead', (qty) => {
|
registerAction('Create Arrowhead', async () => {
|
||||||
const rock = new ItemState(FLINT_NORMAL, 1, null);
|
// const rock = new ItemState(FLINT_NORMAL, 1, null);
|
||||||
|
const item = await SelectItem.show((itemState) => {
|
||||||
|
return true;
|
||||||
|
});
|
||||||
const task = new TaskState(MAKE_ARROWHEAD, {
|
const task = new TaskState(MAKE_ARROWHEAD, {
|
||||||
baseMaterial: rock
|
baseMaterial: rock
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,23 @@
|
||||||
import { Item, ItemFilter, ItemProperty, ItemState } from '@items'
|
import { Item, ItemFilter, ItemProperty, ItemState } from '@items'
|
||||||
|
|
||||||
|
class Material {
|
||||||
|
name: string;
|
||||||
|
hardness: number;
|
||||||
|
|
||||||
|
setName(name: string) {
|
||||||
|
this.name = name;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
setHardness(n: number) {
|
||||||
|
this.hardness = n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// #region properties!
|
// #region properties!
|
||||||
export const ROCK = new ItemProperty('core:rock')
|
export const ROCK = new ItemProperty('core:rock')
|
||||||
export const ROCK_HARDNESS = new ItemProperty('core:mohs-hardness')
|
export const MATERIAL = new ItemProperty('core:material')
|
||||||
|
export const ROCK_SIZE = new ItemProperty('core:rock-size')
|
||||||
export const SEDIMENTARY = new ItemProperty('core:sedimentary')
|
export const SEDIMENTARY = new ItemProperty('core:sedimentary')
|
||||||
export const IGNEOUS = new ItemProperty('core:igneous')
|
export const IGNEOUS = new ItemProperty('core:igneous')
|
||||||
export const METAMORPHIC = new ItemProperty('core:metamorphic')
|
export const METAMORPHIC = new ItemProperty('core:metamorphic')
|
||||||
|
|
@ -26,7 +41,12 @@ export const PLANT_FIBRES = new Item()
|
||||||
export const FLINT_NORMAL = new Item()
|
export const FLINT_NORMAL = new Item()
|
||||||
.setName("Flint")
|
.setName("Flint")
|
||||||
.setId('core:flint')
|
.setId('core:flint')
|
||||||
.setProperty(ROCK_HARDNESS, 7)
|
.setProperty(MATERIAL, new Material()
|
||||||
|
.setName('Flint')
|
||||||
|
.setHardness(7)
|
||||||
|
)
|
||||||
|
.setProperty(ROCK, true)
|
||||||
|
.setProperty(IGNEOUS, true)
|
||||||
|
|
||||||
export const SANDSTONE_NORMAL = new Item()
|
export const SANDSTONE_NORMAL = new Item()
|
||||||
.setName("Sandstone")
|
.setName("Sandstone")
|
||||||
|
|
@ -104,9 +124,13 @@ export const OBSIDIAN_SPEAR = new Item()
|
||||||
|
|
||||||
// #endregion
|
// #endregion
|
||||||
|
|
||||||
// export function FILTER_CRAFTABLE_ROCK(item: ItemState<any>) {
|
export function FILTER_CRAFTABLE_ROCK(itemState: ItemState<any>) {
|
||||||
// return
|
if(!itemState.item.getProperty(MATERIAL)) return false;
|
||||||
// }
|
const mat: Material = itemState.item.getProperty(MATERIAL) as Material;
|
||||||
|
return itemState.item.getProperty(ROCK)
|
||||||
|
&& mat.hardness >= 6
|
||||||
|
&& mat.hardness < 10
|
||||||
|
}
|
||||||
|
|
||||||
// tools: plant fibres = rope, flint hatchet
|
// tools: plant fibres = rope, flint hatchet
|
||||||
// shale - igneous. metamorphasis => slate
|
// shale - igneous. metamorphasis => slate
|
||||||
|
|
@ -4,5 +4,5 @@ import chalk from 'chalk'
|
||||||
registerTheme("default", {});
|
registerTheme("default", {});
|
||||||
|
|
||||||
registerTheme("high contrast", {
|
registerTheme("high contrast", {
|
||||||
selected: chalk.ansi256(250).inverse
|
bright: chalk.ansi256(250).inverse
|
||||||
});
|
});
|
||||||
|
|
@ -5,6 +5,7 @@ const moduleAliases = {
|
||||||
"@actions": "./out/src/registries/Actions.js",
|
"@actions": "./out/src/registries/Actions.js",
|
||||||
"@tasks": "./out/src/registries/Tasks.js",
|
"@tasks": "./out/src/registries/Tasks.js",
|
||||||
"@items": "./out/src/registries/Items.js",
|
"@items": "./out/src/registries/Items.js",
|
||||||
|
"@ui": "./out/src/ui/UI.js",
|
||||||
"@game": "./out/src/Game.js"
|
"@game": "./out/src/Game.js"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,10 @@
|
||||||
"@types/bonjour": "^3.5.8",
|
"@types/bonjour": "^3.5.8",
|
||||||
"@types/chai": "^4.2.19",
|
"@types/chai": "^4.2.19",
|
||||||
"@types/faker": "^5.5.6",
|
"@types/faker": "^5.5.6",
|
||||||
|
"@types/fs-extra": "^9.0.11",
|
||||||
"@types/mocha": "^8.2.2",
|
"@types/mocha": "^8.2.2",
|
||||||
"@types/uuid": "^8.3.0",
|
"@types/uuid": "^8.3.0",
|
||||||
|
"@types/ws": "^7.4.6",
|
||||||
"bonjour": "^3.5.0",
|
"bonjour": "^3.5.0",
|
||||||
"chai": "^4.3.4",
|
"chai": "^4.3.4",
|
||||||
"chalk": "^4.1.1",
|
"chalk": "^4.1.1",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
console.clear();
|
||||||
|
|
||||||
|
const n = 10 ** 8;
|
||||||
|
// const map = new Map();
|
||||||
|
|
||||||
|
console.log('sequential insertion');
|
||||||
|
for(let run = 0; run < 10; run ++) {
|
||||||
|
const arr = [];
|
||||||
|
|
||||||
|
console.time('array');
|
||||||
|
for(let i = 0; i < n; i ++) {
|
||||||
|
arr.push(133769420)
|
||||||
|
}
|
||||||
|
console.timeEnd('array')
|
||||||
|
}
|
||||||
|
|
@ -9,7 +9,7 @@ import { render, Renderable, setTitle, start } from './ui/UI.js';
|
||||||
import { ready } from './multiplayer/mDNS.js';
|
import { ready } from './multiplayer/mDNS.js';
|
||||||
import faker from 'faker';
|
import faker from 'faker';
|
||||||
|
|
||||||
let game = null;
|
let game: Game = null;
|
||||||
|
|
||||||
export class Game extends Frigid implements Tickable, Renderable {
|
export class Game extends Frigid implements Tickable, Renderable {
|
||||||
pawns: Pawn[] = [];
|
pawns: Pawn[] = [];
|
||||||
|
|
@ -47,7 +47,7 @@ export class Game extends Frigid implements Tickable, Renderable {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
advanceSelection(number) {
|
advanceSelection(number: number) {
|
||||||
let index = this.pawns.indexOf(this.selected);
|
let index = this.pawns.indexOf(this.selected);
|
||||||
this.selected = this.pawns[Math.min(Math.max(index + number, 0), this.pawns.length - 1)];
|
this.selected = this.pawns[Math.min(Math.max(index + number, 0), this.pawns.length - 1)];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,29 +42,23 @@ export class Inventory extends Serializable implements Renderable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private reduceInv() {
|
private reduceInv() {
|
||||||
// TODO deduplicate itemstates...
|
this.items = this.items.reduce((items, itemState) => {
|
||||||
// use a reduce to reconstruct the array.
|
|
||||||
// REMEMBER TO MAINTAIN THE OBJECTs!
|
|
||||||
// dont do immutability to it, as the objects
|
|
||||||
// may have crossreferences! (maybe)
|
|
||||||
}
|
|
||||||
|
|
||||||
// add(item: Item, qty: number = 1) {
|
// TODO at some point, be able to merge data items?
|
||||||
// const id = item.id;
|
|
||||||
// const existingArr = this.items.filter(itemState => {
|
const existing = items.find(testItemState => {
|
||||||
// return itemState.itemId === id;
|
return itemState.itemId === testItemState.itemId
|
||||||
// });
|
&& itemState.data === testItemState.data;
|
||||||
// let existing: ItemState = null;
|
});
|
||||||
// if(existingArr.length === 1) {
|
|
||||||
// existing = existingArr[0];
|
if(existing) {
|
||||||
// }
|
existing.qty += itemState.qty;
|
||||||
// if(existing) {
|
} else {
|
||||||
// existing.qty += qty;
|
items.push(itemState);
|
||||||
// } else {
|
}
|
||||||
// this.items.push(new ItemState(item, qty, {}));
|
return items
|
||||||
// }
|
}, [] as ItemState<any>[])
|
||||||
// Game.current.sync();
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return this.items.map(item => item.render()).join('\n');
|
return this.items.map(item => item.render()).join('\n');
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ export class TaskList extends Serializable implements Renderable {
|
||||||
this.tasks = [...this.tasks, task];
|
this.tasks = [...this.tasks, task];
|
||||||
}
|
}
|
||||||
|
|
||||||
removeTask(task) {
|
removeTask(task: TaskState<any>) {
|
||||||
this.tasks = this.tasks.filter(v => v !== task);
|
this.tasks = this.tasks.filter(v => v !== task);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -118,7 +118,7 @@ export default class Time extends Serializable implements Renderable {
|
||||||
setTimeout(this.doTick.bind(this), 0);
|
setTimeout(this.doTick.bind(this), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
advanceTime(seconds) {
|
advanceTime(seconds: number) {
|
||||||
this.minute += seconds / 60;
|
this.minute += seconds / 60;
|
||||||
this.normalize()
|
this.normalize()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
11
src/World.ts
11
src/World.ts
|
|
@ -1,5 +1,14 @@
|
||||||
|
import { ItemState } from "@items";
|
||||||
import { Serializable } from "frigid";
|
import { Serializable } from "frigid";
|
||||||
|
|
||||||
export class World extends Serializable {
|
export class World extends Serializable {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class WorldItemState {
|
||||||
|
itemState: ItemState<any>
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -29,7 +29,7 @@ export type GiftMessage = {
|
||||||
|
|
||||||
export default network;
|
export default network;
|
||||||
|
|
||||||
export async function ready(name) {
|
export async function ready(name: string) {
|
||||||
const port = await getPort({port: getPort.makeRange(52300, 52399)});
|
const port = await getPort({port: getPort.makeRange(52300, 52399)});
|
||||||
mdns.publish({
|
mdns.publish({
|
||||||
type: 'dfi',
|
type: 'dfi',
|
||||||
|
|
@ -39,7 +39,7 @@ export async function ready(name) {
|
||||||
const wss = new WebSocket.Server({ port });
|
const wss = new WebSocket.Server({ port });
|
||||||
wss.on('connection', function connection(ws) {
|
wss.on('connection', function connection(ws) {
|
||||||
ws.on('message', function incoming(message) {
|
ws.on('message', function incoming(message) {
|
||||||
const {pawns: pawnJsons, from} = JSON.parse(message);
|
const {pawns: pawnJsons, from} = JSON.parse(message.toString());
|
||||||
const pawns = [];
|
const pawns = [];
|
||||||
for(const pawnJson of pawnJsons) {
|
for(const pawnJson of pawnJsons) {
|
||||||
const pawn: Pawn = Pawn.fromJson(pawnJson);
|
const pawn: Pawn = Pawn.fromJson(pawnJson);
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { Renderable } from "../ui/UI.js";
|
||||||
|
|
||||||
export const actions: Action[] = [];
|
export const actions: Action[] = [];
|
||||||
|
|
||||||
export function registerAction(name: string, invoke: (qty: number) => void) {
|
export function registerAction(name: string, invoke: () => void) {
|
||||||
console.log('Registered action', name);
|
console.log('Registered action', name);
|
||||||
actions.push(new Action(name, invoke))
|
actions.push(new Action(name, invoke))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,16 +6,14 @@ export type ItemID = string;
|
||||||
|
|
||||||
const items = new Map<ItemID, Item<any>>();
|
const items = new Map<ItemID, Item<any>>();
|
||||||
|
|
||||||
export type PropertyValue = number | boolean;
|
|
||||||
|
|
||||||
// ITEMS SHALL BE SINGULAR
|
// ITEMS SHALL BE SINGULAR
|
||||||
export class Item<Data> extends Serializable {
|
export class Item<Data> extends Serializable {
|
||||||
|
|
||||||
name = '';
|
name = '';
|
||||||
id: ItemID = '';
|
id: ItemID = '';
|
||||||
props: Map<string, PropertyValue> = new Map();
|
props: Map<string, any> = new Map();
|
||||||
|
|
||||||
setName(name) {
|
setName(name: string) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.register(false);
|
this.register(false);
|
||||||
return this;
|
return this;
|
||||||
|
|
@ -35,7 +33,7 @@ export class Item<Data> extends Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
setProperty(prop: ItemProperty, value: any) {
|
setProperty(prop: ItemProperty, value: any) {
|
||||||
this.props[prop.name] = value;
|
this.props.set(prop.name, value);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -50,6 +48,12 @@ export class ItemState<Data> extends Serializable implements Renderable {
|
||||||
itemId: ItemID;
|
itemId: ItemID;
|
||||||
data: Data;
|
data: Data;
|
||||||
|
|
||||||
|
take(qty: number) {
|
||||||
|
if(this.qty < qty) throw new Error('cant split more than stack from stack...');
|
||||||
|
this.qty -= qty;
|
||||||
|
return new ItemState<Data>(this.item, qty, this.data);
|
||||||
|
}
|
||||||
|
|
||||||
get item() {
|
get item() {
|
||||||
if(!items.has(this.itemId))
|
if(!items.has(this.itemId))
|
||||||
throw new Error('unknown item: ' + this.itemId);
|
throw new Error('unknown item: ' + this.itemId);
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,9 @@ type StyleFunction = (text: string) => string;
|
||||||
export type Theme = {
|
export type Theme = {
|
||||||
header: StyleFunction,
|
header: StyleFunction,
|
||||||
subheader: StyleFunction,
|
subheader: StyleFunction,
|
||||||
|
bright: StyleFunction,
|
||||||
normal: StyleFunction,
|
normal: StyleFunction,
|
||||||
selected: StyleFunction,
|
dimmed: StyleFunction,
|
||||||
hotkey: StyleFunction,
|
hotkey: StyleFunction,
|
||||||
tab: {
|
tab: {
|
||||||
normal: StyleFunction,
|
normal: StyleFunction,
|
||||||
|
|
@ -42,10 +43,11 @@ export type Theme = {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const backupTheme: Theme = {
|
export const backupTheme: Theme = {
|
||||||
header: chalk.ansi256(255).bold,
|
header: chalk.ansi256(255),
|
||||||
subheader: chalk.ansi256(243).bold,
|
subheader: chalk.ansi256(250),
|
||||||
normal: chalk.ansi256(243),
|
bright: chalk.ansi256(255),
|
||||||
selected: chalk.ansi256(250),
|
normal: chalk.ansi256(250),
|
||||||
|
dimmed: chalk.ansi256(245),
|
||||||
hotkey: chalk.ansi256(40),
|
hotkey: chalk.ansi256(40),
|
||||||
tab: {
|
tab: {
|
||||||
normal: chalk.ansi256(117),
|
normal: chalk.ansi256(117),
|
||||||
|
|
@ -53,7 +55,7 @@ export const backupTheme: Theme = {
|
||||||
},
|
},
|
||||||
border: {
|
border: {
|
||||||
focused: '#ffffff',
|
focused: '#ffffff',
|
||||||
normal: '#222222'
|
normal: '#888888'
|
||||||
},
|
},
|
||||||
progressBar: {
|
progressBar: {
|
||||||
indicator: {
|
indicator: {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
declare module "neo-blessed";
|
||||||
|
|
@ -25,7 +25,7 @@ export class GiftPopup {
|
||||||
tags: true,
|
tags: true,
|
||||||
...boxStyle(),
|
...boxStyle(),
|
||||||
});
|
});
|
||||||
this.box.on('keypress', (evt, key) => {
|
this.box.on('keypress', (evt: {}, key: {full: string}) => {
|
||||||
if(key.full === 'enter') {
|
if(key.full === 'enter') {
|
||||||
this.send();
|
this.send();
|
||||||
} if(key.full === 'escape' || key.full === 'enter') {
|
} if(key.full === 'escape' || key.full === 'enter') {
|
||||||
|
|
@ -69,7 +69,7 @@ export class GiftPopup {
|
||||||
this.box.setContent(`${(() => {
|
this.box.setContent(`${(() => {
|
||||||
let pawns = [];
|
let pawns = [];
|
||||||
for (const [pawn, qty] of this.pawns.entries()) {
|
for (const [pawn, qty] of this.pawns.entries()) {
|
||||||
const style = i === this.selected ? getTheme().selected : getTheme().normal;
|
const style = i === this.selected ? getTheme().bright : getTheme().normal;
|
||||||
if(qty > 0) {
|
if(qty > 0) {
|
||||||
pawns.push(style(`{|}${pawn.toString()} `))
|
pawns.push(style(`{|}${pawn.toString()} `))
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ import { View } from './View.js';
|
||||||
import { ActionsView } from './view/ActionsView.js';
|
import { ActionsView } from './view/ActionsView.js';
|
||||||
import { tasks } from '@tasks';
|
import { tasks } from '@tasks';
|
||||||
|
|
||||||
const clamp = (min, max, value) => Math.min(Math.max(value, min), max);
|
const clamp = (min: number, max: number, value: number) => Math.min(Math.max(value, min), max);
|
||||||
|
|
||||||
// TODO move KeypressAcceptor to ui something idk
|
// TODO move KeypressAcceptor to ui something idk
|
||||||
export interface KeypressAcceptor {
|
export interface KeypressAcceptor {
|
||||||
|
|
@ -46,7 +46,7 @@ export class Menu implements Renderable {
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
panels.right.on('keypress', (evt, key) => {
|
panels.right.on('keypress', (evt: {}, key: {full: string}) => {
|
||||||
|
|
||||||
if (key.full === 'left') {
|
if (key.full === 'left') {
|
||||||
this.regressView();
|
this.regressView();
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ export class PawnDetails {
|
||||||
tags: true,
|
tags: true,
|
||||||
...boxStyle(),
|
...boxStyle(),
|
||||||
});
|
});
|
||||||
this.box.on('keypress', (evt, key) => {
|
this.box.on('keypress', (evt: {}, key: {full: string}) => {
|
||||||
if(key.full === 'escape' || key.full === 'enter') {
|
if(key.full === 'escape' || key.full === 'enter') {
|
||||||
Game.current.clock.start();
|
Game.current.clock.start();
|
||||||
panels.screen.remove(this.box);
|
panels.screen.remove(this.box);
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,11 @@ import { panels } from './UI.js';
|
||||||
export class Popup {
|
export class Popup {
|
||||||
box;
|
box;
|
||||||
|
|
||||||
static show(content) {
|
static show(content: string) {
|
||||||
new Popup(content)
|
new Popup(content)
|
||||||
}
|
}
|
||||||
|
|
||||||
private constructor(content) {
|
private constructor(content: string) {
|
||||||
this.box = blessed.box({
|
this.box = blessed.box({
|
||||||
top: 'center',
|
top: 'center',
|
||||||
left: 'center',
|
left: 'center',
|
||||||
|
|
@ -21,7 +21,7 @@ export class Popup {
|
||||||
tags: true,
|
tags: true,
|
||||||
...boxStyle(),
|
...boxStyle(),
|
||||||
});
|
});
|
||||||
this.box.on('keypress', (evt, key) => {
|
this.box.on('keypress', (evt: {}, key: {full: string}) => {
|
||||||
if(key.full === 'escape' || key.full === 'enter') {
|
if(key.full === 'escape' || key.full === 'enter') {
|
||||||
Game.current.clock.start();
|
Game.current.clock.start();
|
||||||
panels.screen.remove(this.box);
|
panels.screen.remove(this.box);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,77 @@
|
||||||
|
import { Game } from "@game";
|
||||||
|
import { ItemState } from "@items";
|
||||||
|
import { boxStyle, getTheme } from "@themes";
|
||||||
|
import { panels } from "@ui";
|
||||||
|
import EventEmitter from "events";
|
||||||
|
import blessed from 'neo-blessed';
|
||||||
|
|
||||||
|
type ItemFilterFunction = (itemState: ItemState<any>) => boolean;
|
||||||
|
|
||||||
|
export class SelectItem {
|
||||||
|
box: any;
|
||||||
|
emitter: EventEmitter;
|
||||||
|
qty: number;
|
||||||
|
items: ItemState<any>[];
|
||||||
|
selectedIdx: number;
|
||||||
|
|
||||||
|
static show(filter: ItemFilterFunction, qty: number = 1): Promise<ItemState<any>> {
|
||||||
|
const si = new SelectItem(filter, qty);
|
||||||
|
return new Promise(res => {
|
||||||
|
si.emitter.on('selected', (itemState: ItemState<any>) => {
|
||||||
|
res(itemState);
|
||||||
|
});
|
||||||
|
si.emitter.on('cancel', () => {
|
||||||
|
res(null);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private open() {
|
||||||
|
panels.screen.append(this.box);
|
||||||
|
this.box.focus();
|
||||||
|
Game.current.clock.pause();
|
||||||
|
}
|
||||||
|
|
||||||
|
private close() {
|
||||||
|
Game.current.clock.start();
|
||||||
|
panels.screen.remove(this.box);
|
||||||
|
}
|
||||||
|
|
||||||
|
get selectedItem(): ItemState<any> {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private constructor(filter: ItemFilterFunction, qty: number) {
|
||||||
|
this.emitter = new EventEmitter();
|
||||||
|
this.qty = qty;
|
||||||
|
this.box = blessed.box({
|
||||||
|
top: 'center',
|
||||||
|
left: 'center',
|
||||||
|
width: 'shrink',
|
||||||
|
height: 'shrink',
|
||||||
|
tags: true,
|
||||||
|
...boxStyle(),
|
||||||
|
});
|
||||||
|
this.box.on('keypress', (evt: {}, key: {full: string}) => {
|
||||||
|
if(key.full === 'escape') {
|
||||||
|
this.emitter.emit('cancel');
|
||||||
|
this.close();
|
||||||
|
} else if(key.full === 'enter') {
|
||||||
|
this.emitter.emit('selected', this.selectedItem.take(this.qty));
|
||||||
|
this.close();
|
||||||
|
} else if(key.full === 'down') {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.items = Game.current.inv.items.filter(filter);
|
||||||
|
this.update();
|
||||||
|
this.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
update() {
|
||||||
|
this.box.setContent('test');
|
||||||
|
panels.screen.render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import blessed from 'neo-blessed';
|
import blessed from 'neo-blessed';
|
||||||
import ansi from 'sisteransi';
|
import ansi from 'sisteransi';
|
||||||
|
|
@ -99,7 +98,8 @@ export function start() {
|
||||||
|
|
||||||
process.stdout.write(ansi.cursor.hide);
|
process.stdout.write(ansi.cursor.hide);
|
||||||
|
|
||||||
screen.key(['C-c'], function(ch, key) {
|
// todo make a real menu
|
||||||
|
screen.key(['C-c'], function() {
|
||||||
process.stdout.write(ansi.cursor.show);
|
process.stdout.write(ansi.cursor.show);
|
||||||
setTimeout(_ => {
|
setTimeout(_ => {
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ export class ActionsView extends View {
|
||||||
this.name = 'Actions';
|
this.name = 'Actions';
|
||||||
}
|
}
|
||||||
|
|
||||||
keypress(key) {
|
keypress(key: {full: string}) {
|
||||||
if(key.full === 'up') {
|
if(key.full === 'up') {
|
||||||
this.actionIdx --;
|
this.actionIdx --;
|
||||||
} else if (key.full === 'down') {
|
} else if (key.full === 'down') {
|
||||||
|
|
@ -24,7 +24,7 @@ export class ActionsView extends View {
|
||||||
render() {
|
render() {
|
||||||
return actions.map((action, idx) => `${(() => {
|
return actions.map((action, idx) => `${(() => {
|
||||||
if(this.actionIdx === idx) {
|
if(this.actionIdx === idx) {
|
||||||
return getTheme().selected(' ❯ ' + action.name);
|
return getTheme().bright(' ❯ ' + action.name);
|
||||||
} else {
|
} else {
|
||||||
return getTheme().normal(' ' + action.name);
|
return getTheme().normal(' ' + action.name);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ export default class MultiplayerView extends View {
|
||||||
render() {
|
render() {
|
||||||
if(mdns.players.length === 0) return `{center}${getTheme().normal('No friends online')}{/center}`;
|
if(mdns.players.length === 0) return `{center}${getTheme().normal('No friends online')}{/center}`;
|
||||||
return mdns.players.map((player, i) => {
|
return mdns.players.map((player, i) => {
|
||||||
if(i === this.selected) return ' ' + getTheme().selected(' ❯ ' + player.toString());
|
if(i === this.selected) return ' ' + getTheme().bright(' ❯ ' + player.toString());
|
||||||
else return ' ' + getTheme().normal(player.toString());
|
else return ' ' + getTheme().normal(player.toString());
|
||||||
}).join('\n');
|
}).join('\n');
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -6,36 +6,36 @@ import { panels } from "../UI.js";
|
||||||
import { View } from "../View.js";
|
import { View } from "../View.js";
|
||||||
|
|
||||||
export default class PawnsView extends View {
|
export default class PawnsView extends View {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.name = 'Pawns';
|
this.name = 'Pawns';
|
||||||
}
|
}
|
||||||
|
|
||||||
keypress(key: { full: string; }) {
|
keypress(key: { full: string; }) {
|
||||||
if (key.full === 'delete') {
|
if (key.full === 'delete') {
|
||||||
Game.current.removePawn(Game.current.selected);
|
Game.current.removePawn(Game.current.selected);
|
||||||
} else if (key.full === 'up') {
|
} else if (key.full === 'up') {
|
||||||
Game.current.advanceSelection(-1);
|
Game.current.advanceSelection(-1);
|
||||||
} else if (key.full === 'down') {
|
} else if (key.full === 'down') {
|
||||||
Game.current.advanceSelection(1);
|
Game.current.advanceSelection(1);
|
||||||
} else if (key.full === 'enter') {
|
} else if (key.full === 'enter') {
|
||||||
new PawnDetails(Game.current.selected);
|
new PawnDetails(Game.current.selected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return `${
|
return `${
|
||||||
Game.current.pawns.map(pawn => `${(function() {
|
Game.current.pawns.map(pawn => `${(function() {
|
||||||
const selected = pawn === Game.current.selected;
|
const selected = pawn === Game.current.selected;
|
||||||
let str = '';
|
let str = '';
|
||||||
if(selected) {
|
if(selected) {
|
||||||
str += ` ${getTheme().selected(` ❯ ${pawn.toString()}`)}{|}${pawn.status} \n`;
|
str += ` ${getTheme().bright(` ❯ ${pawn.toString()}`)}{|}${pawn.status} \n`;
|
||||||
str += ` ${getTheme().normal('Energy')}{|}${progressbar(pawn.energy / 100, (panels.right.width - 4) / 2)} \n`;
|
str += ` ${getTheme().normal('Energy')}{|}${progressbar(pawn.energy / 100, (panels.right.width - 4) / 2)} \n`;
|
||||||
} else {
|
} else {
|
||||||
str += ` ${getTheme().normal(pawn.toString())}{|}${pawn.status} `;
|
str += ` ${getTheme().normal(pawn.toString())}{|}${pawn.status} `;
|
||||||
}
|
}
|
||||||
return str;
|
return str;
|
||||||
})()}`).join('\n')
|
})()}`).join('\n')
|
||||||
}`;
|
}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -12,8 +12,10 @@
|
||||||
"@actions": ["./src/registries/Actions"],
|
"@actions": ["./src/registries/Actions"],
|
||||||
"@tasks": ["./src/registries/Tasks"],
|
"@tasks": ["./src/registries/Tasks"],
|
||||||
"@items": ["./src/registries/Items"],
|
"@items": ["./src/registries/Items"],
|
||||||
|
"@ui": ["./src/ui/UI"],
|
||||||
"@game": ["./src/Game"]
|
"@game": ["./src/Game"]
|
||||||
}
|
},
|
||||||
|
"noImplicitAny": true
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"src/**/*.ts",
|
"src/**/*.ts",
|
||||||
|
|
|
||||||
14
yarn.lock
14
yarn.lock
|
|
@ -35,6 +35,13 @@
|
||||||
version "5.5.6"
|
version "5.5.6"
|
||||||
resolved "https://registry.yarnpkg.com/@types/faker/-/faker-5.5.6.tgz#039b700a9d8ad9150ecc842bf5e717e2027b6f75"
|
resolved "https://registry.yarnpkg.com/@types/faker/-/faker-5.5.6.tgz#039b700a9d8ad9150ecc842bf5e717e2027b6f75"
|
||||||
|
|
||||||
|
"@types/fs-extra@^9.0.11":
|
||||||
|
version "9.0.11"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-9.0.11.tgz#8cc99e103499eab9f347dbc6ca4e99fb8d2c2b87"
|
||||||
|
integrity sha512-mZsifGG4QeQ7hlkhO56u7zt/ycBgGxSVsFI/6lGTU34VtwkiqrrSDgw0+ygs8kFGWcXnFQWMrzF2h7TtDFNixA==
|
||||||
|
dependencies:
|
||||||
|
"@types/node" "*"
|
||||||
|
|
||||||
"@types/minimatch@^3.0.3", "@types/minimatch@^3.0.4":
|
"@types/minimatch@^3.0.3", "@types/minimatch@^3.0.4":
|
||||||
version "3.0.4"
|
version "3.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.4.tgz#f0ec25dbf2f0e4b18647313ac031134ca5b24b21"
|
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.4.tgz#f0ec25dbf2f0e4b18647313ac031134ca5b24b21"
|
||||||
|
|
@ -53,6 +60,13 @@
|
||||||
version "8.3.0"
|
version "8.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.0.tgz#215c231dff736d5ba92410e6d602050cce7e273f"
|
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.0.tgz#215c231dff736d5ba92410e6d602050cce7e273f"
|
||||||
|
|
||||||
|
"@types/ws@^7.4.6":
|
||||||
|
version "7.4.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/ws/-/ws-7.4.6.tgz#c4320845e43d45a7129bb32905e28781c71c1fff"
|
||||||
|
integrity sha512-ijZ1vzRawI7QoWnTNL8KpHixd2b2XVb9I9HAqI3triPsh1EC0xH0Eg6w2O3TKbDCgiNNlJqfrof6j4T2I+l9vw==
|
||||||
|
dependencies:
|
||||||
|
"@types/node" "*"
|
||||||
|
|
||||||
"@ungap/promise-all-settled@1.1.2":
|
"@ungap/promise-all-settled@1.1.2":
|
||||||
version "1.1.2"
|
version "1.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44"
|
resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue