Sidebars

A Sidebar shows up to 15 lines of text on the right of the screen, like a minigame server scoreboard. Each line has a left text and an optional right-aligned value, and can hold live scores, selectors or NBT values.

import io.github.ayfri.kore.helpers.sidebar.sidebar

val lobby = sidebar("lobby") {
	title("Sky Wars", Color.GOLD)
	line("Map: Floating Isles")
	emptyLine()
	line("Players", value = scoreComponent("players_alive", literal("#game")))
	line("Kills", Color.RED, scoreComponent("kills", literal("#top")))
	emptyLine()
	line("play.example.net", Color.YELLOW)
}

load { lobby.create() }
tick { lobby.refresh() }
Kotlin

In game: the lobby sidebar after lobby.refresh(), with sample scores

sidebar(...) only declares the sidebar, commands are emitted where you call its functions.

Lines

line(text, color, value) adds a line, emptyLine() adds a blank one. Lines appear in declaration order, top to bottom.

sidebar("stats") {
	line("Coins") { value("1 250", Color.GOLD) }
	line(textComponent("Rank: ") + text("VIP", Color.AQUA))
}
Kotlin

Without a value, a line shows nothing on its right: the score numbers are always hidden.

Live values and refresh

The game resolves score, selector and NBT components once, when a line is written. refresh() rewrites only the lines holding such components, so calling it every tick stays cheap.

val arena = sidebar("arena") {
	line("Time left", value = scoreComponent("timer", literal("#round")))
	line("Arena: Desert")
}

tick { arena.refresh() }
Kotlin

Here refresh() emits the three commands of the "Time left" line, the static "Arena" line is never rewritten.

Score components read a named score holder, such as a fake player like #round. @s has no meaning in a sidebar refreshed from tick.

Conditional lines

visibleIf only shows a line while its condition passes. The condition is checked on create() and refresh().

sidebar("event") {
	line("Double XP active!", Color.GREEN) {
		visibleIf { score(literal("#event"), "double_xp", rangeOrInt(1)) }
	}
}
Kotlin

Runtime changes

setLine replaces a line from any function, without changing its declaration.

function("switch_map") {
	lobby.setLine(0, textComponent("Map: Nether Fortress"))
}
Kotlin

show(slot), hide(slot) and remove() manage the display. DisplaySlots.sidebarTeam(color) shows a different sidebar to each team color.

function("red_team_sidebar") {
	redTeamSidebar.show(DisplaySlots.sidebarTeam(FormattingColor.RED))
}

function("end_game") {
	lobby.hide()
	lobby.remove()
}
Kotlin

How it works

Each sidebar owns its objective, and each line is the fake player $<index> scored -index, so lines sort top to bottom and two sidebars never share a line. create() recreates the objective, hides score numbers with numberformat blank, writes the text with scoreboard players display name and the value with numberformat fixed.

A sidebar looks the same for every player watching the same slot. Per-player sidebars aren't possible in vanilla because display slots are global, team-colored slots are the closest option.