Navigating Between Views - DevNatan/inventory-framework GitHub Wiki

Navigating between views using InventoryFramework is pretty simple and straightforward, but there's some "little things" that you must understand about Data Transitivity and Shared Contexts before really diving into it.

Basic Usage

Let's get started with the most basic usage of navigation between views, we have the following views:

"A" view with a DIAMOND item on it that navigates to "B";

Screenshot 2023-09-13 at 21 21 44
// A.java
@Override
public void onInit(ViewConfigBuilder config) {
    config.title("A");
}

@Override
public void onFirstRender(RenderContext render) {
    // Moves player to "B" view on click
    render.firstSlot(new ItemStack(Material.DIAMOND))
        .onClick(click -> click.openForPlayer(B.class));
}

"B" view with a REDSTONE item on it that navigates back to "A";

Screenshot 2023-09-13 at 21 23 01
// B.java
@Override
public void onInit(ViewConfigBuilder config) {
    config.title("B");
}

@Override
public void onFirstRender(RenderContext render) {
    // Moves player to back to "A" view on click
    render.firstSlot(new ItemStack(Material.REDSTONE))
        .onClick(click -> click.openForPlayer(A.class));
}

And how it's working? What we have done?

Take a look inside the onClick method of each item, we have a openForPlayer method. That method is responsible for opening a view to the player that clicked on the item. Its signature is similar to ViewFrame's open but without the view class parameter. Pretty simple.


openForPlayer vs. openForEveryone

You've probably noticed that there is a another function called openForEveryone, it's also used to navigate between views, but... For shared contexts. Learn more about Shared Contexts.

In short, the difference is that: openForPlayer considers the subject of the context launched at that moment, that is, if you are opening within an onClick the context is SlotClickContext whose current player is the one who clicked on the item, then the next view will be displayed for that player.

Now, with shared context and using openForEveryone, the next screen will be opened to all players present in that context.

Creating Flows with back() and onResume

Inventory Framework has a feature that make possible to return to the previous view using a method called back(), it's works exactly like a browser history and it's especially useful when...

  • You don't know which view the player is coming from;
  • Cannot access the view (e.g. SomeView.class is not available) so is not possible to use openForPlayer(...))
  • Your view can be opened from different views, not just one, so there is no way to directly reference a single view to return.

So let's take a look, we will use a code similiar from Basic Usage topic but replacing openForPlayer in "B" view by back() and REDSTONE item by a GLOWSTONE_DUST.

// B.java
@Override
public void onInit(ViewConfigBuilder config) {
    config.title("B");
}

@Override
public void onFirstRender(RenderContext render) {
    // Moves player to back to the previous view on click
    render.firstSlot(new ItemStack(Material.GLOWSTONE_DUST))
        .onClick(click -> click.back());
}

"Welcome Back" message on resume

onResume is a method that is called when a player comes back from a view that used back() to navigate, so:

  1. Player go to "B" from "A" using openForPlayer(B.class)
  2. Player goes back to "A" using back()
  3. onResume is called on "A".

Resume have two parameters: origin that called back() and target that's the view who player is going back to. In our case origin context will have "B" as root and target will have "A" as root.

You can do cool things with that like changing the title of current view from "A" to "Welcome Back"!!

// A.java
@Override
public void onResume(Context origin, Context target) {
    // Use `target` here since its the current context
    target.updateTitleForPlayer("Welcome back!");
}

Considerations about back()

Different from ViewFrame's open, context's back() actually opens the view to the player but it doesn't perform rendering, instead, once player uses openForPlayer or openForEveryone a snapshot of his context is stored internally and when back() is called it's resumed exactly the same way it was before so:

  • onOpen nor onFirstRender is called;
  • All states will have the same value they had before open.

For example, if you use our Counter code sample that uses a State Management to create a counter, the count valu will remain the same as when you left.

Sharing Data Between Views

Data can be sent from one view to another via openForPlayer and openForEveryone, the second parameter of each one is called initialData that can be used for it. Initial data sent from one view to another can be retrieved on the second view by using initial state.

This code behaves exactly like as explained in Initial State docs, sents a "String" as initial data.

context.openForPlayer(B.class, "something")

Complex objects is supported as well like a Map or some random object, everything supported in Initial State

context.openForPlayer(B.class, ImmutableMap.of("some-int", 3))
⚠️ **GitHub.com Fallback** ⚠️