Building interfaces in Kotlin since 2022.
interfaces-kotlin
is a builder-style user interface library designed to make creation of flexible user interfaces as easy as
possible.
This is a forked version of the original interfaces by Incendo. Specifically, this repository contains a Kotlin version of interfaces v2 (or interfaces-next). The entire library is written in Kotlin and uses suspending methods for better coroutine support than what can be offered by a Java library.
An interface is the main class that you'll be interacting with. Interfaces hold a series of transformations and other values that can be used to construct an InterfaceView.
An InterfaceView represents a 'rendered' interface. An InterfaceView holds one pane and one InterfaceViewer.
A pane holds a collection of elements that make up the visual aspect of an interface.
A transformation ("transform") operates on a type of pane to add, remove, or change elements. Transformations are used to interact with panes.
Interfaces can be found on our public Maven repository and added to a Maven project as follows:
<repository>
<id>noxcrew-maven</id>
<name>Noxcrew Public Maven Repository</name>
<url>https://maven.noxcrew.com/public</url>
</repository>
<dependency>
<groupId>com.noxcrew.interfaces</groupId>
<artifactId>interfaces</artifactId>
<version>REPLACE_WITH_CURRENT_INTERFACES_VERSION</version>
</dependency>
Creating an interface
This code creates a chest interface with 6 rows, a background fill, an ItemStack that counts how many ticks have passed and automatically updates itself, and an item that runs a coroutine for 5 seconds before allowing further click actions.
// Create a property that will trigger an update of the transform on change.
val counterProperty = interfaceProperty(5)
var counter by counterProperty
// Create a new chest interface. You can also create a player interface (player inventory) or combined interface (opened chest and player inventory below).
val chestInterface = buildChestInterface {
rows = 6
// Create a new transform that updates whenever the counter property changes
withTransform(counterProperty) { pane, _ ->
// Define the item to show. This transform is re-run whenever the property changes
// so we can reference the variable here.
val item = ItemStack(Material.BEE_NEST)
.name("it's been $counter's ticks")
.description("click to see the ticks now")
// Create a new static element that runs the function when clicked.
pane[3, 3] = StaticElement(drawable(item)) {
it.player.sendMessage("it's been $counter's ticks")
}
}
// Create a second transform that is only drawn once (on open) which has an item to run a delayed function
withTransform { pane, _ ->
val item = ItemStack(Material.BEE_NEST)
.name("block the interface")
.description("block interaction and message in 5 seconds")
pane[5, 3] = StaticElement(drawable(item)) {
// Indicate that we are going to run our own function and will run complete() later to resume usage of the menu
completingLater = true
// Use your own scheduling solution and/or coroutines to run a task, just make sure to call complete()!
Bukkit.getScheduler().runTaskLaterAsynchronously(this, Runnable {
it.player.sendMessage("after blocking, it has been $counter's ticks")
complete()
}, 100L)
}
}
// Finally we draw a background by drawing a pane to each slot that is not already filled.
withTransform { pane, _ ->
forEachInGrid(6, 9) { row, column ->
if (pane.has(row, column)) return@forEachInGrid
val item = ItemStack(Material.WHITE_STAINED_GLASS_PANE)
.name("row: $row, column: $column")
pane[row, column] = StaticElement(drawable(item))
}
}
}
// We can easily open the interface which will return an InterfaceView instance
chestInterface.open(player)
Further examples can be found here: https://github.com/Noxcrew/interfaces-kotlin/tree/main/examples
Thanks to broccolai for the original creation of Interfaces 2.
Thanks to incendo for the creation of the interfaces
library.
Thanks to kyori and their adventure
text library.