Using States

Quick example on how to use States.


All examples are for the Paper platform, but it should be similar if not identical in other platforms.

Kotlin examples require the dev.triumphteam:triumph-gui-<platform>-kotlin:<version> dependency.

#Title and states

States can also be applied to titles, which means we can share them between a component and a title making a component update the title.

For this example, let's add a "highScore" in the title, where within the current game session we keep track of the highest number of clicks you did.
For that we need to create a state that is not in the same place as the opening of the GUI. For example as a field in a command class.

For this state it's nice to make it so it can only be updated if the clicks are higher than the stored value. Thankfully we can use a StateMutationPolicy for that, so let's create a new one!

public final class HighScoreMutationPolicy implements StateMutationPolicy<Integer> {

    @Override
    public boolean shouldMutate(@Nullable final Integer currentValue, @Nullable final Integer newValue) {
        if (currentValue == null || newValue == null) return false;
        // Only allow mutation if the new value is higher
        return newValue > currentValue;
    }
}
class HighScoreMutationPolicy : StateMutationPolicy<Int?> {

    override fun shouldMutate(currentValue: Int?, newValue: Int?): Boolean {
        if (currentValue == null || newValue == null) return false
        // Only allow mutation if the new value is higher
        return newValue > currentValue
    }
}

The mutation policy in this example is not really needed; this is just an example of how it can be used.

Now let's create a state with the new policy.

private final MutableState<Integer> highScoreState = MutableState.of(0, new HighScoreMutationPolicy());
private val highScoreState = mutableStateOf(0, HighScoreMutationPolicy())

Then we can change the GUI to support it.

final var gui = Gui.of(1)
        .spamPreventionDuration(0) // Changing the spam prevension to allow faster clicking, for fun
        .title(title -> {
            // Tell the title to remember the high score state
            title.remember(highScoreState);
            // Then render the title with the high score value
            title.render(() -> Component.text("Cookie clicker! Highest score: " + highScoreState.get()));
        })
        .component(component -> {

            // We tell the component to remember the starting value `0`
            // Which will return a MutableState<Integer> that can be used in the render function of the component
            final var clicks = component.remember(0);

            // Here is where the component will be rendered
            component.render(container -> {

                // Like before, we set the item in the middle of the inventory
                // Let's also change the item to a COOKIE
                container.setItem(1, 5, ItemBuilder.from(Material.COOKIE)
                        // We append the value of the clicks state to the name of the item
                        .name(Component.text("Clicked " + clicks.get() + " times!"))
                        .asGuiItem((player, context) -> {
                            // Now we update the clicks state by adding 1 to the previous amount
                            clicks.update(previous -> previous + 1);

                            // Set the value to the high score state
                            // Because of the policy we added, it means that this will only actually change the state
                            // if the value is higher than the current value
                            highScoreState.set(clicks.get());

                            // As stated before, the mutation policy isn't really needed, could have just been
                            // something like if (clicks.get() > highScore.get()) highScore.set(clicks.get())
                            // both are totally fine
                        })
                );
            });
        })
        .build();

gui.open(player);
val gui = buildGui {
    // If not set, defaults to chest - 1 row
    // So in this case this wouldn't be needed, leaving it here as an example
    containerType = chestContainer {
        rows = 1
    }

    // Changing the spam prevension to allow faster clicking, for fun
    spamPreventionDuration = 0.seconds
    
    // Delegate the value of the state
    // Not needed, but it's nicer to work with
    var highScore by highScoreState

    title {
        // Tell the title to remember the high score state
        remember(highScoreState)
        // Then render the title with the high score value
        render { Component.text("Cookie clicker! Highest score: $highScore") }
    }

    // We use stateless since we don't need any updates for this example
    component {

        // We tell the component to remember the starting value `0`
        // Which will return a MutableState<Integer> that can be used in the render function of the component
        var clicks by remember(0)

        // Here is where the component will be rendered
        render { container ->

            // Like before, we set the item in the middle of the inventory
            // Let's also change the item to a COOKIE
            container[1, 5] = ItemBuilder.from(Material.DIAMOND)
                .name(Component.text("Clicked $clicks times!"))
                .asGuiItem { _, _ ->
                    // Now we increase the clicks state by 1
                    clicks++

                    // Set the value to the high score state
                    // Because of the policy we added, it means that this will only actually change the state
                    // if the value is higher than the current value
                    highScore = clicks

                    // As stated before, the mutation policy isn't really needed, could have just been
                    // something like if (clicks > highScore) highScore = clicks
                    // both are totally fine
                }
        }
    }
}

gui.open(player)

When the GUI is opened for the first time the title will update with the clicks, once you close and re-open it, it'll only update once you reach a new high score.

#Finalizing

Now that you have seen the examples and learned how to build a GUI, continue reading on the more in-depth aspects of the library.

Edit this page on GitHub

On this page

Code copied to clipboard!