How to Implement a Player Extension

Player extensions are main ways of handling input in Limon Engine. Input from player is first handled by PhysicalPlayer class, which governs look around and movement, then all input information is passed to selected extension, so it can handle custom interactions, like pickups, shooting etc. On the other side, any interaction send by other entities to player is directly passed to player extension for handling.

Player extensions follow the unified parameter contract. Like Triggers, the base class holds the values on a protected parameters member: you seed any default parameters into that member in the constructor, the base getParameters() const returns it, and setParameters() overwrites it when the designer edits values or a map is loaded. The configured values are persisted with the map and editable in the editor. An extension with no configurable settings simply seeds nothing and the member stays empty.

PlayerExtensionInterface Class

PlayerExtensionInterface(LimonAPI *limonAPI)

void

processInput(const InputStates &inputState, const PlayerInformation &playerInformation, long time)

void

interact(std::vector<LimonTypes::GenericParameter> &parameters)

std::vector<LimonTypes::GenericParameter>

getParameters() const

void

setParameters(std::vector<LimonTypes::GenericParameter>parameters)

std::string

getName() const

PlayerExtensionInterface(LimonAPI *limonAPI)

The constructor of the interface. If the extension exposes editor-configurable settings, this is where it seeds their defaults: build each LimonTypes::GenericParameter descriptor and push_back it onto the protected this->parameters member.

Note

All Player Extension must have the same signature, no other parameters should be required.

void processInput(const InputStates &inputState, const PlayerInformation &playerInformation, long time)

Called each frame with updated input information, current player state, and the frame time in milliseconds.

Parameters:

  1. const InputStates &inputState: Current input state for this frame.

  2. const PlayerInformation &playerInformation: Current player position and look direction. See PlayerInformation struct below.

  3. long time: Frame time in milliseconds.

void interact(std::vector<LimonTypes::GenericParameter> &interactionData)

Called by other entities to interact with player.

std::vector<LimonTypes::GenericParameter> getParameters() const

Returns the configurable parameters of this extension. These are rendered by the editor under the selected extension and persisted with the map. The base implementation returns the instance’s protected parameters member - the defaults you seeded in the constructor, or the configured values after an edit or load - so you normally do not override it. Override only to expose typed members as descriptors (Actor-style). An empty member means the extension has no editor-exposed configuration.

void setParameters(std::vector<LimonTypes::GenericParameter>parameters)

Stores the configured parameter values on the extension instance. Called when the map designer edits values in the editor and when a map is loaded. The base implementation keeps the values in the protected parameters member - the single source of truth for load, serialize, and editor edits. Override only if the extension needs to react to value changes.

std::string getName() const

Returns the name of the Player Extension.

Warning

The name must be unique, or the results will be undefined.

Note

To drive the camera from a player extension, activate a camera rig at runtime with createCameraRig / activateCameraRig (for example from processInput). The old getCustomCameraAttachment mechanism has been removed.

PlayerInformation struct

Passed to processInput each frame.

Type

Name

Description

LimonTypes::Vec4

position

Current world-space position of the player.

LimonTypes::Vec4

lookDirection

Normalized direction the player is looking at. w component unused.

InputStates Class Usage

Input is queried through InputStates using hash-keyed action names. Any binding — keyboard, mouse, or gamepad — maps to the same logical action, so plugin code never needs to know which physical key is pressed.

See Input System for the full API reference, the built-in action name table, how to define custom game actions in XML, and how to detect which input device the player is using.

How to enable Dynamic Library discovery

Limon engine will try to load custom player extensions on engine startup, from libcustomTriggers file (extension based on platform). If the file is found, engine will check for a method with following signature:

void registerPlayerExtensions(std::map<std::string, PlayerExtensionInterface*(*)(LimonAPI*)>* playerExtensionMap)

This method should fill the actorMap passed, with all the custom actors, like this:

(*playerExtensionMap)["$EXTENSION_NAME1$"] = &createPlayerExtension<$ExtensionClass1$>;
(*playerExtensionMap)["$EXTENSION_NAME2$"] = &createPlayerExtension<$ExtensionClass2$>;

Note

Every registered extension name is available through the static PlayerExtensionInterface::getExtensionNames() (Python: get_extension_names()). The editor uses this list to present the launch-time extension as a drop-down in Player Properties, so the registered name you use here is the one a map designer will pick from. See Using Builtin Editor.

Note

getExtensionNames() was previously named getTriggerNames(). It returns registered player-extension names, not trigger names; the old name was a misnomer and has been corrected.

Sample Player Extensions

The engine ships with sample player extensions under samples/ that implement PlayerExtensionInterface:

A Python player-extension sample ships under Engine/Scripts/ as python_player_extension.py (the PythonPlayerExtension class), subclassing the Python base in player_extension_interface.py.