Skip to content

Configurable GUIs

Hamza Coşkun edited this page Mar 27, 2024 · 37 revisions

Beggining to use configurable GUIs

ObliviateInvs can manage your YAML configuration files to load GUIs. It is super useful for creating user-friendly plugins. Just to let you know, that carrying GUI codes to configuration files comes with some issues and restrictions. Because you have to support complex items like fireworks, books, etc. Also, your icons may need complex behavior and graphics.

ObliviateInvs solves these issues and breaks these restrictions. Also, we provided rich configuration stuff that came to our mind.

TL;DR

Copy the code blocks in steps 1,2,3.

Step 1

Specify your menu configuration section/file to the API.

It's called a 'default table' because you can specify different configuration files for each GUI.

public class Test extends JavaPlugin {

	@Override
	public void onEnable() {
		new InventoryAPI(this).init();
		ConfigurableGuiCache.resetCaches(); //not obligatory but recommended at configuration reload methods.
		GuiConfigurationTable.setDefaultConfigurationTable(new GuiConfigurationTable(getConfig()));
	}
}

Step 2

Extend ConfigurableGui class. This class extends the Gui class. You cannot set the title and size of configurable GUIs in the constructor. These attributes are automatically set on init. If you want to override them, you can use setTitle, setSize methods after super() call.

The second parameter is the id of the GUI. This id will be used in configuration sections. If you want to change the section name but you don't want to change id of the GUI, then override getSectionPath() method.

public class ConfigurableTestGUI extends ConfigurableGui {

	public ConfigurableTestGUI(Player player) {
		super(player, "example-configurable-gui");
	}
}

Step 3

Put icons on your GUI. Icons are split into two. Functional and Dysfunctional.

Dysfunctional icons are completely configuration file based and independent of any extra in-build code. You can add custom dysfunctional icons only using the config. For example, filler items.

Functional icons are executable icons. You must program these icons in-build.

Note: ObliviateInvs caches serialized itemstacks as itemstack (not as configuration section). Feel relaxed about using getIcon() or addConfigIcon() methods very often.

Passing names of functional icons is not required but if you don't, obliviate-invs will put these icons as dysfunctional until your addConfigIcon method overrides them. If you do not put the functional icons in some cases, this behavior may cause some misunderstanding for users.

Code

        @Override
	public void onOpen(InventoryOpenEvent event) {
		putDysfunctionalIcons("functional-test-icon"); // passing functional icons' names are recommended

		addConfigIcon("functional-test-icon").onClick(e -> {
			player.sendMessage("You clicked");
		});
	}

Config

example-configurable-gui:
  title: 'Custom Title'
  row: 5
  icons:
    filler-item:
      material: BLACK_STAINED_GLASS_PANE
      display-name: '&a'
      slot: 0-8
    functional-test-icon:
      material: DIAMOND_BOOTS
      display-name: '&aGem'
      slot: 4
      enchantments:
        - 'DEPTH_STRIDER:1'
      item-flags:
        #- 'HIDE_ENCHANTS'
        - '*'

Minimal Configuration

You must specify the sections below in your config file.

example-configurable-gui:
  title: 'Custom Title'
  row: 5
  icons:
    functional-test-icon:
      material: DIAMOND_BOOTS
      slot: 4

Result

image

Also, you can get dysfunctional icons using:

List<DysfunctionalIcon> = super.getDysfunctionalIcons()

What Are GUI Configuration Tables

GUI Configuration Tables define your GUI config and their section names. For example, imagine that you want to make different configuration files for each gui thennnn you have to make different gui configuration tables for each gui. Also, GUI configuration files define section names too.

Defining custom config file to your GUI example

new MyConfigurableGui(player, "gui-id", new GuiConfigurationTable(getConfig())).open();

Default

example-configurable-gui:
  title: 'Custom Title'
  row: 5
  icons:
    functional-test-icon:
      material: DIAMOND_BOOTS
      slot: 4
new GuiConfigurationTable(myMenuConfig).setMaterialSectionName("type");

Changes the 'material' section name to 'type' for GUIs in myMenuConfig.

After the code above

example-configurable-gui:
  title: 'Custom Title'
  row: 5
  icons:
    functional-test-icon:
      type: DIAMOND_BOOTS #<----
      slot: 4

Manipluating Itemstacks At the Intermediate Of Put Process

Sometimes developers need to edit itemstacks before they are added to the GUI. For example, you may want to apply skin to player heads.

Example:

addConfigIcon("any-icon", item -> {
    if (!(item.hasItemMeta() && item.getItemMeta() instanceof SkullMeta meta)) return item;
    meta.setOwningPlayer(Bukkit.getOfflinePlayer(player.getUniqueId()));
    item.setItemMeta(meta);
    return item;
}).onClick(e -> {
    //handle click event
});

Manual Deserializing ItemStacks

Sometimes you may need to deserialize itemstacks manually. obliviate-invs uses mc.obliviate.inventory.configurable.util.ItemStackSerializer.class to deserialize.

Deserializing YAML Configuration To Item

ItemStack item = ItemStackSerializer.deserializeItemStack(section, guiConfigurationTable);

This method deserializes a configuration as an itemstack. This method parses item type, name, lore, amount, durability, enchantment, item flags, custom model data and unbreakability. However, this method does not parse placeholders because this type of itemstack must be raw to caching itemstacks and applying placeholders at runtime.

Placeholder Appling

PlaceholderUtil placeholderUtil = new PlaceholderUtil().add("{any_placeholder}", textValueOfThePlaceholder);
ItemStackSerializer.applyPlaceholdersToItemStack(item, placeholderUtil);

Serializing An Item To YAML Configuration

example-root-section:
  item:

section variable defines example-root-section.item.

ItemStackSerializer.serializeItemStack(item, section);

After the code above

example-root-section:
  item:
    material: STONE
    display-name: 'a stone'

Serializing Complex Item Datas

Some item stacks have complex metadata. For example; potions, banners, fireworks, enchanted books, written books, and skulls. ItemStack Serializer of obliviate-invs is not designed for these metadatas but it does a favor for developers. The serializer is called Bukkit's own serializer methods.

item1:
  material: DIAMOND_CHESTPLATE
item2:
  bukkit-serializing: true
  item:
    ==: org.bukkit.inventory.ItemStack
    type: ENCHANTED_BOOK
    meta:
      ==: ItemMeta
      meta-type: ENCHANTED
      stored-enchants:
        PROTECTION_PROJECTILE: 4
  • item1 is a simple diamond chestplate. It doesn't have any metadata.
  • item2 is an enchanted book. Enchantment books have custom NBTs for storing enchantments. So, the serializer is called Bukkit's serializer.

Gui Configuration Sections

title

Defines title text of the Gui.

title: 'Select a game to play'

row

Defines row amount of the GUI.

row: 5

slot

Defines slot of the icon. If the icon is a dysfunctional icon, you can specify multiple slot.

Examples: slot: 5

Dysfunctional Icon only:

slot: 1,3,5

slot: 1-5 (represents 1,2,3,4,5)

material

Defines type of the icon

Examples:

material: STONE

display-name

Defines the name of the icon.

Examples:

display-name: 'Gem'

lore

Defines description of the icon.

Examples:

lore:
  - 'line 1'
  - 'line 2'

amount

Defines amount of the icon.

Examples:

amount: 5

enchantments

Defines enchantments of the icon. (supports enchanted books)

Examples:

enchantments:
  - 'PROTECTION:2'
  - 'UNBREAKING:5'

custom-model-data

Defines custom model data of the icon. (only supports 1.14+ servers)

Examples:

custom-model-data: 500

durability

defines durability/damage of the icon.

Examples:

durability: 30

unbreakable

Defines the icon is unbreakable or not. (only supports 1.11+ servers)

Examples:

unbreakable: true

item-flags

Defines item flags of the icon. You can hide additional informations from the item. '*' wildcard is allowed.

Examples:

item-flags:
  - '*'
item-flags:
  - 'HIDE_ENCHANTS'

glow

Defines the icon should glow or not. If the icon is enchanted glow section does not matter. This section adds an enchantment and hides using item flags.

Examples:

glow: true