User Input¶
Terasology handles the input over events, which will be send by the engine when an input condition is met. User input can be used for any kind of action, like movement, opening chests or rotating the player. Most of the input system is available through annotations which require little programming effort.
A quick example is the event for forward movement:
@RegisterBindButton(id = "forwards", description = "${engine:menu#binding-forwards}")
@DefaultBinding(type = InputType.KEY, id = Keyboard.KeyId.W)
public class ForwardsButton extends BindButtonEvent {
}
The @RegisterBindButton
annotation marks this class as a button event for a key binding.
A default binding can be defined via the @DefaultBinding
annotation.
In this case, this would be the W
key.
And as the class is used for a button binding, it has to extend BindButtonEvent
.
Define Bindings¶
To define an own binding, one needs to create a subclass of:
BindButtonEvent
, annotated with@RegisterBindButton
for keyboard input.BindAxisEvent
, annotated with@RegisterBindAxis
or@RegisterRealBindAxis
for controller input.
@DefaultBinding
can and should be used in both cases, it is also possible to define multiple defaults for the same binding by using the annotation multiple time.
A full example for a key binding that logs a greeting message when the user presses G
could look like this:
package org.terasology.examplemodule.binds;
import org.terasology.input.ActivateMode;
import org.terasology.input.BindButtonEvent;
import org.terasology.input.DefaultBinding;
import org.terasology.input.InputType;
import org.terasology.input.Keyboard.KeyId;
import org.terasology.input.RegisterBindButton;
@RegisterBindButton(id = "greet", category = "greeting", description = "${ExampleModule:input#binding-greet}", mode = ActivateMode.PRESS)
@DefaultBinding(type = InputType.KEY, id = KeyId.G)
public class GreeterButton extends BindButtonEvent {
}
This binding is defined in the module ExampleModule
. The button is registered with the id greet
and in the greeting
category.
Both of these values are required for the input category, as shown in the next snippet.
The description is a Translation identifier
and the mode restricts the event to a button PRESS
instead of triggering for press and release.
The default binding maps to the key G
and as the class is a button binding, it extends BindButtonEvent
.
Input Categories¶
The binding from the previous example would work on its own but is not shown in the input settings. To register binds to the input configuration, input categories are used.
They can be registered via the @InputCategory
annotation,
which is used to annotate a package, therefore in the package-info.java
file.
The event is contained in the package org.terasology.examplemodule.binds
,
therefore a package-info.java
is required in the same package.
@InputCategory(id = "exampleBindings",
displayName = "${ExampleModule#category-exampleBindings}",
ordering = {
"ExampleModule:greet"
}) package org.terasology.examplemodule.binds;
import org.terasology.input.InputCategory;
The category itself requires an id, exampleBindings
in this case. The display name is again a Translation identifier.
The ordering is an array of identifieres <moduleName>:<BindingId>
and determines the order of the bindings in the setting screen.
Note
All bindings should be in a package with an input category.
Note
Binding description and the display name of the input category should be translation identifiers instead of plain strings.
Handling Input Events¶
Input is handled by the Event System. If a binding is triggered, the input system will send the registered event to the player and the client. For the previous example, the following system can handle the event and will greet the player on the console when he triggers the input.
package org.terasology.examplemodule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.terasology.entitySystem.entity.EntityRef;
import org.terasology.entitySystem.event.ReceiveEvent;
import org.terasology.entitySystem.systems.BaseComponentSystem;
import org.terasology.entitySystem.systems.RegisterSystem;
import org.terasology.examplemodule.binds.GreeterButton;
@RegisterSystem
public class GreeterSystem extends BaseComponentSystem {
private static final Logger logger = LoggerFactory.getLogger(GreeterSystem.class);
@ReceiveEvent
public void onGreet(GreeterButton greetButton, EntityRef entity) {
logger.info("Greeting {}", entity);
}
}
Example output:
[main] INFO o.t.examplemodule.GreeterSystem - Greeting EntityRef{id = 47, netId = 0, prefab = 'engine:client'}
[main] INFO o.t.examplemodule.GreeterSystem - Greeting EntityRef{id = 55, netId = 0, prefab = 'engine:player'}
Note
If the event is consumed for the client entity, it will not be sent again to the player entity.
Todo
client-player difference