1# Rendering API
2
3Axi provides a very extensible rendering API allowing you to
4render elements on a player's screen, be it an action bar,
5the chat or a boss bar.
6
7## Writing your own Renderable
8
9To make your own renderable element, you have to implement
10the `RedrawableRenderable` interface.
11
12## Writing a render function
13
14First up, we have to implement the `render` function. The
15`render` function is a suspending function that gets called
16on every redraw by this renderable and returns the contents
17that should be rendered on the player's screen.
18
19In our case, this will just return the current tick of the
20server:
21
22```kt
23object TickDisplay : RedrawableRenderable {
24 override suspend fun render(): TextComponent = buildText {
25 append(Bukkit.getCurrentTick())
26 green()
27 }
28}
29```
30
31## Writing a tick function
32
33This tick function will handle our redrawing logic. The
34`tickRedraw` function takes in the current `tick` of the
35server and returns a `RedrawResult`. This can either be
36`Redraw`, which forces this redrawable to be redrawn,
37`Dispose`, which removes this redrawable from the player's
38render state or `None` which does nothing.
39
40Let's redraw our tick display every other tick:
41
42```kt
43object TickDisplay : RedrawableRenderable {
44 override suspend fun render(): TextComponent = buildText {
45 append(Bukkit.getCurrentTick())
46 green()
47 }
48
49 override suspend fun tickRedraw(tick: Int): RedrawResult {
50 return if (tick % 2 == 0) {
51 RedrawResult.Redraw
52 } else {
53 RedrawResult.None
54 }
55 }
56}
57```
58
59Great! This will display the current server tick ten times a
60second.
61
62## Writing a renderer
63
64Axi currently provides two built-in renderers:
65
66- `Renderer.Actionbar`, which sends the stacked rendered
67component to an audience's action bar
68- `Renderer.Chat`, which "clears" an audience's chat by
69sending 16 empty lines and the stacked rendered component to
70an audience's chat.
71
72For the sake of this guide, let's re-implement the `Actionbar`
73renderer ourselves. `Renderer` is a functional interface that
74takes in an audience, the current renderable, and the already
75rendered stacked component.
76
77```kt
78val Actionbar = Renderer { audience, renderable, stacked ->
79}
80```
81
82Now, let's actually send the stacked component using adventure's
83API:
84
85```kt
86val Actionbar = Renderer { audience, renderable, stacked ->
87 audience.sendActionBar(stacked)
88}
89```
90
91Well, that was quite simple. Now let's actually use it in our
92renderable!
93
94## Using a renderer
95
96To use a renderer in our redrawable, we have to override the
97`renderer` field:
98
99```kt
100object TickDisplay : RedrawableRenderable {
101 override suspend fun render(): TextComponent = buildText {
102 append(Bukkit.getCurrentTick())
103 green()
104 }
105
106 override suspend fun tickRedraw(tick: Int): RedrawResult {
107 return if (tick % 2 == 0) {
108 RedrawResult.Redraw
109 } else {
110 RedrawResult.None
111 }
112 }
113
114 override val renderer: Renderer = Renderer.Actionbar
115}
116```
117
118## Displaying our renderable
119
120Now, let's actually display our renderable. To do this, we
121simply add it to an `Attachable`'s `RenderStateComponent`:
122
123```kt
124player.renderState.currentlyRenderedRenderables.add(TickDisplay)
125```
126
127Axi also provides a utility for this:
128
129```kt
130player.addRenderable(TickDisplay)
131```