diff --git a/README.md b/README.md index f642b9b..66b1533 100644 --- a/README.md +++ b/README.md @@ -39,8 +39,10 @@ Script file | Description [intercom_inside.ts](./examples/intercom_inside.ts) | An intercom script allowing communication with another room running the [intercom_outside.ts](./examples/intercom_outside.ts) script. [intercom_outside.ts](./examples/intercom_outside.ts) | An intercom script allowing communication with another room running the [intercom_inside.ts](./examples/intercom_inside.ts) script. [lock_inside.ts](./examples/lock_inside.ts) | A script that locks a door preventing others from using an exit in the room running the [lock_outside.ts](./examples/lock_outside.ts) script. -[lock_outside.ts](./examples/lock_outside.ts) | A script that prevents characters from using an exit locked by the script running the [lock_inside.ts](./examples/lock_inside.ts) script. +[lock_outside.ts](./examples/lock_outside.ts) | A script that prevents characters from using an exit locked by the [lock_inside.ts](./examples/lock_inside.ts) script. [secret_exit.ts](./examples/secret_exit.ts) | A script that reveals a secret passage when the password "tapeworm" is spoken. +[vip_list.ts](./examples/vip_list.ts) | A script that manages a list of VIP characters, requested by another room running the [vip_guard.ts](./examples/vip_guard.ts) script. +[vip_guard.ts](./examples/vip_guard.ts) | A script that prevents characters from using an exit unless they are listed as VIP character by the [vip_list.ts](./examples/vip_list.ts) script. ## About diff --git a/devbin/devutils/docsconverter.js b/devbin/devutils/docsconverter.js index b1aecd2..4dfcf25 100644 --- a/devbin/devutils/docsconverter.js +++ b/devbin/devutils/docsconverter.js @@ -608,10 +608,16 @@ export default class DocsConverter { * @return {string} Converted markdown. */ _convertToNamedHeaders(text, level = 0, idPrefix, headerCallback) { + let parentIds = []; return text.replace(/^(#+)\s*(.*)/gm, (match, hashes, title) => { title = title.trim(); const l = level + hashes.length; - const id = this._stringToId(title, idPrefix); + parentIds = parentIds.slice(0, l); + let id = this._stringToId(title, idPrefix); + id = l > 3 && parentIds[l - 1] + ? parentIds[l - 1] + '-' + id + : id; + parentIds[l] = id; headerCallback?.(title, hashes.length, id); return `${escapeHtml(title)}`; }); diff --git a/docs/documentation.md b/docs/documentation.md index 89c8f6a..3ec8482 100644 --- a/docs/documentation.md +++ b/docs/documentation.md @@ -11,6 +11,8 @@     [onCharEvent](#oncharevent)     [onExitUse](#onexituse)     [onCommand](#oncommand) +    [onRequest](#onrequest) +    [onResponse](#onresponse) [API references](#api-references) Mucklet scripts are written in AssemblyScript, a strictly typed @@ -38,8 +40,10 @@ Script file | Description [intercom_inside.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/intercom_inside.ts) | An intercom script allowing communication with another room running the [intercom_outside.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/intercom_outside.ts) script. [intercom_outside.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/intercom_outside.ts) | An intercom script allowing communication with another room running the [intercom_inside.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/intercom_inside.ts) script. [lock_inside.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/lock_inside.ts) | A script that locks a door preventing others from using an exit in the room running the [lock_outside.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/lock_outside.ts) script. -[lock_outside.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/lock_outside.ts) | A script that prevents characters from using an exit locked by the script running the [lock_inside.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/lock_inside.ts) script. +[lock_outside.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/lock_outside.ts) | A script that prevents characters from using an exit locked by the [lock_inside.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/lock_inside.ts) script. [secret_exit.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/secret_exit.ts) | A script that reveals a secret passage when the password "tapeworm" is spoken. +[vip_list.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/vip_list.ts) | A script that manages a list of VIP characters, requested by another room running the [vip_guard.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/vip_guard.ts) script. +[vip_guard.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/vip_guard.ts) | A script that prevents characters from using an exit unless they are listed as VIP character by the [vip_list.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/vip_list.ts) script.

Entry points

@@ -62,6 +66,8 @@ commands ([Room.addCommand](#function-room-addcommand)), or scheduled posts ([Sc with delay), will be removed, and [onActivate](#onactivate) will be called again on the new script version. +

Examples

+ ```ts // Send a describe to the room and log a message to the console on activation. export function onActivate(): void { @@ -73,14 +79,22 @@ export function onActivate(): void {

onRoomEvent

_onRoomEvent_ is called when an event occurs in the room, such as a _say_, -_arrive_, or _sleep_. It requires that [Room.listen](#function-room-listen) has been called -earlier, usually in the [onActivate](#onactivate) function. +_arrive_, or _sleep_. [Room.listen](#function-room-listen) must have been called earlier to +start listening to room events, usually in the [onActivate](#onactivate) +function. + +

Parameters

+ +* `addr` _(string)_: Address of this script instance receiving the event. +* `ev` _(string)_: Event encoded as a json string. + +

Examples

```ts // Check the event type and decode the event. export function onRoomEvent( - addr: string, // Address of this script instance receiving the event. - ev: string, // Event encoded as a json string. + addr: string, + ev: string, ): void { const eventType = Event.getType(ev); if (eventType == 'say') { @@ -93,16 +107,27 @@ export function onRoomEvent(

onMessage

_onMessage_ is called when another script sends a message to this script, -using [Script.post](#function-script-post). It requires that [Script.listen](#function-script-listen) has been -called earlier, usually in the [onActivate](#onactivate) function. +using [Script.post](#function-script-post). [Script.listen](#function-script-listen) must have been called +earlier to start listening to messages, usually in the +[onActivate](#onactivate) function. + +

Parameters

+ +* `addr` _(string)_: Address of this script instance receiving the message. +* `topic` _(string)_: Topic of the message. Determined by the sender. +* `data` _(string | null)_: JSON encoded data of the message or null. + Determined by the sender. +* `sender` _(string)_: Address of the sending script instance. + +

Examples

```ts // Receive a message from another script to change room profile export function onMessage( - addr: string, // Address of this script instance receiving the message. - topic: string, // Topic of the message. Determined by the sender. - data: string | null, // JSON encoded data of the message or null. Determined by the sender. - sender: string, // Address of the sending script instance. + addr: string, + topic: string, + data: string | null, + sender: string, ): void { if (topic == "changeProfile") { Room.setProfile(JSON.parse(data)) @@ -113,17 +138,28 @@ export function onMessage(

onCharEvent

_onCharEvent_ is called when a character enters a room, leaves a room, or -changes any of its properties while inside the room. It requires that -[Room.listenCharEvent](#function-room-listencharevent) has been called earlier, usually in the -[onActivate](#onactivate) function. +changes any of its properties while inside the room. +[Room.listenCharEvent](#function-room-listencharevent) must have been called earlier to start listening +to character events, usually in the [onActivate](#onactivate) function. + +

Parameters

+ +* `addr` _(string)_: Address of this script instance receiving the event. +* `charId` _(string)_: ID of character. +* `after` _(string | null)_: Character state after the event encoded as a + json string, or null if the character left the room. +* `before` _(string | null)_: Character state before the event encoded as a + json string, or null if the character entered the room. + +

Examples

```ts // Output to log when a character arrives or leaves export function onCharEvent( - addr: string, // Address of this script instance receiving the event. - charId: string, // ID of character. - after: string | null, // Character state after the event encoded as a json string, or null if the character left the room. - before: string | null, // Character state before the event encoded as a json string, or null if the character entered the room. + addr: string, + charId: string, + after: string | null, + before: string | null, ): void { if (after == null && before != null) { // If after is null, the character left @@ -140,18 +176,26 @@ export function onCharEvent(

onExitUse

-_onExitUse_ is called when a character tries to use an exit. It requires that -[Room.listenExit](#function-room-listenexit) has been called earlier, usually in the -[onActivate](#onactivate) function. The script should call either -[ExitAction.cancel](#method-exitaction-cancel) or [ExitAction.useExit](#method-exitaction-useexit) to determine what -should happen. If neither method is called, the action will timeout after 1 -second, automatically canceling the exit use with a default message. +_onExitUse_ is called when a character tries to use an exit. +[Room.listenExit](#function-room-listenexit) must have been called earlier to start listening to +exit use, usually in the [onActivate](#onactivate) function. The script +should call either [ExitAction.cancel](#method-exitaction-cancel) or [ExitAction.useExit](#method-exitaction-useexit) to +determine what should happen. If neither method is called, the action will +timeout after 1 second, automatically canceling the exit use with a default +message. + +

Parameters

+ +* `addr` _(string)_: Address of this script instance receiving the event. +* `cmdAction` _([ExitAction](#class-exitaction))_: Exit action object. + +

Examples

```ts // Prevent anyone from using an exit export function onExitUse( - addr: string, // Address of this script instance receiving the event. - exitAction: ExitAction, // Exit action object. + addr: string, + exitAction: ExitAction, ): void { exitAction.cancel("The door seems to be locked."); } @@ -159,13 +203,20 @@ export function onExitUse(

onCommand

-_onCommand_ is called when a character uses a custom command. It requires -that [Room.addCommand](#function-room-addcommand) has been called earlier to register the command, -usually in the [onActivate](#onactivate) function. The script may send a -response to the caller using either [CmdAction.info](#method-cmdaction-info), +_onCommand_ is called when a character uses a custom command. +[Room.addCommand](#function-room-addcommand) must have been called earlier to register the +command, usually in the [onActivate](#onactivate) function. The script may +send a response to the caller using either [CmdAction.info](#method-cmdaction-info), [CmdAction.error](#method-cmdaction-error), or [CmdAction.useExit](#method-cmdaction-useexit), but it is not required. The response must be sent within 1 second from the call. +

Parameters

+ +* `addr` _(string)_: Address of this script instance receiving the action. +* `cmdAction` _([CmdAction](#class-cmdaction))_: Command action object. + +

Examples

+ ```ts // Adding a ping command on activation export function onActivate(): void { @@ -181,6 +232,64 @@ export function onCommand( } ``` +

onRequest

+ +_onRequest_ is called when another script sends a request to this script, +using [Script.request](#function-script-request). [Script.listen](#function-script-listen) must have been called +earlier to start listening to requests, usually in the +[onActivate](#onactivate) function. + +

Parameters

+ +* `addr` _(string)_: Address of this script instance receiving the request. +* `request` _([Request](#class-request))_: Request object. + +

Examples

+ +```ts +// Receive a request from another script and send a response. +export function onRequest( + addr: string, + request: Request, +): void { + if (request.topic == "getValue") { + // Parse any data passed as arguments. + const key = request.parseData() + const value = Store.getString(key) + // Send a response to the request + request.reply(value) + } +} +``` + +

onResponse

+ +_onResponse_ is called when another script sends a response to a request by +calling [Request.reply](#method-request-reply). + +

Parameters

+ +* `addr` _(string)_: Address of the script instance receiving the response. +* `response` _([Response](#class-response))_: Response object. + +

Examples

+ +```ts +// Receive a response to an request +export function onResponse( + addr: string, + response: Response, +): void { + response obn + // Parse any data passed as arguments. + const key = request.ParseData() + const value = Store.getString(key); + // Send a response to the request + request.reply(value) + } +} +``` +

API references

[Type aliases](#type-aliases) @@ -209,6 +318,13 @@ export function onCommand(     [class ExitAction](#class-exitaction)         [method useExit](#method-exitaction-useexit)         [method cancel](#method-exitaction-cancel) +    [class Request](#class-request) +        [method parseData](#method-request-parsedata) +        [method reply](#method-request-reply) +        [method error](#method-request-error) +    [class Response](#class-response) +        [method isError](#method-response-iserror) +        [method parseResult](#method-response-parseresult) [Namespaces](#namespaces)     [Event namespace](#namespace-event)     [Field namespace](#namespace-field) @@ -393,6 +509,7 @@ export function onCommand(     [function Script.getChar](#function-script-getchar)     [function Script.listen](#function-script-listen)     [function Script.post](#function-script-post) +    [function Script.request](#function-script-request)     [function Script.unlisten](#function-script-unlisten) [Script classes](#script-classes)     [class Script.Char](#class-script-char) @@ -617,7 +734,7 @@ Responds to the command action with an info message.

Parameters

-* `msg` (string): Info message. +* `msg` (string): Info message. It may be formatted with info formatting and span multiple paragraphs. --- @@ -632,7 +749,7 @@ Responds to the command action with an error message.

Parameters

-* `msg` (string): Error message. +* `msg` (string): Error message. It may be formatted and span multiple paragraphs. --- @@ -766,6 +883,108 @@ shown. * `msg` (string | null): Info message to show, or default message if null. +--- + +

class Request

+ +Request is a request sent from another script. + +

class Request properties

+ +* `actionId` (i32): Action ID +* `topic` (string): Request topic +* `data` (string): Request data encoded as JSON. +* `sender` (string): Request sender address. + + +--- + +

method Request.parseData

+ +```ts +parseData(): T +``` + +Parses the data into a value of type T. + +

Returns

+ +* (T) + + +--- + +

method Request.reply

+ +```ts +reply(result: string | null = null): void +``` + +Responds to the request with a reply containing JSON encoded result. + +

Parameters

+ +* `result` (string | null): Reply data encoded as JSON. + + +--- + +

method Request.error

+ +```ts +error(msg: string): void +``` + +Responds to the request with an error message. + +

Parameters

+ +* `msg` (string): Error message. + + +--- + +

class Response

+ +Response is a response to a request sent by the script. + +

class Response properties

+ +* `result` (string | null): Result encoded as JSON. +* `error` (string | null): Error string or null on no error. + + +--- + +

method Response.isError

+ +```ts +isError(): boolean +``` + +Returns true if it is an error response by checking that the error +property is not a null value. + +

Returns

+ +* (boolean) + + +--- + +

method Response.parseResult

+ +```ts +parseResult(): T +``` + +Parses the result into a value of type T. + +

Returns

+ +* (T) + +

Namespaces

Event functions

@@ -2075,6 +2294,10 @@ new JSON.Obj() ``` +

class JSON.Obj properties

+ +* `storage` (Map<string, [JSON.Value](#class-json-value)>) + --- @@ -3332,12 +3555,14 @@ To get character description or image info use Room.getChar instead. Script.listen(addrs: Array | null = null): void ``` -Starts listening for posted messages from any of the given `addr` -addresses. If an address is a non-instance room, it will also listen to -posted messages from any instance of that room. +Starts listening for posted messages and requests, sent with +[Script.post](#function-script-post) and [Script.request](#function-script-request), from any of the given +`addr` addresses. If an address is a non-instance room, it will also +listen to posted messages from any instance of that room. -If no `addr` is provided, the script will listen to posts from _any_ -source, including scripts and bots controlled by other players. +If no `addr` is provided, the script will listen to posts and requests +from _any_ source, including scripts and bots controlled by other +players. Posts from the current script does not require listening. A script can always post to itself. @@ -3361,7 +3586,9 @@ help roomscript Script.post(addr: string, topic: string, data: string | null = null, delay: i64 = 0): ID | null ``` -Posts a message to another script with the address `addr`. +Posts a message to another script with the address `addr`. The receiving +script will get the message through the [onMessage](#onmessage) entry +point. To get the address of a room script, use the `roomscript` command. For more info, type: @@ -3381,6 +3608,36 @@ help roomscript * ([ID](#type-id) | null): Schedule [ID](#type-id) or null if the message was posted without delay of if the receiving script was not listening. +--- + +

function Script.request

+ +```ts +Script.request(addr: string, topic: string, data: string | null = null): Response +``` + +Sends a request to another script with the address `addr`. The receiving +script will get the request through the [onRequest](#onrequest) entry +point. Once replied, the requesting script will get the response together +with provided context through the [onResponse](#onresponse) entry point + +To get the address of a room script, use the `roomscript` command. For +more info, type: +``` +help roomscript +``` + +

Parameters

+ +* `addr` (string): Address of target script. If addr is "#", it will be a post to the current script instance. +* `topic` (string): Message topic. May be any kind of string. +* `data` (string | null): Additional data to be sent with the request. Must be valid JSON. + +

Returns

+ +* ([Response](#class-response)): Response to the request. + + ---

function Script.unlisten

diff --git a/examples/intercom_inside.ts b/examples/intercom_inside.ts index cca5e9f..1a56a8d 100644 --- a/examples/intercom_inside.ts +++ b/examples/intercom_inside.ts @@ -57,7 +57,7 @@ export function onRoomEvent(addr: string, ev: string): void { } } -// onCommand is called when a characters uses a script command. +// onCommand is called when a character uses a script command. export function onCommand(addr: string, cmdAction: CmdAction): void { // Get the current active state of the intercom. const active = isActive() diff --git a/examples/vip_guard.ts b/examples/vip_guard.ts new file mode 100644 index 0000000..c5140bc --- /dev/null +++ b/examples/vip_guard.ts @@ -0,0 +1,47 @@ +/** + * The vip_guard.ts is a script that prevents characters from using an exit + * unless they are added to the VIP list that is kept by the vip_list.ts script. + * + * When a character tries to use the exit, a request is sent to vip_list.ts to + * check whether or not they are VIP characters. The vip_guard.ts script and + * vip_list.ts may (and should) be running in different rooms. + */ + +// Post address to the vipList script. Replace this. +// To get a room script's address, type: roomscript +const vipListAddr = "room.aaaaaaaaaaaaaaaaaaaa#bbbbbbbbbbbbbbbbbbbb" + +// ID of the exit to guard. Replace this. +// To get a room script's address, type: get exit +// The leading # should not be included. +const exitId = "aaaaaaaaaaaaaaaaaaaa" + +export function onActivate(): void { + // Always listen and intercept any use of the exit. + Room.listenExit(exitId) +} + +// onExitUse is called when someone tries to use the exit. +export function onExitUse(addr: string, exitAction: ExitAction): void { + // Send a request to the vip_list.ts script. It waits until we receive a response. + const response = Script.request(vipListAddr, "isVip", JSON.stringify(exitAction.charId)) + + // Assert we didn't get an error response. + if (response.isError()) { + // We look the error for debugging purpose + console.debug("Request error: " + response.error!) + // We cancel the exit use attempt with a message. + exitAction.cancel("The guard can't seem to find the VIP list.") + return + } + + // Parse the response. The vip_list.ts should have sent a boolean value. + const isVip = response.parseResult() + if (isVip) { + // We let the character use the exit. + exitAction.useExit() + } else { + // We cancel the exit use attempt with a message. + exitAction.cancel("The guard blocks your way as they cannot find you in the VIP list.") + } +} diff --git a/examples/vip_list.ts b/examples/vip_list.ts new file mode 100644 index 0000000..34471be --- /dev/null +++ b/examples/vip_list.ts @@ -0,0 +1,130 @@ +/** + * The vip_list.ts is a script that keeps a list of VIP characters, with + * commands to add, remove, and list them. Other scripts, such as vip_guard.ts, + * may send requests to ask whether a character is a VIP, using + * `Script.request`: + * ``` + * const response = Script.request(vipListAddr, "isVip", JSON.stringify(charId)) + * ``` + * + * The vip_guard.ts script sends requests to this scripts to only let VIP + * characters use an exit. + * + * The script adds three commands to the room: + * ``` + * add vip + * remove vip + * list vip + * ``` + */ + +// onActivate is called when the script is activated. +export function onActivate(): void { + // Add commands for managing the VIP list + Room.addCommand( + "add", + new Command("add vip ", "Add a character to the VIP list.") + .field("Character", new Field.Char("Character to add.")), + ) + Room.addCommand( + "remove", + new Command("remove vip ", "Remove a character from the VIP list.") + .field("Character", new Field.Char("Character to remove.")), + ) + Room.addCommand( + "list", + new Command("list vip", "List all VIP characters."), + ) + // Listen for script requests. + Script.listen() +} + +// Command arguments class. Used by both the "add" and "remove" command. +@json +class Args { + @alias("Character") + char: FieldValue.Char = new FieldValue.Char(); +} + +// onCommand is called when a character uses a script command. +export function onCommand(addr: string, cmdAction: CmdAction): void { + // Handle add command + if (cmdAction.keyword == "add") { + const args = JSON.parse(cmdAction.data) + // Check if the character is already added. + if (Store.getString(args.char.id) == null) { + // Add the character to the store. As value, we store the timestamp + // when the character was added. This value currently not used in + // this script. + Store.setString(args.char.id, Date.now().toString()) + cmdAction.info(`**${args.char.name} ${args.char.surname}** was added to the VIP list.`) + } else { + cmdAction.info(`**${args.char.name} ${args.char.surname}** was already in the VIP list.`) + } + return + } + + // Handle remove command + if (cmdAction.keyword == "remove") { + const args = JSON.parse(cmdAction.data) + // Check if the character is not already removed. + if (Store.getString(args.char.id) != null) { + // Remove the character from the store. + Store.deleteKey(args.char.id) + cmdAction.info(`**${args.char.name} ${args.char.surname}** was removed from the VIP list.`) + } else { + cmdAction.info(`**${args.char.name} ${args.char.surname}** was not found in the VIP list.`) + } + return + } + + // Handle list command + if (cmdAction.keyword == "list") { + let chars = new Array() + // Iterate over all characters stored in the list + for (const iter = new Store.Iterator(); iter.isValid(); iter.next()) { + // Get the store key which is the character ID. + const charId = iter.getKeyString() + // Get character info. + const char = Script.getChar(charId) + // Verify that the character is found. + if (char != null) { + chars.push(char) + } else { + // The character is probably deleted. + // We prune our VIP list by deleting them there as well. + console.debug("Pruned " + charId) + Store.deleteKey(charId) + } + } + + // Check if the list is empty. If so, show a simple message. + if (chars.length == 0) { + cmdAction.info("_List is empty_") + return + } + + // Sort the characters by name and surname. + chars.sort((a: Script.Char, b: Script.Char) => a.name.localeCompare(b.name) || a.surname.localeCompare(b.surname)) + // Concatenate the names into a string with line breaks between each character. + const list = chars + .map((char: Script.Char, i: i32, chars: Script.Char[]) => char.name + " " + char.surname) + .join("\n") + // Show the list with a header "VIP list". For help on how to format + // text, see: `help format info` + cmdAction.info("## VIP list\n" + list) + return + } +} + +// onRequest is called when another script sends a request to this script. +export function onRequest(addr: string, request: Request): void { + if (request.topic == "isVip") { + // Parse the data passed as arguments. It should be the charId. + const charId = request.parseData() + // If the charId exists in the store, the character is a VIP. + const isVip = Store.getString(charId) != null + // Send a response to the request. It must be JSON encoded. + request.reply(JSON.stringify(isVip)) + } +} diff --git a/lib/env.ts b/lib/env.ts index 98da82a..f44bda5 100644 --- a/lib/env.ts +++ b/lib/env.ts @@ -1,3 +1,4 @@ + // @ts-nocheck export declare namespace Room { @@ -77,6 +78,9 @@ export declare namespace Script { @external("env", "script.getChar") export function getChar(charId: string): string | null + + @external("env", "script.request") + export function request(addr: string, topic: string, data: string | null): T } export declare namespace Store { @@ -134,3 +138,11 @@ export declare namespace CmdAction { @external("env", "cmdAction.useExit") export function useExit(actionId: i32, exitId: string): void } + +export declare namespace RequestAction { + @external("env", "requestAction.reply") + export function reply(actionId: i32, result: string | null): void + + @external("env", "requestAction.error") + export function error(actionId: i32, msg: string): void +} diff --git a/lib/host.ts b/lib/host.ts index be35d6b..cea687c 100644 --- a/lib/host.ts +++ b/lib/host.ts @@ -24,8 +24,10 @@ * [intercom_inside.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/intercom_inside.ts) | An intercom script allowing communication with another room running the [intercom_outside.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/intercom_outside.ts) script. * [intercom_outside.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/intercom_outside.ts) | An intercom script allowing communication with another room running the [intercom_inside.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/intercom_inside.ts) script. * [lock_inside.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/lock_inside.ts) | A script that locks a door preventing others from using an exit in the room running the [lock_outside.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/lock_outside.ts) script. - * [lock_outside.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/lock_outside.ts) | A script that prevents characters from using an exit locked by the script running the [lock_inside.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/lock_inside.ts) script. + * [lock_outside.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/lock_outside.ts) | A script that prevents characters from using an exit locked by the [lock_inside.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/lock_inside.ts) script. * [secret_exit.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/secret_exit.ts) | A script that reveals a secret passage when the password "tapeworm" is spoken. + * [vip_list.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/vip_list.ts) | A script that manages a list of VIP characters, requested by another room running the [vip_guard.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/vip_guard.ts) script. + * [vip_guard.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/vip_guard.ts) | A script that prevents characters from using an exit unless they are listed as VIP character by the [vip_list.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/vip_list.ts) script. * * # Entry points * @@ -48,6 +50,8 @@ * with delay), will be removed, and [onActivate](#onactivate) will be called * again on the new script version. * + * ### Examples + * * ```ts * // Send a describe to the room and log a message to the console on activation. * export function onActivate(): void { @@ -59,14 +63,22 @@ * ## onRoomEvent * * _onRoomEvent_ is called when an event occurs in the room, such as a _say_, - * _arrive_, or _sleep_. It requires that {@link Room.listen} has been called - * earlier, usually in the [onActivate](#onactivate) function. + * _arrive_, or _sleep_. {@link Room.listen} must have been called earlier to + * start listening to room events, usually in the [onActivate](#onactivate) + * function. + * + * ### Parameters + * + * * `addr` _(string)_: Address of this script instance receiving the event. + * * `ev` _(string)_: Event encoded as a json string. + * + * ### Examples * * ```ts * // Check the event type and decode the event. * export function onRoomEvent( - * addr: string, // Address of this script instance receiving the event. - * ev: string, // Event encoded as a json string. + * addr: string, + * ev: string, * ): void { * const eventType = Event.getType(ev); * if (eventType == 'say') { @@ -79,16 +91,27 @@ * ## onMessage * * _onMessage_ is called when another script sends a message to this script, - * using {@link Script.post}. It requires that {@link Script.listen} has been - * called earlier, usually in the [onActivate](#onactivate) function. + * using {@link Script.post}. {@link Script.listen} must have been called + * earlier to start listening to messages, usually in the + * [onActivate](#onactivate) function. + * + * ### Parameters + * + * * `addr` _(string)_: Address of this script instance receiving the message. + * * `topic` _(string)_: Topic of the message. Determined by the sender. + * * `data` _(string | null)_: JSON encoded data of the message or null. + * Determined by the sender. + * * `sender` _(string)_: Address of the sending script instance. + * + * ### Examples * * ```ts * // Receive a message from another script to change room profile * export function onMessage( - * addr: string, // Address of this script instance receiving the message. - * topic: string, // Topic of the message. Determined by the sender. - * data: string | null, // JSON encoded data of the message or null. Determined by the sender. - * sender: string, // Address of the sending script instance. + * addr: string, + * topic: string, + * data: string | null, + * sender: string, * ): void { * if (topic == "changeProfile") { * Room.setProfile(JSON.parse(data)) @@ -99,17 +122,28 @@ * ## onCharEvent * * _onCharEvent_ is called when a character enters a room, leaves a room, or - * changes any of its properties while inside the room. It requires that - * {@link Room.listenCharEvent} has been called earlier, usually in the - * [onActivate](#onactivate) function. + * changes any of its properties while inside the room. + * {@link Room.listenCharEvent} must have been called earlier to start listening + * to character events, usually in the [onActivate](#onactivate) function. + * + * ### Parameters + * + * * `addr` _(string)_: Address of this script instance receiving the event. + * * `charId` _(string)_: ID of character. + * * `after` _(string | null)_: Character state after the event encoded as a + * json string, or null if the character left the room. + * * `before` _(string | null)_: Character state before the event encoded as a + * json string, or null if the character entered the room. + * + * ### Examples * * ```ts * // Output to log when a character arrives or leaves * export function onCharEvent( - * addr: string, // Address of this script instance receiving the event. - * charId: string, // ID of character. - * after: string | null, // Character state after the event encoded as a json string, or null if the character left the room. - * before: string | null, // Character state before the event encoded as a json string, or null if the character entered the room. + * addr: string, + * charId: string, + * after: string | null, + * before: string | null, * ): void { * if (after == null && before != null) { * // If after is null, the character left @@ -126,18 +160,26 @@ * * ## onExitUse * - * _onExitUse_ is called when a character tries to use an exit. It requires that - * {@link Room.listenExit} has been called earlier, usually in the - * [onActivate](#onactivate) function. The script should call either - * {@link ExitAction.cancel} or {@link ExitAction.useExit} to determine what - * should happen. If neither method is called, the action will timeout after 1 - * second, automatically canceling the exit use with a default message. + * _onExitUse_ is called when a character tries to use an exit. + * {@link Room.listenExit} must have been called earlier to start listening to + * exit use, usually in the [onActivate](#onactivate) function. The script + * should call either {@link ExitAction.cancel} or {@link ExitAction.useExit} to + * determine what should happen. If neither method is called, the action will + * timeout after 1 second, automatically canceling the exit use with a default + * message. + * + * ### Parameters + * + * * `addr` _(string)_: Address of this script instance receiving the event. + * * `cmdAction` _({@link ExitAction})_: Exit action object. + * + * ### Examples * * ```ts * // Prevent anyone from using an exit * export function onExitUse( - * addr: string, // Address of this script instance receiving the event. - * exitAction: ExitAction, // Exit action object. + * addr: string, + * exitAction: ExitAction, * ): void { * exitAction.cancel("The door seems to be locked."); * } @@ -145,13 +187,20 @@ * * ## onCommand * - * _onCommand_ is called when a character uses a custom command. It requires - * that {@link Room.addCommand} has been called earlier to register the command, - * usually in the [onActivate](#onactivate) function. The script may send a - * response to the caller using either {@link CmdAction.info}, + * _onCommand_ is called when a character uses a custom command. + * {@link Room.addCommand} must have been called earlier to register the + * command, usually in the [onActivate](#onactivate) function. The script may + * send a response to the caller using either {@link CmdAction.info}, * {@link CmdAction.error}, or {@link CmdAction.useExit}, but it is not * required. The response must be sent within 1 second from the call. * + * ### Parameters + * + * * `addr` _(string)_: Address of this script instance receiving the action. + * * `cmdAction` _({@link CmdAction})_: Command action object. + * + * ### Examples + * * ```ts * // Adding a ping command on activation * export function onActivate(): void { @@ -167,6 +216,64 @@ * } * ``` * + * ## onRequest + * + * _onRequest_ is called when another script sends a request to this script, + * using {@link Script.request}. {@link Script.listen} must have been called + * earlier to start listening to requests, usually in the + * [onActivate](#onactivate) function. + * + * ### Parameters + * + * * `addr` _(string)_: Address of this script instance receiving the request. + * * `request` _({@link Request})_: Request object. + * + * ### Examples + * + * ```ts + * // Receive a request from another script and send a response. + * export function onRequest( + * addr: string, + * request: Request, + * ): void { + * if (request.topic == "getValue") { + * // Parse any data passed as arguments. + * const key = request.parseData() + * const value = Store.getString(key) + * // Send a response to the request + * request.reply(value) + * } + * } + * ``` + * + * ## onResponse + * + * _onResponse_ is called when another script sends a response to a request by + * calling {@link Request.reply}. + * + * ### Parameters + * + * * `addr` _(string)_: Address of the script instance receiving the response. + * * `response` _({@link Response})_: Response object. + * + * ### Examples + * + * ```ts + * // Receive a response to an request + * export function onResponse( + * addr: string, + * response: Response, + * ): void { + * response obn + * // Parse any data passed as arguments. + * const key = request.ParseData() + * const value = Store.getString(key); + * // Send a response to the request + * request.reply(value) + * } + * } + * ``` + * * @packageDocumentation */ @@ -178,6 +285,7 @@ import { Iterator as iterator_binding, ExitAction as exitaction_binding, CmdAction as cmdaction_binding, + RequestAction as requestaction_binding, } from "./env"; import { JSON } from 'json-as' export { JSON }; @@ -248,12 +356,55 @@ function keyToBuffer(key: T): ArrayBuffer { return key; } +/** + * CmdAction is a command action triggered by a character. + */ +@json +export class CmdAction { + /** Action ID */ + actionId: i32 = 0; + /** Character performing the action */ + char: Event.Char = new Event.Char(); + /** Command keyword */ + keyword: string = ""; + /** Command data in JSON format. */ + data: string = ""; + + /** + * Responds to the command action with an info message. + * @param msg Info message. It may be formatted with info formatting and span multiple paragraphs. + */ + info(msg: string): void { + cmdaction_binding.info(this.actionId, msg); + } + + /** + * Responds to the command action with an error message. + * @param msg Error message. It may be formatted and span multiple paragraphs. + */ + error(msg: string): void { + cmdaction_binding.error(this.actionId, msg); + } + + /** + * Responds to the command action by making the character use an exit. + * + * The exit may be hidden or inactive. May not be used in combination with + * info or error. + * @param exitId Exit ID. + */ + useExit(exitId: ID): void { + cmdaction_binding.useExit(this.actionId, exitId); + } +} + /** * ExitAction is an action representing an intercepted use of an exit. * * It is passed to [onExitUse](#onexituse) entry point when a character tries to * use an exit that is being listen to with {@link Room.listenExit}. */ +@json export class ExitAction { /** Action ID */ actionId: i32 = 0; @@ -285,43 +436,68 @@ export class ExitAction { } /** - * CmdAction is a command action triggered by a character. + * Request is a request sent from another script. */ -export class CmdAction { +@json +export class Request { /** Action ID */ actionId: i32 = 0; - /** Character performing the action */ - char: Event.Char = new Event.Char(); - /** Command keyword */ - keyword: string = ""; - /** Command data in JSON format. */ + /** Request topic */ + topic: string = ""; + /** Request data encoded as JSON. */ data: string = ""; + /** Request sender address. */ + sender: string = ""; /** - * Responds to the command action with an info message. - * @param msg Info message. + * Parses the data into a value of type T. */ - info(msg: string): void { - cmdaction_binding.info(this.actionId, msg); + parseData(): T { + return JSON.parse(this.data); } /** - * Responds to the command action with an error message. + * Responds to the request with a reply containing JSON encoded result. + * @param result Reply data encoded as JSON. + */ + reply(result: string | null = null): void { + requestaction_binding.reply(this.actionId, result); + } + + /** + * Responds to the request with an error message. * @param msg Error message. */ error(msg: string): void { - cmdaction_binding.error(this.actionId, msg); + requestaction_binding.error(this.actionId, msg); + } +} + +/** + * Response is a response to a request sent by the script. + */ +export class Response { + /** Result encoded as JSON. */ + result: string | null = null; + /** Error string or null on no error. */ + error: string | null = null; + + /** + * Returns true if it is an error response by checking that the error + * property is not a null value. + */ + isError(): boolean { + return this.error != null; } /** - * Responds to the command action by making the character use an exit. - * - * The exit may be hidden or inactive. May not be used in combination with - * info or error. - * @param exitId Exit ID. + * Parses the result into a value of type T. */ - useExit(exitId: ID): void { - cmdaction_binding.useExit(this.actionId, exitId); + parseResult(): T { + if (this.result == null) { + abort("no result to parse") + } + return JSON.parse(this.result!); } } @@ -1367,12 +1543,14 @@ export namespace Script { } /** - * Starts listening for posted messages from any of the given `addr` - * addresses. If an address is a non-instance room, it will also listen to - * posted messages from any instance of that room. + * Starts listening for posted messages and requests, sent with + * {@link Script.post} and {@link Script.request}, from any of the given + * `addr` addresses. If an address is a non-instance room, it will also + * listen to posted messages from any instance of that room. * - * If no `addr` is provided, the script will listen to posts from _any_ - * source, including scripts and bots controlled by other players. + * If no `addr` is provided, the script will listen to posts and requests + * from _any_ source, including scripts and bots controlled by other + * players. * * Posts from the current script does not require listening. A script can * always post to itself. @@ -1406,7 +1584,9 @@ export namespace Script { } /** - * Posts a message to another script with the address `addr`. + * Posts a message to another script with the address `addr`. The receiving + * script will get the message through the [onMessage](#onmessage) entry + * point. * * To get the address of a room script, use the `roomscript` command. For * more info, type: @@ -1440,6 +1620,27 @@ export namespace Script { return script_binding.cancelPost(scheduleId); } + /** + * Sends a request to another script with the address `addr`. The receiving + * script will get the request through the [onRequest](#onrequest) entry + * point. Once replied, the requesting script will get the response together + * with provided context through the [onResponse](#onresponse) entry point + * + * To get the address of a room script, use the `roomscript` command. For + * more info, type: + * ``` + * help roomscript + * ``` + * + * @param addr - Address of target script. If addr is "#", it will be a post to the current script instance. + * @param topic - Message topic. May be any kind of string. + * @param data - Additional data to be sent with the request. Must be valid JSON. + * @returns Response to the request. + */ + export function request(addr: string, topic: string, data: string | null = null): Response { + return script_binding.request(addr, topic, data); + } + /** * Gets info on an existing character. * diff --git a/lib/types/host/index.d.ts b/lib/types/host/index.d.ts index 21fca03..dae90d3 100644 --- a/lib/types/host/index.d.ts +++ b/lib/types/host/index.d.ts @@ -24,8 +24,10 @@ * [intercom_inside.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/intercom_inside.ts) | An intercom script allowing communication with another room running the [intercom_outside.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/intercom_outside.ts) script. * [intercom_outside.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/intercom_outside.ts) | An intercom script allowing communication with another room running the [intercom_inside.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/intercom_inside.ts) script. * [lock_inside.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/lock_inside.ts) | A script that locks a door preventing others from using an exit in the room running the [lock_outside.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/lock_outside.ts) script. - * [lock_outside.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/lock_outside.ts) | A script that prevents characters from using an exit locked by the script running the [lock_inside.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/lock_inside.ts) script. + * [lock_outside.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/lock_outside.ts) | A script that prevents characters from using an exit locked by the [lock_inside.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/lock_inside.ts) script. * [secret_exit.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/secret_exit.ts) | A script that reveals a secret passage when the password "tapeworm" is spoken. + * [vip_list.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/vip_list.ts) | A script that manages a list of VIP characters, requested by another room running the [vip_guard.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/vip_guard.ts) script. + * [vip_guard.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/vip_guard.ts) | A script that prevents characters from using an exit unless they are listed as VIP character by the [vip_list.ts](https://github.com/mucklet/mucklet-script/blob/master/examples/vip_list.ts) script. * * # Entry points * @@ -48,6 +50,8 @@ * with delay), will be removed, and [onActivate](#onactivate) will be called * again on the new script version. * + * ### Examples + * * ```ts * // Send a describe to the room and log a message to the console on activation. * export function onActivate(): void { @@ -59,14 +63,22 @@ * ## onRoomEvent * * _onRoomEvent_ is called when an event occurs in the room, such as a _say_, - * _arrive_, or _sleep_. It requires that {@link Room.listen} has been called - * earlier, usually in the [onActivate](#onactivate) function. + * _arrive_, or _sleep_. {@link Room.listen} must have been called earlier to + * start listening to room events, usually in the [onActivate](#onactivate) + * function. + * + * ### Parameters + * + * * `addr` _(string)_: Address of this script instance receiving the event. + * * `ev` _(string)_: Event encoded as a json string. + * + * ### Examples * * ```ts * // Check the event type and decode the event. * export function onRoomEvent( - * addr: string, // Address of this script instance receiving the event. - * ev: string, // Event encoded as a json string. + * addr: string, + * ev: string, * ): void { * const eventType = Event.getType(ev); * if (eventType == 'say') { @@ -79,16 +91,27 @@ * ## onMessage * * _onMessage_ is called when another script sends a message to this script, - * using {@link Script.post}. It requires that {@link Script.listen} has been - * called earlier, usually in the [onActivate](#onactivate) function. + * using {@link Script.post}. {@link Script.listen} must have been called + * earlier to start listening to messages, usually in the + * [onActivate](#onactivate) function. + * + * ### Parameters + * + * * `addr` _(string)_: Address of this script instance receiving the message. + * * `topic` _(string)_: Topic of the message. Determined by the sender. + * * `data` _(string | null)_: JSON encoded data of the message or null. + * Determined by the sender. + * * `sender` _(string)_: Address of the sending script instance. + * + * ### Examples * * ```ts * // Receive a message from another script to change room profile * export function onMessage( - * addr: string, // Address of this script instance receiving the message. - * topic: string, // Topic of the message. Determined by the sender. - * data: string | null, // JSON encoded data of the message or null. Determined by the sender. - * sender: string, // Address of the sending script instance. + * addr: string, + * topic: string, + * data: string | null, + * sender: string, * ): void { * if (topic == "changeProfile") { * Room.setProfile(JSON.parse(data)) @@ -99,17 +122,28 @@ * ## onCharEvent * * _onCharEvent_ is called when a character enters a room, leaves a room, or - * changes any of its properties while inside the room. It requires that - * {@link Room.listenCharEvent} has been called earlier, usually in the - * [onActivate](#onactivate) function. + * changes any of its properties while inside the room. + * {@link Room.listenCharEvent} must have been called earlier to start listening + * to character events, usually in the [onActivate](#onactivate) function. + * + * ### Parameters + * + * * `addr` _(string)_: Address of this script instance receiving the event. + * * `charId` _(string)_: ID of character. + * * `after` _(string | null)_: Character state after the event encoded as a + * json string, or null if the character left the room. + * * `before` _(string | null)_: Character state before the event encoded as a + * json string, or null if the character entered the room. + * + * ### Examples * * ```ts * // Output to log when a character arrives or leaves * export function onCharEvent( - * addr: string, // Address of this script instance receiving the event. - * charId: string, // ID of character. - * after: string | null, // Character state after the event encoded as a json string, or null if the character left the room. - * before: string | null, // Character state before the event encoded as a json string, or null if the character entered the room. + * addr: string, + * charId: string, + * after: string | null, + * before: string | null, * ): void { * if (after == null && before != null) { * // If after is null, the character left @@ -126,18 +160,26 @@ * * ## onExitUse * - * _onExitUse_ is called when a character tries to use an exit. It requires that - * {@link Room.listenExit} has been called earlier, usually in the - * [onActivate](#onactivate) function. The script should call either - * {@link ExitAction.cancel} or {@link ExitAction.useExit} to determine what - * should happen. If neither method is called, the action will timeout after 1 - * second, automatically canceling the exit use with a default message. + * _onExitUse_ is called when a character tries to use an exit. + * {@link Room.listenExit} must have been called earlier to start listening to + * exit use, usually in the [onActivate](#onactivate) function. The script + * should call either {@link ExitAction.cancel} or {@link ExitAction.useExit} to + * determine what should happen. If neither method is called, the action will + * timeout after 1 second, automatically canceling the exit use with a default + * message. + * + * ### Parameters + * + * * `addr` _(string)_: Address of this script instance receiving the event. + * * `cmdAction` _({@link ExitAction})_: Exit action object. + * + * ### Examples * * ```ts * // Prevent anyone from using an exit * export function onExitUse( - * addr: string, // Address of this script instance receiving the event. - * exitAction: ExitAction, // Exit action object. + * addr: string, + * exitAction: ExitAction, * ): void { * exitAction.cancel("The door seems to be locked."); * } @@ -145,13 +187,20 @@ * * ## onCommand * - * _onCommand_ is called when a character uses a custom command. It requires - * that {@link Room.addCommand} has been called earlier to register the command, - * usually in the [onActivate](#onactivate) function. The script may send a - * response to the caller using either {@link CmdAction.info}, + * _onCommand_ is called when a character uses a custom command. + * {@link Room.addCommand} must have been called earlier to register the + * command, usually in the [onActivate](#onactivate) function. The script may + * send a response to the caller using either {@link CmdAction.info}, * {@link CmdAction.error}, or {@link CmdAction.useExit}, but it is not * required. The response must be sent within 1 second from the call. * + * ### Parameters + * + * * `addr` _(string)_: Address of this script instance receiving the action. + * * `cmdAction` _({@link CmdAction})_: Command action object. + * + * ### Examples + * * ```ts * // Adding a ping command on activation * export function onActivate(): void { @@ -167,6 +216,64 @@ * } * ``` * + * ## onRequest + * + * _onRequest_ is called when another script sends a request to this script, + * using {@link Script.request}. {@link Script.listen} must have been called + * earlier to start listening to requests, usually in the + * [onActivate](#onactivate) function. + * + * ### Parameters + * + * * `addr` _(string)_: Address of this script instance receiving the request. + * * `request` _({@link Request})_: Request object. + * + * ### Examples + * + * ```ts + * // Receive a request from another script and send a response. + * export function onRequest( + * addr: string, + * request: Request, + * ): void { + * if (request.topic == "getValue") { + * // Parse any data passed as arguments. + * const key = request.parseData() + * const value = Store.getString(key) + * // Send a response to the request + * request.reply(value) + * } + * } + * ``` + * + * ## onResponse + * + * _onResponse_ is called when another script sends a response to a request by + * calling {@link Request.reply}. + * + * ### Parameters + * + * * `addr` _(string)_: Address of the script instance receiving the response. + * * `response` _({@link Response})_: Response object. + * + * ### Examples + * + * ```ts + * // Receive a response to an request + * export function onResponse( + * addr: string, + * response: Response, + * ): void { + * response obn + * // Parse any data passed as arguments. + * const key = request.ParseData() + * const value = Store.getString(key); + * // Send a response to the request + * request.reply(value) + * } + * } + * ``` + * * @packageDocumentation */ /** ID for in game entities such as characters, rooms, and areas. */ @@ -222,6 +329,37 @@ declare const enum ExitIcon { In = 11, Out = 12 } +/** + * CmdAction is a command action triggered by a character. + */ +declare class CmdAction { + /** Action ID */ + actionId: i32; + /** Character performing the action */ + char: Event.Char; + /** Command keyword */ + keyword: string; + /** Command data in JSON format. */ + data: string; + /** + * Responds to the command action with an info message. + * @param msg Info message. It may be formatted with info formatting and span multiple paragraphs. + */ + info(msg: string): void; + /** + * Responds to the command action with an error message. + * @param msg Error message. It may be formatted and span multiple paragraphs. + */ + error(msg: string): void; + /** + * Responds to the command action by making the character use an exit. + * + * The exit may be hidden or inactive. May not be used in combination with + * info or error. + * @param exitId Exit ID. + */ + useExit(exitId: ID): void; +} /** * ExitAction is an action representing an intercepted use of an exit. * @@ -252,35 +390,49 @@ declare class ExitAction { cancel(msg?: string | null): void; } /** - * CmdAction is a command action triggered by a character. + * Request is a request sent from another script. */ -declare class CmdAction { +declare class Request { /** Action ID */ actionId: i32; - /** Character performing the action */ - char: Event.Char; - /** Command keyword */ - keyword: string; - /** Command data in JSON format. */ + /** Request topic */ + topic: string; + /** Request data encoded as JSON. */ data: string; + /** Request sender address. */ + sender: string; /** - * Responds to the command action with an info message. - * @param msg Info message. + * Parses the data into a value of type T. */ - info(msg: string): void; + parseData(): T; /** - * Responds to the command action with an error message. + * Responds to the request with a reply containing JSON encoded result. + * @param result Reply data encoded as JSON. + */ + reply(result?: string | null): void; + /** + * Responds to the request with an error message. * @param msg Error message. */ error(msg: string): void; +} +/** + * Response is a response to a request sent by the script. + */ +declare class Response { + /** Result encoded as JSON. */ + result: string | null; + /** Error string or null on no error. */ + error: string | null; /** - * Responds to the command action by making the character use an exit. - * - * The exit may be hidden or inactive. May not be used in combination with - * info or error. - * @param exitId Exit ID. + * Returns true if it is an error response by checking that the error + * property is not a null value. */ - useExit(exitId: ID): void; + isError(): boolean; + /** + * Parses the result into a value of type T. + */ + parseResult(): T; } /** * BaseIterator is an iterator over items with an ID. @@ -950,12 +1102,14 @@ declare namespace Script { rp: RPState; } /** - * Starts listening for posted messages from any of the given `addr` - * addresses. If an address is a non-instance room, it will also listen to - * posted messages from any instance of that room. + * Starts listening for posted messages and requests, sent with + * {@link Script.post} and {@link Script.request}, from any of the given + * `addr` addresses. If an address is a non-instance room, it will also + * listen to posted messages from any instance of that room. * - * If no `addr` is provided, the script will listen to posts from _any_ - * source, including scripts and bots controlled by other players. + * If no `addr` is provided, the script will listen to posts and requests + * from _any_ source, including scripts and bots controlled by other + * players. * * Posts from the current script does not require listening. A script can * always post to itself. @@ -983,7 +1137,9 @@ declare namespace Script { */ function unlisten(addrs?: string[] | null): void; /** - * Posts a message to another script with the address `addr`. + * Posts a message to another script with the address `addr`. The receiving + * script will get the message through the [onMessage](#onmessage) entry + * point. * * To get the address of a room script, use the `roomscript` command. For * more info, type: @@ -1008,6 +1164,24 @@ declare namespace Script { * @returns True if the post was successfully canceled, otherwise false. */ function cancelPost(scheduleId: ID | null): boolean; + /** + * Sends a request to another script with the address `addr`. The receiving + * script will get the request through the [onRequest](#onrequest) entry + * point. Once replied, the requesting script will get the response together + * with provided context through the [onResponse](#onresponse) entry point + * + * To get the address of a room script, use the `roomscript` command. For + * more info, type: + * ``` + * help roomscript + * ``` + * + * @param addr - Address of target script. If addr is "#", it will be a post to the current script instance. + * @param topic - Message topic. May be any kind of string. + * @param data - Additional data to be sent with the request. Must be valid JSON. + * @returns Response to the request. + */ + function request(addr: string, topic: string, data?: string | null): Response; /** * Gets info on an existing character. * diff --git a/package-lock.json b/package-lock.json index 5cac5d5..253fc17 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "assemblyscript": "^0.28.2", "isomorphic-ws": "^5.0.0", - "json-as": "github:anisus/json-as#863f37b8c6666e79c219f9e36b01efb5a49a9a19", + "json-as": "1.1.21", "resclient": "^2.5.0", "tinyargs": "^0.1.4", "visitor-as": "^0.11.4" @@ -1085,9 +1085,9 @@ } }, "node_modules/json-as": { - "version": "1.1.17", - "resolved": "git+ssh://git@github.com/anisus/json-as.git#863f37b8c6666e79c219f9e36b01efb5a49a9a19", - "integrity": "sha512-pIdamF7Vsr0sSPwIJqyy0EKtfab+1hwtVynO4jFqQf1Mt6Y1U9w8vxocGODyfJk8wThQDOWNlh3xkU/RlVlxKg==" + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/json-as/-/json-as-1.1.21.tgz", + "integrity": "sha512-4WlxVqLY6sZHqGyFiKE+ulmbnxhiBlOPXb2KELjNpj1LXh0ZYhaPJq7Ml2Jnt2E5Zmn6AXPmyerdkR0w9GbXRg==" }, "node_modules/json-buffer": { "version": "3.0.1", diff --git a/package.json b/package.json index d2d69ba..c55448b 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "dependencies": { "assemblyscript": "^0.28.2", "isomorphic-ws": "^5.0.0", - "json-as": "github:anisus/json-as#863f37b8c6666e79c219f9e36b01efb5a49a9a19", + "json-as": "1.1.21", "resclient": "^2.5.0", "tinyargs": "^0.1.4", "visitor-as": "^0.11.4"