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
openForPlayervs.openForEveryone-
Creating Flows with
back()andonResume - Sharing Data Between Views
Let's get started with the most basic usage of navigation between views, we have the following views:
// 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.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));
}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.
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.
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.classis not available) so is not possible to useopenForPlayer(...)) - 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());
}onResume is a method that is called when a player comes back from a view that used back() to navigate, so:
- Player go to "B" from "A" using
openForPlayer(B.class) - Player goes back to "A" using
back() -
onResumeis 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!");
}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:
-
onOpennoronFirstRenderis 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.
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))