Library for easy making Construct 3 Addons.
Lost is a library for easy making Construct 3 addons that was created by lostinmind.
Key features:
๐ Quickstart
Install global lost-c3-cli by using npm i lost-c3-cli -g
Create a bare-bones Lost Addon for plugin by using lost-c3 init --plugin
npm i lost-c3-cli -g
lost-c3 init --plugin # For plugin
npm run build
๐ Documentation
After using lost-c3 init --plugin
we get default file structure for creating addon.
๐งฑ Addon file structure
โโโ build/ # Final build folder (creates automatically after build)
โ โโโ addon/
โ โโโ lost/
โโโ node_modules/ # 'node_modules' folder
โโโ src/ # Main addon folder
โ โโโ addon/ # Construct 3 Typescript based addon folder
โ โโโ categories/ # Addon categories folder
โ โโโ files/ # Addon other files folder
โ โโโ libs/ # Addon libraries folder (only .js libraries, use .d.ts
โ โโโ ts-defs/
โ โโโ Instance.ts # Main addon Instance class.
โ โโโ icon.svg # Addon icon file (only image/svg format!)
โ โโโ lost.config.ts # Lost addon config file
โ โโโ plugin.properties.ts # Plugin properties file
โโโ .babelrc.json # 'Babel' config file
โโโ package.json # 'package.json' file
โโโ tsconfig.json # 'tsconfig.json' file
โ๏ธ Config setup
Letโs setup lost.config.ts
file at first.
import { Lost } from "lost-c3-lib";
const Config: Lost.Config = {
/**
* Common options
*/
MinConstructVersion: "",
IsSingleGlobal: true,
IsDeprecated: false,
CanBeBundled: true,
ObjectName: "MyLostAddon",
/**
* Info
*/
AddonId: "addon_id",
Type: "plugin",
AddonCategory: "general",
AddonName: "My First Lost Addon",
AddonDescription: "My first lost addon is awesome!",
Version: "1.0.0.0",
Author: "Lost",
WebsiteURL: "https://addon.com",
DocsURL: "https://docs.addon.com",
Icon: {
FileName: 'icon.svg',
Type: 'image/svg+xml'
},
/**
* Files
*/
Scripts: [
{FileName: 'library.js', Type: 'external-dom-script', ScriptType: 'module'},
{FileName: 'library.js', Type: 'external-runtime-script'}
],
RemoteScripts: [
"https://script/library.js"
],
Files: [
{FileName: '', Type: 'external-css'},
{FileName: '', Type: 'copy-to-output'}
]
}
export { Config };
Check more info about using scripts OR libraries in your addon: Using custom libraries/scripts/files
๐ Using custom libraries/scripts/files
Itโs available to use custom scripts or libraries in your addon.
Add any library file (
library.js
) intosrc/addon/libs/
folder.Add any file (
data.txt
) intosrc/addon/files
folder.
Important
You should update lost.config.ts
Scripts OR Files property and add any script/file you have uploaded.
Example of adding custom script
import { Lost } from "lost-c3-lib";
const Config: Lost.Config = {
/**
* Here we added some objects
*/
Scripts: [
{FileName: 'library.js', Type: 'external-dom-script', ScriptType: 'module'},
],
MinConstructVersion: "",
IsSingleGlobal: true,
IsDeprecated: false,
CanBeBundled: true,
ObjectName: "MyLostAddon",
AddonId: "addon_id",
Type: "plugin",
AddonCategory: "general",
AddonName: "My First Lost Addon",
AddonDescription: "My first lost addon is awesome!",
Version: "1.0.0.0",
Author: "Lost",
WebsiteURL: "https://addon.com",
DocsURL: "https://docs.addon.com",
Icon: {
FileName: 'icon.svg',
Type: 'image/svg+xml'
}
}
export { Config };
In that case we added new object in Scripts
property. That object has some own properties:
- FileName: string // Use only path to lib without ./lib/. Example: "lib.js"
- Type: "external-runtime-script" | "external-dom-script"
Note
Useful information for choosing Type
property value:
https://www.construct.net/en/make-games/manuals/addon-sdk/reference/specifying-dependencies#internalH1Link0
Tip
Itโs recommended to use .d.ts
files to easy code writing.
You can also move them into src/libs/
folder.
Warning
If you passed adding script into lost.config.ts
file. Addon wonโt be loaded successfully!
Warning
Use only .js libraries with .d.ts declaration files only.
โ๏ธ Specifying plugin properties
Use plugin.properties.ts
file to specify any plugin properties for your addon.
Example
import { CheckProperty, ColorProperty, ComboProperty, FloatProperty, FontProperty, GroupProperty, IntegerProperty, LongTextProperty, ObjectProperty, PercentProperty, TextProperty } from "lost-lib";
const PluginProperties: Lost.PluginProperty[] = [
new IntegerProperty({
Id: "int",
Name: "Integer Property",
Description: "Description...",
InitialValue: 0,
}),
new FloatProperty({
Id: "float",
Name: "Float Property",
InitialValue: 0,
}),
new PercentProperty({
Id: "percent",
Name: "Percent Property",
InitialValue: 1,
}),
new TextProperty({
Id: "text",
Name: "Text Property",
InitialValue: "",
}),
new LongTextProperty({
Id: "long_text",
Name: "Long Text Property",
InitialValue: "",
}),
new CheckProperty({
Id: "check",
Name: "Check Property",
InitialValue: false,
}),
new FontProperty({
Id: "font",
Name: "Font Property",
InitialValue: "Arial",
}),
new ComboProperty({
Id: "combo",
Name: "Combo Property",
InitialValue: "item_one",
Items: [
{Id: "item_one", Name: "Item 1"},
{Id: "item_two", Name: "Item 2"}
]
}),
new ColorProperty({
Id: "color",
Name: "Color Property",
InitialValue: [1, 0, 0]
}),
new ObjectProperty({
Id: "object",
Name: "Object Property"
}),
new GroupProperty({
Id: "group",
Name: "Group Property",
}),
]
export { PluginProperties };
๐ Creating category
To create category you should create new CategoryName.ts
file in src/addon/categories
folder.
Then you can use code snippet !CC
to create default Category structure or copy-paste below script.
import { Lost, Action, Condition, Expression } from "lost-c3-lib";
import type { Instance } from "@Instance";
class MyCategory extends Lost.Category {
/**
* @super(categoryId: string, categoryName: string)
*/
constructor() { super('main', 'My Category') };
}
const Category = new MyCategory();
export { Category };
Caution
DO NOT CHANGE Category
VARIABLE NAME!โ
โก๏ธ Create action
To create actions for your addon you should use @Action
decorator of function in your category class.
Example
import { Lost, Action, StringParam } from "lost-c3-lib";
import type { Instance } from "@Instance";
class MyCategory extends Lost.Category {
constructor() { super('myCategoryId', 'My Category') };
@Action({
/**
* A string specifying a unique ID
*/
Id: 'myAction',
/**
* The name that appears in the action picker dialog
*/
Name: '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.
* (There must be one parameter placeholder per parameter.)
*/
DisplayText: 'Do something',
/**
* @optional A description of the action or condition, which appears as a tip at the top of the condition/action picker dialog.
*/
Description: 'Awesome action...',
/**
* @optional Set to true to mark the action as asynchronous.
* Make the action method an async function, and the system Wait for previous actions to complete action will be able to wait for the action as well.
*/
IsAsync: false,
/**
* @optional Set to true to deprecate
*/
Deprecated: false,
/**
* Use Params property if you need to assign action parameters
*/
Params: [
new StringParam({
/**
* A string specifying a unique ID
*/
Id: 'message',
/**
* The name of the parameter
*/
Name: 'Message',
/**
* @optional The parameter description
*/
Description: 'Enter your message...',
/**
* A string which is used as the initial expression
*/
InitialValue: '"Some message"'
})
]
})
myAction(message: string) {
console.log('Log message', message);
}
}
const Category = new MyCategory();
export { Category };
Warning
Itโs important to use {0}, {1} as parameter placeholders inside DisplayText property if you have any parameters inside your function (excluding this parameter as Instance Type)
โ Create condition
To create conditions for your addon you should use @Condition
decorator of function in your category class.
Example
import { Lost, Condition, ComboParam } from "lost-c3-lib";
import type { Instance } from "@Instance";
class MyCategory extends Lost.Category {
constructor() { super('myCategoryId', 'My Category') };
@Condition({
Id: 'myCondition',
Name: 'On event',
DisplayText: 'On event [i]{0}[/i]',
/**
* Set to true to highlight the ACE in the condition/action/expression picker dialogs.
*/
Highlight: true,
/**
* Specifies a trigger condition.
* This appears with an arrow in the event sheet.
* Instead of being evaluated every tick, triggers only run when they are explicity triggered by a runtime call.
*/
IsTrigger: true,
IsCompatibleWithTriggers: false,
IsFakeTrigger: false,
IsInvertible: false,
IsLooping: false,
IsStatic: false,
Params: [
new ComboParam({
Id: 'event',
Name: 'Event',
Items: [
{Id: 'open', Name: 'Open'},
{Id: 'close', Name: 'Close'}
],
/**
* Use any item id to use as iniial value
* If passed, library will automatically set initial value to the first item
*/
InitialValue: 'open'
})
]
})
onEvent(eventIndex: number) {
/**
* When it's a ComboParam, in function you get item index
*/
switch(eventIndex) {
case 0:
// 'open' event
break;
case 1:
// 'close' event
break;
}
}
}
const Category = new MyCategory();
export { Category };
Warning
Itโs important to use {0}, {1} as parameter placeholders inside DisplayText property if you have any parameters inside your function (excluding this parameter as Instance Type)
๐งฎ Create expression
To create expressions for your addon you should use @Expression
decorator of function in your category class.
Example
import { Lost, Expression, StringParam } from "lost-c3-lib";
import type { Instance } from "@Instance";
class MyCategory extends Lost.Category {
constructor() { super('myCategoryId', 'My Category') };
@Expression({
Id: 'getValue',
/**
* Name will not be used, but required
*/
Name: 'GetValue',
DisplayText: 'GetValue',
ReturnType: 'string',
/**
* If true, Construct 3 will allow the user to enter any number of parameters beyond those defined.
* In other words the parameters (if any) listed in "params" are required, but this flag enables adding further "any" type parameters beyond the end.
*/
IsVariadicParameters: false
})
getValue() {
return 'somevalue';
}
}
const Category = new MyCategory();
export { Category };
Tip
Itโs recommended to name DisplayText property without spaces Because if you name DisplayText with spaces it will not correctly display expression after user close expressions window.
Caution
Lost library isnโt checking parameters that you use in Expressions at that moment. But you must use only StringParam() OR NumberParam() OR AnyParam()
๐ข Deprecating Actions, Conditions, Expressions
Caution
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 Deprecated property in decorator, so you can set it to true
to deprecate.
Deprecated: boolean;
๐ณ Using Instance
Also you have an ability to use Instance class to implement your custom logic to addon.
Main instance class is available at path src/addon/Instance.ts
.
Note
Example of using instance inside function
Instance.ts
import { Config } from "@Config";
const C3 = globalThis.C3;
class LostInstance extends globalThis.ISDKInstanceBase {
myVar: string = 'someValue';
readonly PluginConditions = C3.Plugins[Config.AddonId].Cnds;
constructor() {
super();
const properties = this._getInitProperties();
if (properties) {
}
}
_release() {
super._release();
}
};
C3.Plugins[Config.AddonId].Instance = LostInstance;
export type { LostInstance as Instance };
Category.ts
import { Lost, Action } from "lost-c3-lib";
import type { Instance } from "@Instance";
class MyCategory extends Lost.Category {
constructor() { super('myCategoryId', 'My Category') };
@Action({
Id: 'getValue',
Name: 'GetValue',
DisplayText: 'GetValue',
})
getValue(this: Instance) {
console.log(this.myVar);
}
}
const Category = new MyCategory();
export { Category };
Building addon
To build addon into addon.c3addon
file you should use npm run build
.c3addon
file will be available in your main folder when you are developing your addon.
Testing addons in developer mode
To run test server you should use npm run server
OR npm run dev
npm run server
comman will run server oncenpm run dev
will detect all addon changes and reload addon with recompiling
Important
Read more info about developer mode in Construct 3:
https://www.construct.net/en/make-games/manuals/addon-sdk/guide/using-developer-mode
Tip
If you want to open Construct 3 page after server run you should use npm run server --open
๐ชช License
MIT