Skip to content

Ticking API

If you're working with tick-based automations (e.g. walk for a certain number of ticks, ...), Actor has a comprehensive API built around ClientTicks.
If you're unfamiliar with Minecraft Ticks, see the Minecraft Wiki.

ClientTickBus

Actor provides a ClientTickBus in order to deliver ticks to internal implementations, but also to you, the user.

Adding Tick Listeners

For various reasons, you may want to execute code every ClientTick (20 times per second).
For that, you can either use the TickEvent of the Mod Loader of your choice, or use the functionality Actor delivers out of the box.
To add a tick listener, you can do the following:

java
var tickProvider = ClientTickBus.getInstance();

Runnable LOG = () -> MY_LOGGER.info("Hello from a ClientTick");

tickProvider.onTick(LOG);

In the onTick() method, you can provide any Runnable (or function reference) you'd like to execute on each ClientTick.
You can also remove a listener if you decide it's not useful anymore:

java
tickProvider.removeTick(LOG);

For that you just need to pass a reference to the original Runnable you submitted.

WARNING

It is NOT recommended to implement IClientTickBus yourself, Actor takes care of that.
You should only ever use ClientTickBus.getInstance()

WaitableTask

Another really useful feature of Actor is WaitableTasks.
These represent tasks that are executed every ClientTick but are capable of being suspended for a specified amount of ticks.
This leads to easier handling of tick-based automations.

java
private static void jump(IWaitableTask instance){
    var actor = YOUR_ACTOR;
    var mov = actor.getMovement();
    
    mov.setJumping(true);
    instance.WaitForTicks(20); // Jump for 20 ticks
    mov.setJumping(false);
}

// Any Method you call when initializing your Actor
private void init(){
    ClientTickBus.getInstance().submitWaitable(WaitableTask.create(YourClass::jump));
}

This is especially useful when you need a lot of changing states that are based on ticks that pass.
Just be careful to make sure your method that uses WaitForTicks() always takes exactly one argument, an IWaitableTask, otherwise you won't be able to use this feature.
You may also use a Consumer<IWaitableTask> or declare the function inline:

java
Consumer<IWaitableTask> jump = (instance) -> {
    mov.setJumping(true);
    instance.WaitForTicks(20); // Jump for 20 ticks
    mov.setJumping(false);
};
ClientTickBus.getInstance().submitWaitable(new WaitableTask(jump));

// OR

ClientTickBus.getInstance().submitWaitable(new WaitableTask(instance -> {
    mov.setJumping(true);
    instance.WaitForTicks(20); // Jump for 20 ticks
    mov.setJumping(false);
}));

WARNING

Do NOT try to obtain a WaitableTask instance in any other way, as this may break things.
It is designed to be used like in the examples provided.
STRICTLY use either new WaitableTask(Consumer<IWaitableTask> action) or WaitableTask.create(Consumer<IWaitableTask> action)