Skip to content

Rendering API

Axi provides a very extensible rendering API allowing you to render elements on a player's screen, be it an action bar, the chat or a boss bar.

Writing your own Renderable

To make your own renderable element, you have to implement the RedrawableRenderable interface.

Writing a render function

First up, we have to implement the render function. The render function is a suspending function that gets called on every redraw by this renderable and returns the contents that should be rendered on the player's screen.

In our case, this will just return the current tick of the server:

kt
object TickDisplay : RedrawableRenderable {
  override suspend fun render(): TextComponent = buildText {
    append(Bukkit.getCurrentTick())
    green()
  }
}

Writing a tick function

This tick function will handle our redrawing logic. The tickRedraw function takes in the current tick of the server and returns a RedrawResult. This can either be Redraw, which forces this redrawable to be redrawn, Dispose, which removes this redrawable from the player's render state or None which does nothing.

Let's redraw our tick display every other tick:

kt
object TickDisplay : RedrawableRenderable {
  override suspend fun render(): TextComponent = buildText {
    append(Bukkit.getCurrentTick())
    green()
  }
  
  override suspend fun tickRedraw(tick: Int): RedrawResult {
    return if (tick % 2 == 0) {
      RedrawResult.Redraw
    } else {
      RedrawResult.None
    }
  }
}

Great! This will display the current server tick ten times a second.

Writing a renderer

Axi currently provides two built-in renderers:

  • Renderer.Actionbar, which sends the stacked rendered component to an audience's action bar
  • Renderer.Chat, which "clears" an audience's chat by sending 16 empty lines and the stacked rendered component to an audience's chat.

For the sake of this guide, let's re-implement the Actionbar renderer ourselves. Renderer is a functional interface that takes in an audience, the current renderable, and the already rendered stacked component.

kt
val Actionbar = Renderer { audience, renderable, stacked ->
}

Now, let's actually send the stacked component using adventure's API:

kt
val Actionbar = Renderer { audience, renderable, stacked ->
  audience.sendActionBar(stacked)
}

Well, that was quite simple. Now let's actually use it in our renderable!

Using a renderer

To use a renderer in our redrawable, we have to override the renderer field:

kt
object TickDisplay : RedrawableRenderable {
  override suspend fun render(): TextComponent = buildText {
    append(Bukkit.getCurrentTick())
    green()
  }

  override suspend fun tickRedraw(tick: Int): RedrawResult {
    return if (tick % 2 == 0) {
      RedrawResult.Redraw
    } else {
      RedrawResult.None
    }
  }
  
  override val renderer: Renderer = Renderer.Actionbar
}

Displaying our renderable

Now, let's actually display our renderable. To do this, we simply add it to an Attachable's RenderStateComponent:

kt
player.renderState.currentlyRenderedRenderables.add(TickDisplay)

Axi also provides a utility for this:

kt
player.addRenderable(TickDisplay)