Scripts
Behaviour is written in Kalem, Caria's language, in .kalem files
of the project. A script is attached as a component to a package, a part or the world.
Writing
New › Sakin › Kalem Script makes a script from its label: "Door bell" becomes
door-bell.kalem, script DoorBell. The editor carries Kalem's language server and starts one
per project; it works on unsaved text and never compiles (compiling happens when Play starts).
- Errors as you type, on their line: syntax, types and effects. The messages are in Turkish
today ("
ifbloğu kapanmadı:endeksik": theifblock is not closed,endis missing). - Colours by meaning: a property (read-only in code, set in the Inspector), memory, a contract field, a state, timer or event, a function, the library, a parameter and a local each have their own colour, mapped onto the colour scheme's known keys.
- Completion: host types after
extends, triggers and events afteron, payload fields inon event(, types after:, states aftergoto, timers aftertimer, a field's parts afterfield., the functions that take a value's type after its dot (andr g b aon a colour), the words that start a declaration or a statement, the locals in view, the script's names and the natives open to its side. Code inside{…}in a string is coloured and completed as code. - On hover: a declaration's line and its
///description, a local's type, a native's signature and effect, a host type's and an event's description from the catalog. - Navigation: go to definition (a started timer goes to its first
start timer), highlight and find usages, the Structure view, folding.
The catalog the server checks against is the editor's host types and calendar
(kalem/hosts.json) and the project's events; when an event document is
added, changed or removed, open scripts are checked again.
Components
A component is kept in the components list of a package's or part's object.json, or of the
.world: {id, script: "kalem/<file name>", enabled, values}. values keeps only the properties
that differ from the script's defaults; a property renamed with was finds its value under the
old name.
In the Inspector and the world's form, every component is a card:
- its enabled box, the script's label, ↑ ↓ (the order is the order they run in) and remove;
- below, the script's name (a click opens the
.kalem), its host type and category; its error count when it has errors; - the script's properties by group, with their
///descriptions (made from the script's manifest;hiddenones do not show, anintstays a whole number); - at the bottom, what the script reacts to ("On ready · timer opening · city.powerChanged") and the signal it is bound to.
The card compares the fields the script reads and writes with the holder's (Fields): a missing field, another type (bool ↔ Yes / No, int ↔ whole number, float ↔ number, string, time), or a field another component writes too is written in red, and Add the fields it uses adds what is missing in one command. When the language server did not answer for a script, its card has Try again. Cards follow a script shortly after it changes, is added or is removed.
Add Component
Add Component offers, in the selector, the project's
scripts that can go on the selection, by their host type: World on the world, Building on a
building, Character on a character, Part on a part or an object, VisualEffect and Light on
a part (Host types).
- Categories are the scripts'
category; the search looks in the name, description, file path, host type, properties and events. - The details show the file path (copyable), where it runs, its properties, the events it reacts to, the fields it reads and writes, and its errors.
- A script that cannot be added still shows, with why: one already on the selection is "Added"; one without a header, or that could not be read, is under "Not ready"; two scripts with the same file name (the id is the file name) both are.
Signals
A client script with an input has a Signal row on its card: Choose… offers the fields of
the right type (the package's, its parts' and the project's first world's, and "Not bound"), and
the choice is written on the component as input: {holder, field} (the holder is a part's id,
package or world). An unbound input keeps its default; a field that is gone or has another type
is written in red (Visual effects).