Skip to content

A Java user-interface library with support for Minecraft.

Notifications You must be signed in to change notification settings

Incendo/interfaces

Repository files navigation

interfaces

Building interfaces since 2021.

interfaces is a builder-style user interface library designed to make creation of flexible user interfaces as easy as possible.

This library is currently in a state of constant breaking changes. The API has yet to be finalized, so please keep this in mind when considering using interfaces.

Packages

interfaces-core provides the core API classes.

interfaces-paper implements interfaces using the Paper Minecraft server API. This package provides the capability to construct a variety of Minecraft-based interfaces, including text, inventory (i.e. chests), and books.

Terminology

Interface

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.

InterfaceView ("view")

An InterfaceView represents a 'rendered' interface. An InterfaceView holds one pane and one InterfaceViewer.

InterfaceViewer ("viewer")

An InterfaceViewer represents an object that can view an interface. InterfaceViewers are provided panes to view.

Pane

A pane holds a collection of elements that make up the visual aspect of an interface.

Transform

A transformation ("transform") operates on a type of pane to add, remove, or change elements. Transformations are used to interact with panes.

Usage

Snapshots of this repository are hosted at https://oss.sonatype.org/content/repositories/snapshots/.

Gradle example:

repositories() {
    // ...
    maven("https://oss.sonatype.org/content/repositories/snapshots/")
    // ...
}

dependencies() {
    implementation("org.incendo.interfaces:interfaces-{package}:1.0.0-SNAPSHOT")
}

Examples

Creating an interface

This code creates a chest interface with one row, a background fill, an ItemStackElement containing information about the player, and utilizes an argument provider. This element also tracks how many times it has been clicked.

ChestInterface infoInterface = ChestInterface.builder()
    // This interface will have one row.
    .rows(1)
    // This interface will update every five ticks.
    .updates(true, 5)
    // Cancel all inventory click events
    .clickHandler(ClickHandler.cancel())
    // Fill the background with black stained glass panes
    .addTransform(PaperTransform.chestFill(
    ItemStackElement.of(new ItemStack(Material.BLACK_STAINED_GLASS_PANE))
    ))
    // Add some information to the pane
    .addTransform((pane, view) -> {
        // Get the view arguments
        // (Keep in mind - these arguments may be coming from a Supplier, so their values can change!)
        final String time = view.arguments().get(ArgumentKey.of("time", String.class));
        final Player player = view.arguments().get(ArgumentKey.of("player", Player.class));
        final Integer clicks = view.arguments().get(ArgumentKey.of("clicks", Integer.class));

        ItemStack itemStack = new ItemStack(Material.PAPER);
        ItemMeta itemMeta = itemStack.getItemMeta();

        itemMeta.displayName(Component.text("Item Name", NamedTextColor.GREEN));
        ArrayList<Component> lore = new ArrayList<>();
        lore.add(Component.text("Line 1"));
        lore.add(Component.text("Clicks: " + clicks));
        itemMeta.lore(lore);
        itemStack.setItemMeta(itemMeta);

        // Return a pane with
        return pane.element(ItemStackElement.of(itemStack,
        // Handle click
        (clickHandler) -> {
            final HashMapInterfaceArguments arguments = HashMapInterfaceArguments
                .with(ArgumentKey.of("clicks", Integer.class), (clickHandler.view().arguments().get(ArgumentKey.of("clicks", Integer.class))) + 1)
                .with(ArgumentKey.of("player", Player.class), clickHandler.view().arguments().get(ArgumentKey.of("player", Player.class))).build();

            clickHandler.view().backing().open(clickHandler.viewer(), arguments);
        }
    ), 4, 0);
    })
    // Set the title
    .title(Component.text("interfaces demo"))
    // Build the interface
    .build();
Showing the interface to a player

This code shows the interface created in the previous example being shown to a viewer. As the interface uses arguments, we can pass in supplier functions to the interface argument.

// Open the interface to the player.
infoInterface.open(PlayerViewer.of(player),
    // Create a HashMapInterfaceArgument with a time argument set to a
    // supplier that returns the current time printed all nice and pretty.
    HashMapInterfaceArguments
        .with(ArgumentKey.of("player", Player.class), player)
        .with(ArgumentKey.of("time", String.class), () -> {
            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
            LocalDateTime now = LocalDateTime.now();
            return dtf.format(now);
            })
        .with(ArgumentKey.of("clicks", Integer.class), 0).build()
);

Video of the result of this code in Minecraft.

Note: these examples may not reflect the latest version of the interfaces API.

Further examples can be found here: https://github.com/Incendo/interfaces/tree/master/examples

Credits

Thanks to kyori and their adventure text library.

Thanks to broccolai for letting me steal his entire Gradle project setup.