9
0
mirror of https://github.com/HibiscusMC/HMCCosmetics.git synced 2026-01-04 15:41:45 +00:00

Improved GUI

This commit is contained in:
Fisher2911
2022-02-17 19:47:03 -05:00
parent 39583b3685
commit a7892ce434
18 changed files with 466 additions and 69 deletions

View File

@@ -1,13 +1,18 @@
package io.github.fisher2911.hmccosmetics.config;
import com.comphenix.protocol.wrappers.EnumWrappers;
import dev.triumphteam.gui.components.GuiAction;
import dev.triumphteam.gui.guis.GuiItem;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.gui.CosmeticGui;
import io.github.fisher2911.hmccosmetics.message.Message;
import io.github.fisher2911.hmccosmetics.message.MessageHandler;
import io.github.fisher2911.hmccosmetics.message.Placeholder;
import io.github.fisher2911.hmccosmetics.user.User;
import io.github.fisher2911.hmccosmetics.util.Utils;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
@@ -16,17 +21,28 @@ import org.spongepowered.configurate.serialize.TypeSerializer;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.function.Consumer;
public class ActionSerializer implements TypeSerializer<GuiAction<InventoryClickEvent>> {
public class ActionSerializer implements TypeSerializer<List<CosmeticGuiAction>> {
public static final ActionSerializer INSTANCE = new ActionSerializer();
private static final HMCCosmetics plugin;
private static final String OPEN_MENU = "open-menu";
private static final String SET_ITEMS = "set-items";
private static final String ON_EQUIP = "equip";
private static final String ON_REMOVE = "unequip";
private static final String ANY = "any";
private static final String SEND_MESSAGE = "send-message";
private static final String SEND_MESSAGES = "send-messages";
private static final String SEND_COMMAND = "send-command";
private static final String SEND_COMMANDS = "send-commands";
private static final String SOUND = "sound";
private static final String SOUND_NAME = "name";
private static final String SOUND_VOLUME = "volume";
@@ -51,33 +67,43 @@ public class ActionSerializer implements TypeSerializer<GuiAction<InventoryClick
}
@Override
public GuiAction<InventoryClickEvent> deserialize(final Type type, final ConfigurationNode source) {
final var children = source.childrenMap();
final List<Consumer<InventoryClickEvent>> consumers = new ArrayList<>();
for (final var entry : children.entrySet()) {
final String clickType = entry.getKey().toString();
if (clickType == null) continue;
consumers.add(this.parseAction(entry.getValue(), clickType.toUpperCase(Locale.ROOT)));
}
return event -> {
for (final Consumer<InventoryClickEvent> consumer : consumers) {
consumer.accept(event);
}
};
public List<CosmeticGuiAction> deserialize(final Type type, final ConfigurationNode source) {
return this.deserialize(type, new ArrayList<>(), source, CosmeticGuiAction.When.ALL);
}
private Consumer<InventoryClickEvent> parseAction(final ConfigurationNode node, final String clickType) {
private List<CosmeticGuiAction> deserialize(
final Type type,
final List<CosmeticGuiAction> consumers,
final ConfigurationNode source,
final CosmeticGuiAction.When when) {
final var children = source.childrenMap();
for (final var entry : children.entrySet()) {
final String clickType = entry.getKey().toString();
try {
final CosmeticGuiAction.When nextWhen = CosmeticGuiAction.When.valueOf(clickType.toUpperCase());
this.deserialize(type, consumers, entry.getValue(), nextWhen);
} catch (final IllegalArgumentException exception) {
consumers.add(this.parseAction(entry.getValue(), clickType.toUpperCase(Locale.ROOT), when));
}
}
return consumers;
}
private CosmeticGuiAction parseAction(
final ConfigurationNode node,
final String clickType,
final CosmeticGuiAction.When when
) {
final ConfigurationNode openMenuNode = node.node(OPEN_MENU);
final ConfigurationNode sendMessageNode = node.node(SEND_MESSAGE);
final ConfigurationNode soundNode = node.node(SOUND);
final ConfigurationNode soundNameNode = soundNode.node(SOUND_NAME);
final ConfigurationNode volumeNode = soundNode.node(SOUND_VOLUME);
final ConfigurationNode pitchNode = soundNode.node(SOUND_PITCH);
final ConfigurationNode categoryNode = soundNode.node(SOUND_CATEGORY);
final ConfigurationNode setItemsNode = node.node(SET_ITEMS);
final String openMenu = openMenuNode.getString();
final String sendMessage = sendMessageNode.getString();
final SoundData soundData;
@@ -97,24 +123,127 @@ public class ActionSerializer implements TypeSerializer<GuiAction<InventoryClick
}
final ClickType click = Utils.stringToEnum(clickType, ClickType.class, ClickType.UNKNOWN);
final Map<Integer, GuiItem> setItems = this.loadSetItems(setItemsNode);
return event -> {
if (click != ClickType.UNKNOWN && event.getClick() != click) return;
if (!(event.getWhoClicked() instanceof final Player player)) return;
if (soundData != null) {
soundData.play(player);
final Consumer<Player> messageConsumer = this.loadMessages(node, plugin);
return new CosmeticGuiAction(
when,
event -> {
if (click != ClickType.UNKNOWN && event.getClick() != click) return;
if (!(event.getWhoClicked() instanceof final Player player)) return;
if (soundData != null) {
soundData.play(player);
}
if (openMenu != null) plugin.getCosmeticsMenu().openMenu(openMenu, event.getWhoClicked());
messageConsumer.accept(player);
final Optional<User> optionalUser = plugin.getUserManager().get(player.getUniqueId());
if (optionalUser.isEmpty()) return;
final User user = optionalUser.get();
final CosmeticGui gui = user.getOpenGui();
if (gui != null) {
for (final var entry : setItems.entrySet()) {
final GuiItem item = entry.getValue();
gui.updateItem(entry.getKey(), item, user, player);
}
}
}
);
}
private Map<Integer, GuiItem> loadSetItems(final ConfigurationNode node) {
if (node.virtual()) return Collections.emptyMap();
final Map<Integer, GuiItem> setItems = new HashMap<>();
try {
for (final var entry : node.childrenMap().entrySet()) {
if (!(entry.getKey() instanceof final Integer slot)) continue;
final var key = entry.getValue();
final GuiItem guiItem = ItemSerializer.INSTANCE.deserialize(GuiItem.class, key);
if (guiItem == null) continue;
setItems.put(slot, guiItem);
}
} catch (final SerializationException exception) {
HMCCosmetics.getPlugin(HMCCosmetics.class).getLogger().severe(
"Error loading set-items"
);
return Collections.emptyMap();
}
return setItems;
}
private static final String CONSOLE = "console";
private static final String PLAYER = "player";
private Consumer<Player> loadMessages(final ConfigurationNode source, final HMCCosmetics plugin) {
final ConfigurationNode messageNode = source.node(SEND_MESSAGE);
final ConfigurationNode messagesNode = source.node(SEND_MESSAGES);
final ConfigurationNode commandNode = source.node(SEND_COMMAND);
final ConfigurationNode commandsNode = source.node(SEND_COMMANDS);
final List<String> messages = new ArrayList<>();
final List<String> commands = new ArrayList<>();
final String message = messageNode.getString();
if (message != null) messages.add(message);
final String command = commandNode.getString();
if (command != null) commands.add(command);
for (final var node : messagesNode.childrenList()) {
final String listMessage = node.getString();
if (listMessage == null) continue;
messages.add(listMessage);
}
for (final var node : commandsNode.childrenList()) {
final String commandMessage = node.getString();
if (commandMessage == null) continue;
commands.add(commandMessage);
}
return player -> {
final String playerName = player.getName();
final Map<String, String> placeholders = Map.of(Placeholder.PLAYER, playerName);
final MessageHandler messageHandler = plugin.getMessageHandler();
for (final String sendMessage : messages) {
messageHandler.sendMessage(
player,
new Message("", sendMessage),
placeholders
);
}
if (sendMessage != null) plugin.getMessageHandler().sendMessage(
player,
new Message("", sendMessage)
);
if (openMenu != null) plugin.getCosmeticsMenu().openMenu(openMenu, event.getWhoClicked());
for (final String sendCommand : commands) {
final String[] parts = sendCommand.split(":");
if (parts.length < 2) {
Bukkit.dispatchCommand(
Bukkit.getConsoleSender(),
sendCommand.replace(Placeholder.PLAYER, playerName)
);
continue;
}
final String sender = parts[0];
final String commandToSend = parts[1];
if (sender.equalsIgnoreCase(CONSOLE)) {
Bukkit.dispatchCommand(
Bukkit.getConsoleSender(),
commandToSend.replace(Placeholder.PLAYER, playerName)
);
continue;
}
player.chat("/" + commandToSend.replace(Placeholder.PLAYER, playerName));
}
};
}
@Override
public void serialize(final Type type, @Nullable final GuiAction<InventoryClickEvent> obj, final ConfigurationNode node) throws SerializationException {
public void serialize(final Type type, @Nullable final List<CosmeticGuiAction> obj, final ConfigurationNode node) throws SerializationException {
}

View File

@@ -0,0 +1,28 @@
package io.github.fisher2911.hmccosmetics.config;
import org.bukkit.event.inventory.InventoryClickEvent;
import java.util.function.Consumer;
public class CosmeticGuiAction {
private final When when;
private final Consumer<InventoryClickEvent> consumer;
public CosmeticGuiAction(final When when, final Consumer<InventoryClickEvent> consumer) {
this.when = when;
this.consumer = consumer;
}
public void execute(final InventoryClickEvent event, final When when) {
if (this.when != When.ALL && this.when != when) return;
consumer.accept(event);
}
public enum When {
EQUIP,
REMOVE,
ALL
}
}

View File

@@ -26,7 +26,6 @@ import org.bukkit.NamespacedKey;
import org.bukkit.OfflinePlayer;
import org.bukkit.Registry;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -214,7 +213,7 @@ public class ItemSerializer implements TypeSerializer<GuiItem> {
itemFlags(itemFlags).
build();
final GuiAction<InventoryClickEvent> action = ActionSerializer.INSTANCE.deserialize(GuiAction.class, actionNode);
final List<CosmeticGuiAction> actions = ActionSerializer.INSTANCE.deserialize(GuiAction.class, actionNode);
Keys.setKey(itemStack);
@@ -229,7 +228,7 @@ public class ItemSerializer implements TypeSerializer<GuiItem> {
return new ArmorItem(
itemStack,
action,
actions,
Utils.replaceIfNull(idNode.getString(), ""),
lockedLore,
permission,
@@ -240,7 +239,11 @@ public class ItemSerializer implements TypeSerializer<GuiItem> {
} catch (final IllegalArgumentException exception) {
final GuiItem guiItem = dev.triumphteam.gui.builder.item.ItemBuilder.from(itemStack).asGuiItem();
guiItem.setAction(action);
guiItem.setAction(event -> {
for (final CosmeticGuiAction action : actions) {
action.execute(event, CosmeticGuiAction.When.ALL);
}
});
return guiItem;
}
}

View File

@@ -3,11 +3,14 @@ package io.github.fisher2911.hmccosmetics.gui;
import com.comphenix.protocol.wrappers.EnumWrappers;
import dev.triumphteam.gui.components.GuiAction;
import dev.triumphteam.gui.guis.GuiItem;
import io.github.fisher2911.hmccosmetics.config.CosmeticGuiAction;
import io.github.fisher2911.hmccosmetics.util.builder.ColorBuilder;
import io.github.fisher2911.hmccosmetics.util.builder.ItemBuilder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.bukkit.Color;
import org.bukkit.Material;
import org.bukkit.event.inventory.InventoryClickEvent;
@@ -23,23 +26,23 @@ public class ArmorItem extends GuiItem {
private final List<String> lockedLore;
private final String permission;
private final Type type;
private GuiAction<InventoryClickEvent> action;
private List<CosmeticGuiAction> actions;
private boolean dyeable;
private int dye;
public ArmorItem(
@NotNull final ItemStack itemStack,
final GuiAction<InventoryClickEvent> action,
final List<CosmeticGuiAction> actions,
final String id,
final List<String> lockedLore,
final String permission,
final Type type,
final int dye) {
super(itemStack, action);
super(itemStack, null);
this.id = id;
this.lockedLore = lockedLore;
this.action = action;
this.actions = actions;
this.permission = permission;
this.type = type;
this.dye = dye;
@@ -55,7 +58,7 @@ public class ArmorItem extends GuiItem {
super(itemStack);
this.id = id;
this.lockedLore = lockedLore;
this.action = null;
this.actions = new ArrayList<>();
this.permission = permission;
this.type = type;
this.dye = dye;
@@ -71,7 +74,7 @@ public class ArmorItem extends GuiItem {
super(material);
this.id = id;
this.lockedLore = lockedLore;
this.action = null;
this.actions = new ArrayList<>();
this.permission = permission;
this.type = type;
this.dye = dye;
@@ -79,16 +82,16 @@ public class ArmorItem extends GuiItem {
public ArmorItem(
@NotNull final Material material,
@Nullable final GuiAction<InventoryClickEvent> action,
final List<CosmeticGuiAction> actions,
final String id,
final List<String> lockedLore,
final String permission,
final Type type,
final int dye) {
super(material, action);
super(material, null);
this.id = id;
this.lockedLore = lockedLore;
this.action = action;
this.actions = new ArrayList<>();
this.permission = permission;
this.type = type;
this.dye = dye;
@@ -96,17 +99,17 @@ public class ArmorItem extends GuiItem {
public ArmorItem(
@NotNull final ItemStack itemStack,
final GuiAction<InventoryClickEvent> action,
final List<CosmeticGuiAction> actions,
final String id,
final List<String> lockedLore,
final String permission,
final Type type,
final boolean dyeable,
final int dye) {
super(itemStack, action);
super(itemStack, null);
this.id = id;
this.lockedLore = lockedLore;
this.action = action;
this.actions = actions;
this.permission = permission;
this.type = type;
this.dyeable = dyeable;
@@ -124,7 +127,7 @@ public class ArmorItem extends GuiItem {
super(itemStack);
this.id = id;
this.lockedLore = lockedLore;
this.action = null;
this.actions = new ArrayList<>();
this.permission = permission;
this.type = type;
this.dyeable = dyeable;
@@ -142,7 +145,7 @@ public class ArmorItem extends GuiItem {
super(material);
this.id = id;
this.lockedLore = lockedLore;
this.action = null;
this.actions = new ArrayList<>();
this.permission = permission;
this.type = type;
this.dyeable = dyeable;
@@ -161,7 +164,7 @@ public class ArmorItem extends GuiItem {
super(material, action);
this.id = id;
this.lockedLore = lockedLore;
this.action = action;
this.actions = new ArrayList<>();
this.permission = permission;
this.type = type;
this.dyeable = dyeable;
@@ -169,11 +172,11 @@ public class ArmorItem extends GuiItem {
}
public ArmorItem(final ArmorItem armorItem) {
super(armorItem.getItemStack(), armorItem.getAction());
super(armorItem.getItemStack(), null);
this.id = armorItem.getId();
this.lockedLore = new ArrayList<>();
Collections.copy(armorItem.getLockedLore(), this.lockedLore);
this.action = armorItem.getAction();
this.actions = armorItem.getActions();
this.permission = armorItem.getPermission();
this.type = armorItem.getType();
this.dyeable = armorItem.isDyeable();
@@ -199,14 +202,13 @@ public class ArmorItem extends GuiItem {
return lockedLore;
}
public GuiAction<InventoryClickEvent> getAction() {
return this.action;
public List<CosmeticGuiAction> getActions() {
return actions;
}
@Override
public void setAction(final GuiAction<InventoryClickEvent> action) {
super.setAction(action);
this.action = action;
public void setActions(final List<CosmeticGuiAction> actions) {
this.actions.clear();
this.actions.addAll(actions);
}
public String getPermission() {

View File

@@ -4,6 +4,7 @@ import dev.triumphteam.gui.components.GuiAction;
import dev.triumphteam.gui.guis.Gui;
import dev.triumphteam.gui.guis.GuiItem;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.config.CosmeticGuiAction;
import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor;
import io.github.fisher2911.hmccosmetics.message.Adventure;
import io.github.fisher2911.hmccosmetics.message.MessageHandler;
@@ -11,10 +12,13 @@ import io.github.fisher2911.hmccosmetics.message.Messages;
import io.github.fisher2911.hmccosmetics.message.Placeholder;
import io.github.fisher2911.hmccosmetics.user.User;
import io.github.fisher2911.hmccosmetics.util.builder.ItemBuilder;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryClickEvent;
@@ -45,6 +49,7 @@ public class CosmeticGui {
this.guiItemMap = guiItemMap;
this.itemStackMap = new HashMap<>();
this.guiItemMap.forEach((key, value) -> itemStackMap.put(key, value.getItemStack()));
}
private void setItems(final User user) {
@@ -71,7 +76,7 @@ public class CosmeticGui {
final User user,
final ArmorItem armorItem,
final InventoryClickEvent event,
final GuiAction<InventoryClickEvent> actionIfSet) {
final List<CosmeticGuiAction> actions) {
final long current = System.currentTimeMillis();
if ((current - this.lastClicked) / 1000. < COOL_DOWN) {
@@ -93,7 +98,9 @@ public class CosmeticGui {
);
if (!setTo.isEmpty()) {
actionIfSet.execute(event);
executeActions(event, actions, CosmeticGuiAction.When.EQUIP);
} else {
executeActions(event, actions, CosmeticGuiAction.When.REMOVE);
}
final int slot = event.getSlot();
@@ -107,6 +114,16 @@ public class CosmeticGui {
this.gui.updateItem(slot, guiItem);
}
private void executeActions(
final InventoryClickEvent event,
final List<CosmeticGuiAction> actions,
final CosmeticGuiAction.When when
) {
for (final CosmeticGuiAction action : actions) {
action.execute(event, when);
}
}
public void open(final User user, final Player player) {
this.gui = Gui.gui().
title(Adventure.MINI_MESSAGE.deserialize(
@@ -115,6 +132,7 @@ public class CosmeticGui {
create();
this.gui.setDefaultClickAction(event -> event.setCancelled(true));
this.gui.setCloseGuiAction(event -> user.setOpenGui(null));
this.setItems(user);
@@ -124,17 +142,16 @@ public class CosmeticGui {
@Nullable
private GuiItem getGuiItem(final User user, final Player player, final int slot) {
final GuiItem guiItem = this.guiItemMap.get(slot);
if (guiItem == null) {
return null;
}
final ItemStack itemStack = this.itemStackMap.get(slot);
if (itemStack == null) return null;
return this.getGuiItem(user, player, guiItem, itemStack);
}
if (itemStack == null) {
return null;
}
@Nullable
private GuiItem getGuiItem(final User user, final Player player, final GuiItem guiItem, final ItemStack itemStack) {
if (guiItem instanceof final ArmorItem armorItem) {
final String permission =
armorItem.getPermission() == null ? "" : armorItem.getPermission();
@@ -159,7 +176,7 @@ public class CosmeticGui {
return;
}
this.setUserArmor(player, user, cosmeticItem, event, armorItem.getAction());
this.setUserArmor(player, user, cosmeticItem, event, armorItem.getActions());
}
);
}
@@ -172,7 +189,7 @@ public class CosmeticGui {
}
protected ItemStack applyPlaceholders(final User user, final Player player,
final ArmorItem armorItem, final boolean hasPermission) {
final ArmorItem armorItem, final boolean hasPermission) {
final Map<String, String> placeholders = new HashMap<>();
final PlayerArmor playerArmor = user.getPlayerArmor();
@@ -207,6 +224,15 @@ public class CosmeticGui {
build();
}
public void updateItem(final int slot, final GuiItem guiItem, final User user, final Player player) {
final ItemStack itemStack = guiItem.getItemStack().clone();
this.guiItemMap.put(slot, guiItem);
this.itemStackMap.put(slot, itemStack);
final GuiItem setItem = this.getGuiItem(user, player, guiItem, itemStack);
if (setItem == null) return;
this.gui.updateItem(slot, setItem);
}
public CosmeticGui copy() {
return new CosmeticGui(
this.plugin,

View File

@@ -57,10 +57,14 @@ public class CosmeticsMenu {
if (cosmeticGui instanceof final DyeSelectorGui dyeSelectorGui) {
dyeSelectorGui.getGui(user, user.getLastSetItem().getType()).open(humanEntity);
user.setOpenGui(dyeSelectorGui);
return;
}
if (cosmeticGui != null) cosmeticGui.open(user, player);
if (cosmeticGui != null) {
user.setOpenGui(cosmeticGui);
cosmeticGui.open(user, player);
}
}
public void openDefault(final HumanEntity humanEntity) {

View File

@@ -10,6 +10,7 @@ import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.config.CosmeticSettings;
import io.github.fisher2911.hmccosmetics.config.Settings;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.gui.CosmeticGui;
import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor;
import io.github.fisher2911.hmccosmetics.packet.PacketManager;
import org.bukkit.Bukkit;
@@ -42,6 +43,8 @@ public class User {
private boolean hasArmorStand;
private final int armorStandId;
private CosmeticGui openGui;
// List of players that are currently viewing the armorstand
private final Set<UUID> viewing = new HashSet<>();
@@ -221,6 +224,15 @@ public class User {
this.hasArmorStand = false;
}
@Nullable
public CosmeticGui getOpenGui() {
return openGui;
}
public void setOpenGui(final CosmeticGui openGui) {
this.openGui = openGui;
}
public boolean hasArmorStand() {
return hasArmorStand;
}

View File

@@ -0,0 +1,193 @@
title: "<white>" # GUI Title
rows: 5 # Rows in the GUI
items:
1: # GUI Slot number
material: LEATHER_HORSE_ARMOR # Also supports Oraxen items! Format: "oraxen:item_name"
name: "<rainbow>Colorful Hat</rainbow>"
lore: # Lore displayed when the player owns the item
- ""
- "<gray>Enabled: <#6D9DC5>%enabled%"
- "<gray>Allowed: <#6D9DC5>%allowed%"
locked-lore: # Lore displayed when the player does not have the correct permission.
- "<red>You do not own this item!"
amount: 1
model-data: 2 # CustomModelData Number
type: HAT
dyeable: true # Enables dyeable item feature
color: # Sets default color for item. Uses RGB format.
red: 5
green: 230
blue: 100
action: # See how the action system works on the wiki
any:
open-menu: dye-menu
permission: "cosmetics.colorful_hat" # Can be anything you want.
id: colorful_hat # Internal identifier. Can be anything you want.
2:
material: PAPER
name: "<blue>Backpack"
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%enabled%"
- "<gray>Allowed: <#6D9DC5>%allowed%"
locked-lore:
- "<red>You do not own this item!"
amount: 1
model-data: 4
type: BACKPACK
permission: ""
id: backpack
action:
# when the action should be run
# equip = when a cosmetic is equipped
# remove = when a cosmetic is removed
# any all = default, does not need to be specified
equip:
# click type
any:
send-message: "on equip"
remove:
any:
send-message: "on-remove"
any:
# send a message
send-message: "Test first message"
# send a command, format is <sender:command>
# senders can be player or console
send-command: "player:give %player% diamond"
# list of messages
send-messages:
- "Message 1"
- "Message 2"
# list of commands
send-commands:
- "player:help"
- "console:give %player% gold_ingot"
# set items in the specified slots in the inventory
# works with all actions
# sets items in the next inventory if open-menu is specified
set-items:
12:
material: PAPER
name: "<red>Backpack"
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%enabled%"
- "<gray>Allowed: <#6D9DC5>%allowed%"
locked-lore:
- "<red>You do not own this item!"
amount: 1
model-data: 4
type: BACKPACK
permission: ""
id: backpack
action:
any:
send-message: "It worked?"
set-items:
12:
material: PAPER
name: "<rainbow>Backpack"
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%enabled%"
- "<gray>Allowed: <#6D9DC5>%allowed%"
locked-lore:
- "<red>You do not own this item!"
amount: 1
model-data: 4
type: BACKPACK
permission: ""
id: backpack
3:
material: PAPER
name: "<blue>Lantern Cosmetic"
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%enabled%"
- "<gray>Allowed: <#6D9DC5>%allowed%"
locked-lore:
- "<red>You do not own this item!"
amount: 1
model-data: 5
type: OFF_HAND
permission: ""
id: lantern_cosmetic
4:
material: PAPER
name: "<blue>Baseball Hat"
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%enabled%"
- "<gray>Allowed: <#6D9DC5>%allowed%"
locked-lore:
- "<red>You do not own this item!"
amount: 1
model-data: 6
type: HAT
permission: ""
id: baseball_hat
5:
material: DIAMOND_CHESTPLATE
name: "<blue>Cosmetic Chestplate"
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%enabled%"
- "<gray>Allowed: <#6D9DC5>%allowed%"
locked-lore:
- "<red>You do not own this item!"
amount: 1
type: CHEST_PLATE
permission: ""
id: chestplate
6:
material: DIAMOND_LEGGINGS
name: "<blue>Cosmetic Leggings"
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%enabled%"
- "<gray>Allowed: <#6D9DC5>%allowed%"
locked-lore:
- "<red>You do not own this item!"
amount: 1
type: PANTS
permission: ""
id: pants
7:
material: DIAMOND_BOOTS
name: "<blue>Cosmetic Boots"
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%enabled%"
- "<gray>Allowed: <#6D9DC5>%allowed%"
locked-lore:
- "<red>You do not own this item!"
amount: 1
type: BOOTS
permission: ""
id: boots
37:
material: PAPER
name: "<#40B7D6>Previous Page"
amount: 1
model-data: 1
action:
any:
open-menu: menu-2
40:
material: PAPER
name: "<rainbow>Customization Menu</rainbow>"
amount: 1
model-data: 3
action:
any:
open-menu: dye-menu
43:
material: PAPER
name: "<#40B7D6>Next Page"
amount: 1
model-data: 2
action:
any:
open-menu: menu-2