EntityComposer can be extended through a Lua based extension system. On startup all extensions are loaded from the following directory:
- Windows:
C:\Users\<username>\AppData\Local\InfectedBytes\EntityComposer\extensions
- Linux:
"~/.local/share/InfectedBytes/EntityComposer/extensions"
Each subdirectory corresponds to one extension, which must provide a manifest file (manifest.json
) and an entry point (main.lua
).
A manifest can look like this:
{
"id": "com.infectedbytes.my-awesome-extension",
"version": "0.1.0",
"composerVersion": ">=0.1.0",
"name": "My Awesome Extension",
"description": "Some simple test extension",
"dependencies": {
"com.infectedbytes.some-other-extension": ">=0.1"
},
"exports": ["myPublicAPI"]
}
Entry | Type | Meaning |
---|---|---|
id |
string |
Unique id for the plugin, must be the same as the directory name. It is good practice to follow the java package naming convention. |
version |
string |
Version of this extension (major.minor.patch ). |
composerVersion |
string |
Required version of the EntityComposer. This is a simple version expression, for example: >=0.1.0 |
name |
string |
Name of this extension. |
description |
string |
Description of this extension. |
dependencies |
object |
Contains all extensions this extension requires to run. If any of the dependencies is missing or only present in an unsupported version, the loading fails. |
exports |
array |
List of strings containing the files (without .lua ) that can be required from other extensions. |
require(...)
The normal lua require
function has been replaced by modified version. Just as the regular function it will ensure that a file is never loaded twice, instead the result from the first loading is returned.
local xyz = require "myOtherFile"
- simply loadsmyOtherFile.lua
of the extensionlocal xyz = require "some-other-plugin-id/exportedFile
- loadsexportedFile.lua
of thesome-other-plugin-id
extension, but only if the file is exported via the manifest.
registerExporter(...)
The registerExporter
function is used to register a new exporter.
A very simple exporter looks like this:
local myExporter = class("MyExporter", Exporter) -- create a new class inheriting from the Exporter class
myExporter.static.isFilePath = true -- tell the UI that it should provide a file chooser
-- define some settings that will be shown in the UI
myExporter.static.declaredSettings = {
setting("prettyPrint", "bool", true), -- define a boolean setting called "prettyPrint" that defaults to true
setting("value", "int", 42), -- define an int setting called "value" that defaults to 42
setting("test", "option", {"A", "B", "C"}) -- define a dropdown setting called "test" that has three options (A, B, C), defaulting to A
}
-- tell the system that we want to serialize enums using their fullname:
function myExporter:getEnumSerializationStrategy() return EnumSerialization.TypeDotName end
-- tell the system that we want to serialize entity references using their sequential id
function myExporter:getEntityReferenceKey() return EntityReferenceKey.Id end
-- tell the system that we want to resolve files relative to the export root
function myExporter:getFileResolutionStrategy() return FileResolutionStrategy.ExportRoot end
-- heart of the exporter. This function is called when the actual export happens.
function myExporter:execute()
local all = self.composition:collectUserEntities() -- get a sequential list of all user defined entities
local result = json.object() -- create empty json object
for k,entity in ipairs(all) do -- iterate over all entities
local e = json.object()
result[self:getEntityKey(entity)] = e
e.name = entity.name -- same as e["name"] = entity.name
e.components = json.object()
for i,ci in ipairs(entity.components) do
e.components[ci.component.name] = self:typeValueToJson(ci.component, ci.value)
end
end
local f = self:open()
f:write(json.serialize(result, self.settings.prettyPrint)) -- serialize json object using the prettyPrint setting
f:close()
end
-- register the freshly defined exporter
registerExporter(myExporter)