diff --git a/src/client/modules/main/commands/deleteExit/DeleteExit.js b/src/client/modules/main/commands/deleteExit/DeleteExit.js index 20f6babb..15ffa94f 100644 --- a/src/client/modules/main/commands/deleteExit/DeleteExit.js +++ b/src/client/modules/main/commands/deleteExit/DeleteExit.js @@ -1,5 +1,6 @@ import l10n from 'modapp-l10n'; import ListStep from 'classes/ListStep'; +import * as translateErr from 'utils/translateErr'; const usageText = 'delete exit Keyword'; const shortDesc = 'Delete an exit'; @@ -14,7 +15,12 @@ class DeleteExit { constructor(app) { this.app = app; - this.app.require([ 'cmd', 'cmdLists', 'charLog', 'help' ], this._init.bind(this)); + this.app.require([ + 'cmd', + 'cmdLists', + 'charLog', + 'help', + ], this._init.bind(this)); } _init(module) { @@ -24,8 +30,10 @@ class DeleteExit { key: 'exit', next: new ListStep('exitId', this.module.cmdLists.getInRoomExits(), { name: "exit", + textId: 'exitKey', + errRequired: step => new Err('deleteExit.keyRequired', "What exit do you want to delete?"), }), - value: (ctx, p) => this.deleteExit(ctx.char, { exitId: p.exitId }), + value: (ctx, p) => this.deleteExit(ctx.char, p), }); this.module.help.addTopic({ @@ -40,8 +48,13 @@ class DeleteExit { } deleteExit(char, params) { - return char.call('deleteExit', params).then(() => { + return char.call('deleteExit', params.exitId + ? { exitId: params.exitId } + : { exitKey: params.exitKey }, + ).then(() => { this.module.charLog.logInfo(char, l10n.l('deleteExit.deletedExit', "Exit was successfully deleted.")); + }).catch(err => { + throw translateErr.exitNotFound(err, params.exitKey); }); } } diff --git a/src/client/modules/main/commands/getExit/GetExit.js b/src/client/modules/main/commands/getExit/GetExit.js new file mode 100644 index 00000000..d56cc33a --- /dev/null +++ b/src/client/modules/main/commands/getExit/GetExit.js @@ -0,0 +1,131 @@ +import { Elem, Txt, Html } from 'modapp-base-component'; +import l10n from 'modapp-l10n'; +import DelimStep from 'classes/DelimStep'; +import ListStep from 'classes/ListStep'; +import ItemList from 'classes/ItemList'; +import Err from 'classes/Err'; +import * as translateErr from 'utils/translateErr'; +import escapeHtml from 'utils/escapeHtml'; + +const usageText = 'get exit Keyword'; +const shortDesc = 'Get info about an exit'; +const helpText = +`

Get info about a visible exit in the room.

+

Room owners may also get info on hidden or inactive exits.

`; + +/** + * GetExit adds command to get exit attributes. + */ +class GetExit { + constructor(app) { + this.app = app; + + this.app.require([ + 'cmd', + 'cmdLists', + 'charLog', + 'help', + ], this._init.bind(this)); + } + + _init(module) { + this.module = module; + + const defaultAttr = [ + { + key: 'id', + value: (ctx, exit, p) => { + this.module.charLog.logInfo(ctx.char, l10n.l('getExit.exitHasId', "{name} has ID #{exitId}", { name: exit.name.replace(/([^.])\.$/, "$1"), exitId: exit.id })); + }, + desc: l10n.l('getExit.idDesc', "ID of the exit."), + sortOrder: 10, + }, + ]; + + this.exitAttr = new ItemList({ + compare: (a, b) => (a.sortOrder - b.sortOrder) || a.key.localeCompare(b.key), + }); + for (let o of defaultAttr) { + this.addAttribute(o); + } + + this.module.cmd.addPrefixCmd('get', { + key: 'exit', + next: [ + new ListStep('exitId', this.module.cmdLists.getInRoomExits(), { + name: "exit", + textId: 'exitKey', + errRequired: step => new Err('getExit.keyRequired', "What exit do you want to get info about?"), + }), + new DelimStep(":", { errRequired: null }), + new ListStep('attr', this.exitAttr, { + name: "exit attribute", + token: 'attr', + errRequired: null, + }), + ], + value: this._exec.bind(this), + }); + + this.module.help.addTopic({ + id: 'getExit', + category: 'buildRooms', + cmd: 'get exit', + usage: l10n.l('getExit.usage', usageText), + shortDesc: l10n.l('getExit.shortDesc', shortDesc), + desc: l10n.t('getExit.helpText', helpText), + sortOrder: 75, + }); + } + + addAttribute(attr) { + let next = attr.nextFactory ? attr.nextFactory(this.module) : attr.next; + this.exitAttr.addItem(Object.assign({}, attr, { next })); + return this; + } + + _exec(ctx, p) { + let f = p.attr; + return ctx.char.call('getExit', p.exitId + ? { exitId: p.exitId } + : { exitKey: p.exitKey }, + ).then(exit => { + return f + ? f(ctx, exit, p) + : this.getExit(ctx.char, exit); + }).catch(err => { + throw translateErr.exitNotFound(err, p.exitKey); + }); + } + + getExit(char, exit) { + try { + let rows = [ + [ "Exit", escapeHtml(exit.name), { className: 'charlog--strong' }], + [ "Exit ID", "#" + escapeHtml(exit.id) + "" ], + [ "Keywords", exit.keys.map(k => escapeHtml(k)).join(", ") ], + ]; + + let elem = new Elem(n => { + return n.elem('div', { className: 'charlog--pad' }, [ + n.elem('div', { className: 'charlog--code' }, [ + n.elem('table', { className: 'tbl-small tbl-nomargin charlog--font-small' }, rows.map(m => n.elem('tr', [ + n.elem('td', { className: 'charlog--strong' }, [ + n.component(new Txt(m[0])), + ]), + n.elem('td', [ + n.component(new Html(m[1], { className: m[2]?.className })), + ]), + ]))), + ]), + ]); + }); + + this.module.charLog.logComponent(char, 'getExit', elem); + } catch (ex) { + console.error(ex); + } + } +} + +export default GetExit; diff --git a/src/client/modules/main/commands/getRoom/GetRoom.js b/src/client/modules/main/commands/getRoom/GetRoom.js index 1bb2997d..dbea290d 100644 --- a/src/client/modules/main/commands/getRoom/GetRoom.js +++ b/src/client/modules/main/commands/getRoom/GetRoom.js @@ -11,7 +11,7 @@ import Err from 'classes/Err'; const itemsPerPage = 50; -const usageText = 'get room Attribute page Page'; +const usageText = 'get room Attribute page Page'; const shortDesc = 'Get info about current room'; const helpText = `

Get the value of a room attribute.

@@ -37,7 +37,6 @@ class GetRoom { 'charLog', 'help', 'player', - 'info', ], this._init.bind(this)); } diff --git a/src/client/modules/main/commands/go/Go.js b/src/client/modules/main/commands/go/Go.js index 723c3577..f2a6b719 100644 --- a/src/client/modules/main/commands/go/Go.js +++ b/src/client/modules/main/commands/go/Go.js @@ -1,6 +1,7 @@ import l10n from 'modapp-l10n'; import ListStep from 'classes/ListStep'; import Err from 'classes/Err'; +import * as translateErr from 'utils/translateErr'; const usageText = 'go Keyword'; const shortDesc = 'Go to another room'; @@ -45,7 +46,9 @@ class Go { return ctx.char.call('useExit', p.exitId ? { exitId: p.exitId } : { exitKey: p.exitKey }, - ); + ).catch(err => { + throw translateErr.exitNotFound(err, p.exitKey); + }); } } diff --git a/src/client/modules/main/commands/setExit/SetExit.js b/src/client/modules/main/commands/setExit/SetExit.js index 7c7904bb..8c7e6d36 100644 --- a/src/client/modules/main/commands/setExit/SetExit.js +++ b/src/client/modules/main/commands/setExit/SetExit.js @@ -9,6 +9,7 @@ import { exitIcons } from 'components/ExitIcon'; import { directions } from 'components/NavButtons'; import helpAttribDesc from 'utils/helpAttribDesc'; import { communicationTooLong, keyTooLong, itemNameTooLong } from 'utils/cmdErr'; +import * as translateErr from 'utils/translateErr'; const usageText = 'set exit Keyword : Attribute = Value'; const shortDesc = 'Set an exit attribute'; @@ -217,6 +218,8 @@ class SetExit { : { exitKey: p.exitKey }, )).then(() => { this.module.charLog.logInfo(ctx.char, l10n.l('setExit.updatedExit', "Exit attribute was successfully set.")); + }).catch(err => { + throw translateErr.exitNotFound(err, p.exitKey); }); } } diff --git a/src/client/modules/main/commands/setExitOrder/SetExitOrder.js b/src/client/modules/main/commands/setExitOrder/SetExitOrder.js index 5769cb98..ade1da61 100644 --- a/src/client/modules/main/commands/setExitOrder/SetExitOrder.js +++ b/src/client/modules/main/commands/setExitOrder/SetExitOrder.js @@ -1,6 +1,6 @@ import l10n from 'modapp-l10n'; import NumberStep from 'classes/NumberStep'; - +import * as translateErr from 'utils/translateErr'; /** * SetExitOrder adds command to set exit attributes. @@ -30,6 +30,8 @@ class SetExitOrder { setExitOrder(char, params) { return char.call('setExitOrder', params).then(result => { this.module.charLog.logInfo(char, l10n.l('setExitOrder.exitOrderSet', "Exit order was successfully set.")); + }).catch(err => { + throw translateErr.exitNotFound(err, params.exitKey); }); } } diff --git a/src/common/utils/translateErr.js b/src/common/utils/translateErr.js new file mode 100644 index 00000000..65e0e3aa --- /dev/null +++ b/src/common/utils/translateErr.js @@ -0,0 +1,16 @@ +import Err from 'classes/Err'; + +/** + * Translates a core.exitNotFound error into a more human friendly error. + * @param {ResError} err Error. + * @param {string} key Exit key used. + * @returns {Err | ResError} Translated error if the code was core.exitNotFound, otherwise the original ResError. + */ +export function exitNotFound(err, key) { + if (err?.code == 'core.exitNotFound') { + return key + ? new Err('translateErr.exitNotFoundByKey', "Cannot find the exit '{key}'.", { key }) + : new Err('translateErr.exitNotFound', "Cannot find that exit."); + } + return err; +}