Code editor setup

The engine writes its whole scripting API into every project as declarations: for the Lua language server in a Lua project, and for TypeScript in a TypeScript one (see TypeScript below). With them, your code editor completes names as you type, shows what a function takes and gives back, and shows its description when you hover.

What you need

A code editor with the Lua language server:

EditorHow
VS CodeInstall the "Lua" extension by sumneko
ZedLua support is built in. It downloads the server the first time you open a Lua file
NeovimSet up lua_ls with your LSP plugin

Then open the project's folder (the one with the .cairnproject file) in the editor, not a single script.

What the engine writes

When the editor opens a project it makes two things in the project's folder:

FileWhat it is
.cairn/api.d.luaThe declarations. Written again whenever the engine's API has changed
.luarc.jsonSettings that point the language server at them. Made once, then left alone: it is yours to change

Both are left out of an exported game, and neither shows in the Assets panel.

Commit .luarc.json. Leave .cairn/ out of version control: it is written again from the engine each time.

Tell the editor what a script is

Start a script with a class line:

---@class Player : Script
local Player = {}

Now the editor knows self.Entity is an entity inside the script's functions, and can complete from there: self.Entity.Rigidbody. lists a rigid body's fields.

New > Script in the Assets panel writes that line for you.

Naming your own values

The editor learns the values you keep in self from where you set them. For one it cannot work out, say what it is:

function Player:OnStart()
	---@type Entity
	self.Camera = Scene.Find("Main Camera")
	self.Controller = self.Entity.CharacterController
end

What it does not know

Values other scripts keep in their tables. Scene.Find("Game"):GetScript("Game") gives a plain table.

TypeScript

In a TypeScript project the editor writes .cairn/api.d.ts and a tsconfig.json in place of the Lua files. VS Code and Zed read them with nothing to install: open the project's folder and you get completion, hover text and red underlines for type errors. They are the same errors the editor reports when it compiles, because both read the same settings.

FileWhat it is
tsconfig.jsonYour settings. Made once, then yours. Add stricter checks here if you want them
.cairn/tsconfig.base.jsonThe settings the Lua depends on. Written again on every open, and they win over yours
.cairn/api.d.tsThe declarations, written again when the engine's API changed

DefineScript tells the editor what this is, so there is no class line to write. A value the script keeps is declared in its table, with a starting value, which also gives its type:

export = DefineScript({
	Fields: { Speed: 5 },

	// Set in OnStart. Until then it is an empty stand-in of the right type.
	Camera: {} as Entity,
	Jumps: 0,

	OnStart() {
		this.Camera = Scene.Find("Main Camera");
	},
});

A table or a list declared there is shared by every copy of the script until a copy sets its own, so set one in OnStart before changing it.