Lost is a framework for easy making Construct 3 addons using Deno (JavaScript runtime) that was created by lostinmind.
Here I've compiled some of the benefits from standard addon creation for Construct 3.
- โก๏ธ Using the powerful JavaScript Runtime Deno.
- โ Error detecting before installization of your Addon!
- ๐ Only Typescript and no Javascript for your addon
- E Typescript support for addon scripts!
- ๐ Fast compilation to .c3addon format!
- ๐งช Built-in addon testing using Developer Mode in Construct 3.
- ๐ No need to configure separately aces.json and en-US.json files for addon. All necessary properties for aces.json and en-US.json are defined together with the function implementation.
- ๐ There is no need to configure addon .js scripts/files. Lost automatically detects the addon scripts/files!
- ๐ Structured categorization of all addon Actions, Conditions, Expressions. Categories are separated files like MyCategory.ts.
- ๐ซ Possibility to mark all Actions, Conditions, Expressions in a category as Deprecated instead of having to configure each Action, Condition, Expression separately.
- โจ Additional tools to format the displayed text in Construct 3 itself by using built-in functions - formatting the text into a specific BBCode tag.
deno install --name lost jsr:@lost-c3/lib/cli --global -f -A
deno install --name lost jsr:@lost-c3/lib/cli --global -f -A lost create
lost create --plugin # Creates a bare-bones project for 'plugin' addon
deno install --name lost jsr:@lost-c3/lib@LAST_VERSION/cli --global -f -A
Plugin
addonlost create --plugin # Creates a bare-bones project for 'plugin' addon
โโโ Addon/ # Addon folder โ โโโ Categories/ # Categories folder โ โโโ Files/ # Addon files folder โ โโโ Scripts/ # Addon scripts folder โ โโโ Modules/ # Addon modules folder โ โโโ Types/ # Addon scripts folder โ โโโ global.d.ts # Declaration file for your purposes โ โโโ icon.svg # Your .svg OR .png addon icon โ โโโ Instance.ts # Addon Instance class โ โโโ Plugin.ts # Addon Plugin class โ โโโ Type.ts # Addon Type class โโโ Builds/ # Builds folder โ โโโ Source/ # Final Construct 3 addon folder โ โโโ ... โ โโโ AddonId_Version.c3addon # Final .c3addon file โโโ deno.json # deno.json file for Deno enviroment โโโ addon.ts # Main addon file โโโ lost.config.ts # Addon config file
Let's setup lost.config.ts
config file at first.
import type { LostConfig } from "jsr:@lost-c3/lib@"; const config: LostConfig = { /** * Set addon type */ type: 'plugin', /** * Set a boolean of whether the addon is deprecated or not. */ deprecated?: false, /** * A boolean indicating whether the addon supports Construct's worker mode, where the entire runtime is hosted in a Web Worker instead of the main thread. */ supportsWorkerMode?: false, /** * The minimum Construct version required to load your addon, e.g. "r399". */ minConstructVersion?: 'r416', /** * Pass false to prevent the addon from being bundled via the Bundle addons project property. */ canBeBundled?: false, /** * Pass true to set the plugin to be a single-global type. */ isSingleGlobal?: true, /** * An object name that will applied after plugin was installed/added to project. */ objectName: 'LostPluginName', addonId: 'Lost_MyAddon', addonName: 'Lost addon for Construct 3', addonDescription: 'Amazing addon made with Lost.', category: 'general', version: '1.0.0.0', author: 'lostinmind.', websiteUrl: `https://addon.com`, docsUrl: `https://docs.addon.com`, helpUrl: { EN: 'https://myaddon.com/help/en' } } export default config;
Let's setup addon.ts
file at second.
import { Plugin, Property } from 'jsr:@lost-c3/lib@3.0.0'; import config from "./lost.config.ts"; const Addon = new Plugin(config) Addon .addFilesToOutput() .setRuntimeScripts() .addRemoteScripts('https://cdn/index.js') /** @Properties */ .addPluginProperty('integer', 'Integer', { type: Property.Integer }) .addPluginProperty('float', 'Float', { type: Property.Float }) .addPluginProperty('percent', 'Percent', { type: Property.Percent }) .addPluginProperty('text', 'Text', { type: Property.Text }) .addPluginProperty('longText', 'Long Text', { type: Property.LongText }) .addPluginProperty('check', 'Check', { type: Property.Checkbox }) .addPluginProperty('font', 'Font', { type: Property.Font }) .addPluginProperty('combo', 'Combo', { type: Property.Combo, items: [['item1', 'item2']] }) .addPluginProperty('color', 'Color', { type: Property.Color, initialValue: [255, 210, 155] }) .createGroup('group', 'Awesome Group') .addPluginProperty('info', 'Info', { type: Property.Info, info: 'Lost' }) .addPluginProperty('link', 'Link', { type: Property.Link, callbackType: 'for-each-instance', callback: (inst) => { console.log('Link property for each instance'); } }) .addPluginProperty('link2', 'Link', { type: Property.Link, callbackType: 'once-for-type', callback: (type) => { console.log('Link property once for type'); } }) ; export default Addon;
To create category you should create new CategoryName.ts
file in path:
./Addon/Categories
folder. Then you can use code snippet from bare-bones
project !cc
to create default Category structure or copy-paste below
script.
import { Category, Action, Condition, Expression, addParam } from "jsr:@lost-c3/lib"; import type { Instance } from "../Instance.ts"; @Category('myCategory', 'Category Name', { isDeprecated: false, inDevelopment: false }) export default class MyCategory { /** @Actions */ /** @Conditions */ /** @Expressions */ }
[!INFO] isDeprecated property in options for category in @Category decorator deprecates all category Actions, Conditions, Expressions.
inDevelopment property in options for category in @Category decorator removes all category Actions, Conditions, Expressions from addon.
To create actions for your addon you should use @Action
method decorator
in your category class.
Example
import { Category, Action, Condition, Expression } from 'jsr:@lost-c3/lib'; import type { Instance } from '../Instance.ts'; /** * Setup your category settings here */ @Category('categoryId', 'Category Name') export default class MyCategory { @Action( /** * A string specifying a unique ID for the ACE. */ `doSomething`, /** * The name that appears in the action picker dialog. */ `Do something`, /** * The text that appears in the event sheet. * You can use simple BBCode tags like [b] and [i], and use {0}, {1} etc. as parameter placeholders. * For easy BBCode import functions from @lost-c3/lib --> Bold, Italic, Underline, Strikethrough, Code */ `Do something`, /** * A description of the action or condition, which appears as a tip at the top of the condition/action picker dialog. */ `Awesome description...`, { /** * Set to true to mark the action as asynchronous. */ isAsync: false, /** * Set to true to deprecate. */ isDeprecated: false, /* * Set to true to highlight. */ highlight: true, /** * Setup your parameters here. */ params: [] } ) doSomething() { console.log('Do something'); }; }
You can use build-in BBCode functions for fast and beautiful development.
To create conditions for your addon you should use @Condition
method
decorator in your category class.
Example
import { Category, Action, Condition, Expression } from 'jsr:@lost-c3/lib'; import type { Instance } from '../Instance.ts'; @Category('categoryId', 'Category Name') export default class MyCategory { @Condition( `onEvent`, `On event`, `On event`, 'Trigger when something done...', { /** * Specifies a trigger condition. */ isTrigger: true, /** * Allow the condition to be used in the same branch as a trigger. */ isCompatibleWithTriggers: false, /** * Specifies a fake trigger. */ isFakeTrigger: false, /** * Allow the condition to be inverted in the event sheet. */ isInvertible: false, /** * Display an icon in the event sheet to indicate the condition loops. */ isLooping: false, /** * Normally, the condition runtime method is executed once per picked instance. */ isStatic: false, isDeprecated: false, highlight: false, params: [] } ) onEvent(this: Instance) { return true }; }
You can use build-in BBCode functions for fast and beautiful development.
To create expressions for your addon you should use @Expression
decorator in
your category class.
Example
import { Category, Action, Condition, Expression } from 'jsr:@lost-c3/lib'; import type { Instance } from '../Instance.ts'; @Category('categoryId', 'Category Name') export default class MyCategory { @Expression( `getValue`, `GetValue`, `Returns some value`, { /** * "number" OR "string" OR "any". */ returnType: 'string', /** * Allow the user to enter any number of parameters beyond those defined. */ isVariadicParameters: false, isDeprecated: false, highlight: false, params: [] } ) getValue(this: Instance) { return 'value' }; }
You can use build-in BBCode functions for fast and beautiful development.
To setup parameters in your Action/Condition/Expression you should use 'params'
field when you creating on of the entity. Also you should use addParam()
method AND Param
enum that you can import from library.
List of available parameter types:
Type | Description |
---|---|
"Number" |
A number parameter. |
"String" |
A string parameter. |
"Any" |
Either a number or a string. |
"Boolean" |
A boolean parameter, displayed as a checkbox. |
"Combo" |
A dropdown list. |
"Cmp" |
A dropdown list with comparison options like "equal to", "less than" etc. |
"Object" |
An object picker. |
"ObjectName" |
A string parameter which is interpreted as an object name. |
"Layer" |
A string parameter which is interpreted as a layer name. |
"Layout" |
A dropdown list with every layout in the project. |
"Keyb" |
A keyboard key picker. |
"InstanceVar" |
A dropdown list with the non-boolean instance variables the object has. |
"InstanceVarBool" |
A dropdown list with the boolean instance variables the object has. |
"EventVar" |
A dropdown list with non-boolean event variables in scope. |
"EventVarBool" |
A dropdown list with boolean event variables in scope. |
"Animation" |
A string parameter which is interpreted as an animation name in the object. |
"ObjInstanceVar" |
A dropdown list with non-boolean instance variables available in a prior "object" parameter. |
Example
import { Category, Action, Condition, Expression, addParam, Param } from 'jsr:@lost-c3/lib'; import { bold } from 'jsr:@lost-c3/lib/misc'; import type { Instance } from '../Instance.ts'; @Category('categoryId', 'Category Name') export default class MyCategory { @Action({ `doActionWithParams`, `Do action`, `Do action with value: ${Bold('{0}')}`, { params: [ addParam('value', 'Value', { type: Param.String, initialValue?: '' }) ] } }) doActionWithParams(this: Instance, value: string) { console.log('Do action with value', value); }; }
Do not delete any actions, conditions, expressions from your category file. Because it can break projects that are using your addon inside.
Read more info: https://www.construct.net/en/make-games/manuals/addon-sdk/guide/defining-aces#internalH1Link0
How to mark any Action, Condition OR Expression as deprecated? Each Action,
Condition OR Expression has isDeprecated property in decorator options property, so you can set
it to true
to deprecate.
Example
import { Action, Category, Condition, Expression } from 'jsr:@lost-c3/lib'; import type { Instance } from '../Instance.ts'; @Category('categoryId', 'Category Name') export default class MyCategory { @Action(`doAction`, `Do action`, `Do action`, { /** * Default is False. Set to true to deprecate the ACE. */ isDeprecated: true }) doActionWithParams() { /* do something */ } }
Use Instance class to implement your custom logic to addon. Main instance file
is available at path: ./Addon/Instance.ts
.
Example of using Instance properties and functions inside any category entity (Action/Condition/Expression).
Instance.ts
const C3 = globalThis.C3; class LostInstance extends globalThis.ISDKInstanceBase { readonly value: string = 'My property value'; /** * Use this property to call any condition in your addon */ readonly Conditions = C3.Plugins[Lost.addonId].Cnds; constructor() { super(); const properties = this._getInitProperties(); if (properties) { /** * Here you can find your plugin properties */ } } _release() { super ._release(); } /** * Here is our instance method */ _getPropertyValue() { return this.value; } } C3.Plugins[Lost.addonId].Instance = LostInstance; export type { LostInstance as Instance };
MyCategory.ts
import { Action, Category, Condition, Expression } from 'jsr:@lost-c3/lib'; /** * Import your instance type */ import type { Instance } from '../Instance.ts'; @Category('categoryId', 'Category Name') export default class MyCategory { @Expression(`getValue`, `GetValue`) /** * Set the first argument of your method to: this: Instance */ GetValue(this: Instance) { return this._getPropertyValue(); } }
It's available to use custom Javascript OR Typescript script in your addon.
To use any script you should copy OR create script.js OR script.ts file at path:
./Addon/Scripts
. Your script will automatically will be loaded with type:
external-dom-script.
./Addon/Files
. If you added any .css file it will automatically
loaded with type: external-css. If you added file with any other
extension it will automatically loaded with type: copy-to-output.All Typescript files will be compiled into .js files after addon building.
If you want to load your script with type external-runtime-script, you
should call setRuntimeScripts(path)
in your Addon object in addon.ts
file.
Example
import { Plugin, Property } from 'jsr:@lost-c3/lib@3.0.0'; import config from "./lost.config.ts"; const Addon = new Plugin(config) Addon .setRuntimeScripts('runtime-index.js') ; export default Addon;
It's available to use files in your addon.
To use any file you should copy OR create file.* file at path:
./Addon/Files
. Your file will automatically will be loaded with auto-detected type.
If you want to include your file in project build, you should call addFilesToOutput(path)
in your Addon object in addon.ts
file.
Example
import { Plugin, Property } from 'jsr:@lost-c3/lib@3.0.0'; import config from "./lost.config.ts"; const Addon = new Plugin(config) Addon .addFilesToOutput('myfile.wasm') ; export default Addon;
It's available to use custom Javascript OR Typescript module in your addon.
To use any module you should copy OR create mymodule.js file at path:
./Addon/Modules
.
Example
import * as MyModule from './Modules/mymodule.ts'; const C3 = globalThis.C3; class LostInstance extends globalThis.ISDKInstanceBase { readonly PluginConditions = C3.Plugins[Lost.addonId].Cnds; constructor() { super(); const properties = this._getInitProperties(); console.log(MyModule.VAR); if (properties) { } } _release() { super._release(); } }; C3.Plugins[Lost.addonId].Instance = LostInstance; export type { LostInstance as Instance };
All Typescript files will be compiled into .js files after addon building.
[!INFO] ๐ For more info checkout official docs:
https://www.construct.net/en/make-games/manuals/addon-sdk/guide/runtime-scripts/sdk-v2
For fast and beautiful development there is a few functions that can help you customize displaying text in your addon.
List of available BBCode functions:
Function | Result |
---|---|
bold('Do action') |
Do action |
italic('Do action') |
Do action |
strikethrough('Do action') |
|
underline('Do action') |
Do action |
code('Do action') |
Do action |
Example
import { bold, code, italic, strikethrough, underline } from 'jsr:@lost-c3/lib/misc'; import { Action, Category } from 'jsr:@lost-c3/lib'; import type { Instance } from '../Instance.ts'; @Category('categoryId', 'Category Name') export default class MyCategory { @Action( `doAction`, `${bold('Action name')}`, `${italic('Do something')} and ${strikethrough('NOT')}`, `${underline('Underlined description...')} with ${code('SOMETHING')}` ) doAction(this: Instance) { /* do something */} }
To build addon into .c3addon
file you can use one of the following
commands:
lost build
addon.c3addon
file will be available at path: ./Builds/my_addon_1.0.0.0.c3addon
To test your addon you can use one of the following commands:
lost serve
Read more info about Developer Mode in Construct 3:
https://www.construct.net/en/make-games/manuals/addon-sdk/guide/using-developer-mode
MIT
Add Package
deno add jsr:@lost-c3/lib
Import symbol
import * as lib from "@lost-c3/lib";
---- OR ----
Import directly with a jsr specifier
import * as lib from "jsr:@lost-c3/lib";
Add Package
npx jsr add @lost-c3/lib
Import symbol
import * as lib from "@lost-c3/lib";
Add Package
yarn dlx jsr add @lost-c3/lib
Import symbol
import * as lib from "@lost-c3/lib";
Add Package
pnpm dlx jsr add @lost-c3/lib
Import symbol
import * as lib from "@lost-c3/lib";
Add Package
bunx jsr add @lost-c3/lib
Import symbol
import * as lib from "@lost-c3/lib";