Get Started
Creating UI using Java
and KubeJS
is mostly the same. This page will introduce the basic workflow of creating and using a UI.
The entire UI creation and usage pipeline consists of the following steps:
-
Create UI widget and layout (1)
- Create
buttons
anditem slots
, set their positions...
- Create
-
Bind UI functional logic (1)
- Add logic to be executed when a
button
is clicked, bindinventory
toitem slots
...
- Add logic to be executed when a
-
Display the UI (1)
- Open the
GUI
whenright-clicking
an item, open theGUI
whenright-clicking
a block...
- Open the
Technically, the UI function binding
and UI widget creation
processes happen simultaneously, as many controls provide constructors that bind functions at the same time.
On this page, we separate step 1 and step 2 in the code examples to provide a clearer understanding of how the UI
works.
Create UI
Widgets and Layout
Let's begin with a WigetGroup
, which is a container of child widgtes. Therefore, we create a WidgetGroup
as a root widget. Check all widgets here
.
Then, we add a Label
and a Button
into it.
public WidgetGroup createUI() {
// create a root container
var root = new WidgetGroup();
root.setSize(100, 100);
root.setBackground(ResourceBorderTexture.BORDERED_BACKGROUND);
// create a label and a button
var label = new LabelWidget();
label.setSelfPosition(20, 20);
label.setText("Hello, World!");
var button = new ButtonWidget();
button.setSelfPosition(20, 60);
button.setSize(60, 20);
// prepare button textures
var backgroundImage = ResourceBorderTexture.BUTTON_COMMON;
var hoverImage = backgroundImage.copy().setColor(ColorPattern.CYAN.color);
var textAbove = new TextTexture("Click me!");
button.setButtonTexture(backgroundImage, textAbove);
button.setClickedTexture(hoverImage, textAbove);
// add the label and button to the root container
root.addWidgets(label, button);
return root;
}
function createUI() {
// create a root container
let root = new WidgetGroup();
root.setSize(100, 100);
root.setBackground(ResourceBorderTexture.BORDERED_BACKGROUND);
// create a label and a button
let label = new LabelWidget();
label.setSelfPosition(20, 20);
label.setText("Hello, World!");
let button = new ButtonWidget();
button.setSelfPosition(20, 60);
button.setSize(60, 20);
// prepare button textures
let backgroundImage = ResourceBorderTexture.BUTTON_COMMON;
let hoverImage = backgroundImage.copy().setColor(ColorPattern.CYAN.color);
let textAbove = new TextTexture("Click me!");
button.setButtonTexture(backgroundImage, textAbove);
button.setClickedTexture(hoverImage, textAbove);
// add the label and button to the root container
root.addWidgets(label, button);
return root;
}
Bind UI functional logic
After the creation of the ui, we should implement the logic of the ui. For example, we want to click the button to change the label text.
Display the UI
Now, let's display the ui we create! We need to specify a UI Factory
to display the ui, which maintains the lifecycle of the ui.
There are four steps:
open ui
create UI in server side
notify to open UI
create UI in remote side
sequenceDiagram
autonumber
Note left of Server: 1. open UI
Note left of Server: 2. create UI in server side
Server->>Remote: 3. notify to open UI
Note right of Remote: 4. create UI in remote side
UI Factory
will help handle the step 3
. Therefore, user should define WHEN to trigger step 1
, and WHAT to be createed in step 2
and step 4
. In general, the UI created on the server side and the remote side is the same in most cases.
LDLib provides two built-in factories:
- Block Entity UI Factory
- Held Item UI Factory
Block Entity UI Factory
This factory allows user to open the ui from a block.
Java
-
Java user should implement
IUIHolder.Block
for your ownBlockEntity
and implement the methodcreateUI(Player entityPlayer)
. -
Call the method
BlockEntityUIFactory.INSTANCE.openUI()
when you want to open the ui.
KubeJS
KubeJS user can do the same thing in an easy way. User can even open the ui for the block (without entity), but less accessibility compared with Java.
- KubeJS user should use
LDLibUI.block(ui_name, e => {})
to create the ui by the givenui_name
. - Call the method
BlockUIFactory.INSTANCE.openUI(player, pos, ui_name)
when you want to open the ui.
public class TestBlockEntity extends BlockEntity implements IUIHolder {
public void onPlayerUse(Player player) {
// step 1 here.
if (player instanceof ServerPlayer serverPlayer) {
BlockEntityUIFactory.INSTANCE.openUI(this, serverPlayer);
}
}
private WidgetGroup createUI() {
// ....
}
@Override
public ModularUI createUI(Player entityPlayer) {
// step 2 and step 4 here
return new ModularUI(createUI(), this, entityPlayer);
}
}
// server script
BlockEvents.rightClicked('test_block_ui', event => {
// step 1 here.
BlockUIFactory.INSTANCE.openUI(event.player, event.block.pos);
})
function createUI() {
// ....
}
LDLibUI.block("test_block_ui", e => {
// step 2 and step 4 here
// let level = e.level
// let pos = e.pos
// let block = e.block
// let player = e.player
var ui = createUI();
e.success(ui);
})
Held Item UI Factory
This factory allows user to open the ui from the held item.
Java
-
Java user should implement
IUIHolder.Item
for your ownItem
and implement the methodcreateUI(Player entityPlayer, HeldItemUIFactory.HeldItemHolder holder)
. -
Call the method
HeldItemUIFactory.INSTANCE.openUI()
when you want to open the ui.
KubeJS
KubeJS user can do the same thing in an easy way. User can even open the ui for the block (without entity), but less accessibility compared with Java.
- KubeJS user should use
LDLibUI.item(ui_name, e => {})
to create the ui by the givenui_name
. - Call the method
ItemUIFactory.INSTANCE.openUI(player, hand, ui_name)
when you want to open the ui.
public class TestItem implements IUIHolder.Item {
@Override
public InteractionResult useOn(UseOnContext context) {
// step 1 here.
if (context.getPlayer() instanceof ServerPlayer serverPlayer) {
HeldItemUIFactory.INSTANCE.openUI(serverPlayer, context.getHand());
}
return InteractionResult.SUCCESS;
}
private WidgetGroup createUI() {
// ....
}
@Override
public ModularUI createUI(Player entityPlayer, HeldItemUIFactory.HeldItemHolder holder) {
// step 2 and step 4
return new ModularUI(createUI(), holder, entityPlayer);
}
}
// server script
ItemEvents.firstRightClicked('minecraft:stick', event => {
// step 1 here.
ItemUIFactory.INSTANCE.openUI(event.player, event.hand, "test_item_ui");
})
function createUI() {
// ....
}
LDLibUI.item("test_item_ui", e => {
// step 2 and step 4
// let player = e.player
// let hand = e.hand
// let held = e.held
var ui = createUI();
e.success(ui);
})