Architecture
Architecture
This guide covers the engine architecture in detail, describing entities and showing major event flows.
Contents
Actors
The service controller player and non-player characters. Unrelated to the actor model.
Behavior
Behavioral actors are controlled by the computer - NPCs.
Inventory
Actors can carry items in their inventory. There is currently no inventory limit.
Equipment Slots
Actors can equip items from their inventory into specific slots. The weapon-*
slots are used to attack, for example.
Only items with a corresponding slot can be equipped, limited what some actors can use (animals may have slots for claws
and teeth instead of hands).
Config
Configuring the engine.
Locale Config
Logger Config
Service Config
Commands
The player’s input lines are parsed into commands for the actor to execute. NPC AI generates input commands directly.
Command Tokenization
Commands are built by splitting input on whitespace, removing articles (a, an, the, etc) and other filler words, and assuming the verb and target are in the correct order. Some validation is done when invoking commands, but the parsing is very simple.
Common Commands
There are common verbs built into the engine for actions such as:
drop
an itemhit
an enemylook
at an entitymove
to another roomtake
an itemuse
an itemwait
the turn
Meta Commands
There are some meta commands that are handled by the state service, rather than actor scripts.
create
- create a new world from the template
debug
- print the world state to output
graph
- print the world state to path in graphviz format
help
- list common and meta commands
load
- load the world state from a path
save
- save the world state to a path
quit
World Commands
World entities may define their own contextual verbs, which can be invoked normally through input.
Entities
Actor Entity
TODO: explain actors
Item Entity
TODO: explain items
Portal Entity
TODO: explain portals
Room Entity
TODO: explain rooms
Events
The entire engine is event-driven, with intentionally little direct coupling between services. Some operations are too trivial to bus, like translating a string, but any significant change to game state should be sent as an event.
Event Flow: Creating a New World
When the player sends a `create` command, generate a new world and inform the actor service, which will automatically join the loaded world.
![flowchart with actor joining local world](/textual-engine/docs/events-world-create.svg)Event Flow: Loading an Existing World
When the player sends a `load` command, the path is passed on to the loader, which responds with the loaded state and triggers the auto-join sequence ([shown in the create event flow](#event-flow-creating-a-new-world)).
![flowchart with player input being processed locally](/textual-engine/docs/events-world-load.svg)Event Flow: Command with Local State
When the player submits a world command, it is parsed into commands and triggers a state step, processed locally.
![flowchart with player input being processed locally](/textual-engine/docs/events-command-local.svg)Event Flow: Command with Remote State
When the client is connected to a remote state service, with a corresponding remote actor on the server-side, the command flow is similar but extended. Notably, localization occurs on the client-side after output has been returned, one reason for having actor services on both sides.
![flowchart with player input being sent to remote server](/textual-engine/docs/events-command-remote.svg)Modules
Modules are dependency injection groups, binding a related set of services.
Browser Module
Provides:
browser-fetch-loader
browser-local-loader
browser-page-loader
browser-dom-render
Core Module
Binds:
LocalCounter
NodeEventBus
NextLocale
YamlParser
AleaRandom
LocalScript
ChainTemplate
WordTokenizer
Provides:
core-behavior-actor
core-player-actor
core-local-state
core-compromise-tokenizer
core-split-tokenizer
Node Module
Provides:
node-file-loader
node-fetch-loader
node-ink-render
node-line-render
Services
Please see the services doc for details on what each service does. The list is too long to include here.
Scripts
Events in the world are processed by scripts attached to the entity performing the action. Scripts may be invoked on a single target entity or broadcast to an entire room, and take a context with field for some (optional) primitive data.
Script Target (this
)
The entity on which the script is being invoked. Always a world entity.
Script Context
A context is prepared whenever a script is invoked, with the target (entity upon which the script has been invoked), any data that was provided, and some helpers that provide safe ways to mutate the game state.
Scope Data
The context contains a data field, suitable for passing in non-nested numbers and strings.
TODO: support custom template data for scripts
Signal Scripts
Signals are named events on an entity, linked to (named) scripts.
Verb Scripts
Verbs are custom commands, which invoke a slot with some additional data.