9
0
mirror of https://github.com/HibiscusMC/HMCCosmetics.git synced 2026-01-03 22:26:21 +00:00

Added tokens

This commit is contained in:
Fisher2911
2022-03-06 15:08:30 -05:00
parent a55ad14934
commit 960bb97a04
20 changed files with 447 additions and 14 deletions

View File

@@ -5,11 +5,13 @@ import com.comphenix.protocol.ProtocolManager;
import io.github.fisher2911.hmccosmetics.command.CosmeticsCommand;
import io.github.fisher2911.hmccosmetics.concurrent.Threads;
import io.github.fisher2911.hmccosmetics.config.Settings;
import io.github.fisher2911.hmccosmetics.config.TokenLoader;
import io.github.fisher2911.hmccosmetics.cosmetic.CosmeticManager;
import io.github.fisher2911.hmccosmetics.database.Database;
import io.github.fisher2911.hmccosmetics.database.DatabaseFactory;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.gui.CosmeticsMenu;
import io.github.fisher2911.hmccosmetics.gui.Token;
import io.github.fisher2911.hmccosmetics.hook.HookManager;
import io.github.fisher2911.hmccosmetics.hook.CitizensHook;
import io.github.fisher2911.hmccosmetics.hook.item.ItemsAdderHook;
@@ -54,6 +56,7 @@ public class HMCCosmetics extends JavaPlugin {
private CosmeticManager cosmeticManager;
private MessageHandler messageHandler;
private CosmeticsMenu cosmeticsMenu;
private TokenLoader tokenLoader;
private CommandManager commandManager;
private Database database;
@@ -70,8 +73,9 @@ public class HMCCosmetics extends JavaPlugin {
this.settings = new Settings(this);
this.messageHandler = new MessageHandler(this);
this.userManager = new UserManager(this);
this.cosmeticManager = new CosmeticManager(new HashMap<>());
this.cosmeticManager = new CosmeticManager(new HashMap<>(), new HashMap<>());
this.cosmeticsMenu = new CosmeticsMenu(this);
this.tokenLoader = new TokenLoader(this);
this.userManager.startTeleportTask();
@@ -164,8 +168,15 @@ public class HMCCosmetics extends JavaPlugin {
);
completionHandler.register("#ids",
resolver ->
this.cosmeticManager.getAll().stream().map(ArmorItem::getId)
this.cosmeticManager.getAllArmorItems().stream().map(ArmorItem::getId)
.collect(Collectors.toList()));
completionHandler.register("#tokens",
resolver ->
this.cosmeticManager.getAllTokens().stream().map(Token::getId)
.collect(Collectors.toList()));
completionHandler.register("#menus",
resolver -> new ArrayList<>(this.cosmeticsMenu.getMenus())
);
completionHandler.register("#npc-args",
resolver -> List.of(CosmeticsCommand.NPC_REMOVE, CosmeticsCommand.NPC_APPLY));
completionHandler.register("#npcs", resolver -> {
@@ -185,6 +196,7 @@ public class HMCCosmetics extends JavaPlugin {
this.settings.load();
this.messageHandler.load();
this.cosmeticsMenu.load();
this.tokenLoader.load();
Translation.getInstance().load();
this.database.load();
}, 1);
@@ -196,6 +208,7 @@ public class HMCCosmetics extends JavaPlugin {
this.settings.load();
this.messageHandler.load();
this.cosmeticsMenu.reload();
this.tokenLoader.load();
Translation.getInstance().load();
});
}

View File

@@ -3,8 +3,10 @@ package io.github.fisher2911.hmccosmetics.command;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.config.Settings;
import io.github.fisher2911.hmccosmetics.config.WardrobeSettings;
import io.github.fisher2911.hmccosmetics.cosmetic.CosmeticManager;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.gui.CosmeticsMenu;
import io.github.fisher2911.hmccosmetics.gui.Token;
import io.github.fisher2911.hmccosmetics.hook.HookManager;
import io.github.fisher2911.hmccosmetics.hook.CitizensHook;
import io.github.fisher2911.hmccosmetics.message.Message;
@@ -38,6 +40,7 @@ public class CosmeticsCommand extends CommandBase {
private final UserManager userManager;
private final MessageHandler messageHandler;
private final CosmeticsMenu cosmeticsMenu;
private final CosmeticManager cosmeticManager;
private final Settings settings;
public CosmeticsCommand(final HMCCosmetics plugin) {
@@ -45,15 +48,23 @@ public class CosmeticsCommand extends CommandBase {
this.userManager = this.plugin.getUserManager();
this.messageHandler = this.plugin.getMessageHandler();
this.cosmeticsMenu = this.plugin.getCosmeticsMenu();
this.cosmeticManager = this.plugin.getCosmeticManager();
this.settings = this.plugin.getSettings();
}
@Default
@Permission(io.github.fisher2911.hmccosmetics.message.Permission.DEFAULT_COMMAND)
public void defaultCommand(final Player player) {
this.defaultCommand(player, CosmeticsMenu.DEFAULT_MAIN_MENU);
}
@SubCommand("menu")
@Permission(io.github.fisher2911.hmccosmetics.message.Permission.DEFAULT_COMMAND)
public void defaultCommand(final Player player, @Completion("#menus") @me.mattstudios.mf.annotations.Optional String menu) {
final Optional<User> optionalUser = this.userManager.get(player.getUniqueId());
if (menu == null) menu = CosmeticsMenu.DEFAULT_MAIN_MENU;
if (optionalUser.isEmpty()) {
this.cosmeticsMenu.openDefault(player);
this.cosmeticsMenu.openMenu(menu, player);
return;
}
final User user = optionalUser.get();
@@ -67,7 +78,7 @@ public class CosmeticsCommand extends CommandBase {
Messages.CLOSED_WARDROBE
);
}
this.cosmeticsMenu.openDefault(player);
this.cosmeticsMenu.openMenu(menu, player);
}
@SubCommand("reload")
@@ -366,6 +377,42 @@ public class CosmeticsCommand extends CommandBase {
);
}
@SubCommand("token")
@Permission(io.github.fisher2911.hmccosmetics.message.Permission.GIVE_TOKEN)
public void token(final CommandSender sender, @Completion("#tokens") final String tokenId, @me.mattstudios.mf.annotations.Optional Player giveTo) {
if (!(sender instanceof Player) && giveTo == null) {
this.messageHandler.sendMessage(
sender,
Messages.MUST_BE_PLAYER
);
return;
}
if (giveTo == null) {
giveTo = ((Player) sender);
}
final Token token = this.cosmeticManager.getToken(tokenId);
if (token == null) {
this.messageHandler.sendMessage(
sender,
Messages.ITEM_NOT_FOUND
);
return;
}
giveTo.getInventory().addItem(token.getItemStack().clone());
final String tokenName = token.getArmorItem().getItemName();
this.messageHandler.sendMessage(
sender,
Messages.GAVE_TOKEN,
Map.of(Placeholder.ID, tokenName,
Placeholder.PLAYER, giveTo.getDisplayName())
);
this.messageHandler.sendMessage(
giveTo,
Messages.RECEIVED_TOKEN,
Map.of(Placeholder.ID, tokenName)
);
}
private void setNpcCosmetic(final CitizensHook hook, final CommandSender sender, final int npcId, final ArmorItem item) {
final boolean isSet = hook.setNpcCosmetic(npcId, item);
if (!isSet) {

View File

@@ -0,0 +1,37 @@
package io.github.fisher2911.hmccosmetics.config;
import io.github.fisher2911.hmccosmetics.gui.CosmeticGui;
import io.github.fisher2911.hmccosmetics.gui.TokenGui;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
import org.spongepowered.configurate.serialize.TypeSerializer;
import java.lang.reflect.Type;
public class TokenGuiSerializer implements TypeSerializer<TokenGui> {
public static final TokenGuiSerializer INSTANCE = new TokenGuiSerializer();
private static final String TOKEN_SLOT = "token-slot";
private static final String COSMETIC_SLOT = "cosmetic-slot";
private TokenGuiSerializer() {}
@Override
public TokenGui deserialize(final Type type, final ConfigurationNode source) throws SerializationException {
final CosmeticGui cosmeticGui = GuiSerializer.INSTANCE.deserialize(CosmeticGui.class, source);
final ConfigurationNode tokenSlotNode = source.node(TOKEN_SLOT);
final ConfigurationNode cosmeticSlotNode = source.node(COSMETIC_SLOT);
return new TokenGui(
cosmeticGui,
tokenSlotNode.getInt(),
cosmeticSlotNode.getInt()
);
}
@Override
public void serialize(final Type type, @Nullable final TokenGui obj, final ConfigurationNode node) throws SerializationException {
}
}

View File

@@ -0,0 +1,55 @@
package io.github.fisher2911.hmccosmetics.config;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.cosmetic.CosmeticManager;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.gui.Token;
import org.bukkit.inventory.ItemStack;
import org.spongepowered.configurate.ConfigurateException;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
import java.io.File;
import java.nio.file.Path;
public class TokenLoader {
private static final String FILE_NAME = "tokens.yml";
private static final String TOKEN_PATH = "tokens";
private static final String ID_PATH = "id";
private final HMCCosmetics plugin;
private final CosmeticManager cosmeticManager;
public TokenLoader(final HMCCosmetics plugin) {
this.plugin = plugin;
this.cosmeticManager = this.plugin.getCosmeticManager();
}
public void load() {
final Path path = Path.of(this.plugin.getDataFolder().getPath(), FILE_NAME);
final File file = path.toFile();
if (!file.exists()) {
this.plugin.saveResource(FILE_NAME, false);
}
final YamlConfigurationLoader loader = YamlConfigurationLoader.
builder().
defaultOptions(opts -> opts.serializers(build -> build.register(ItemStack.class, ItemSerializer.INSTANCE))).
path(path).
build();
try {
final ConfigurationNode source = loader.load().node(TOKEN_PATH);
for (final var entry : source.childrenMap().entrySet()) {
final var node = entry.getValue();
final String id = node.node(ID_PATH).getString();
final ItemStack itemStack = node.get(ItemStack.class);
final ArmorItem armorItem = this.cosmeticManager.getArmorItem(id);
if (armorItem == null) {
this.plugin.getLogger().severe("Could not find armor item for token: " + id + " with id: " + id);
}
this.cosmeticManager.addToken(new Token(itemStack, armorItem));
}
} catch (final ConfigurateException exception) {
this.plugin.getLogger().severe("Error loading tokens!");
}
}
}

View File

@@ -1,15 +1,22 @@
package io.github.fisher2911.hmccosmetics.cosmetic;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.gui.Token;
import io.github.fisher2911.hmccosmetics.util.Keys;
import org.bukkit.inventory.ItemStack;
import org.bukkit.persistence.PersistentDataType;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.Map;
import org.jetbrains.annotations.Nullable;
public class CosmeticManager {
private final Map<String, Token> tokenMap;
private final Map<String, ArmorItem> armorItemMap;
public CosmeticManager(final Map<String, ArmorItem> armorItemMap) {
public CosmeticManager(final Map<String, Token> tokenMap, final Map<String, ArmorItem> armorItemMap) {
this.tokenMap = tokenMap;
this.armorItemMap = armorItemMap;
}
@@ -22,7 +29,7 @@ public class CosmeticManager {
this.armorItemMap.put(armorItem.getId(), armorItem);
}
public Collection<ArmorItem> getAll() {
public Collection<ArmorItem> getAllArmorItems() {
return this.armorItemMap.values();
}
@@ -30,4 +37,31 @@ public class CosmeticManager {
return armorItemMap;
}
@Nullable
public Token getToken(final String id) {
return this.tokenMap.get(id);
}
public void addToken(final Token token) {
this.tokenMap.put(token.getId(), token);
}
public Collection<Token> getAllTokens() {
return this.tokenMap.values();
}
public Map<String, Token> getTokenMap() {
return this.tokenMap;
}
@Nullable
public Token getToken(final ItemStack itemStack) {
final String id = Keys.getValue(itemStack, Keys.TOKEN_KEY, PersistentDataType.STRING);
if (id == null) return null;
return this.tokenMap.get(id);
}
public boolean isToken(final ItemStack itemStack) {
return Keys.hasKey(itemStack, Keys.TOKEN_KEY, PersistentDataType.STRING);
}
}

View File

@@ -6,6 +6,7 @@ import io.github.fisher2911.hmccosmetics.config.ArmorItemSerializer;
import io.github.fisher2911.hmccosmetics.config.DyeGuiSerializer;
import io.github.fisher2911.hmccosmetics.config.GuiSerializer;
import io.github.fisher2911.hmccosmetics.config.ItemSerializer;
import io.github.fisher2911.hmccosmetics.config.TokenGuiSerializer;
import io.github.fisher2911.hmccosmetics.cosmetic.CosmeticManager;
import io.github.fisher2911.hmccosmetics.user.User;
import io.github.fisher2911.hmccosmetics.user.Wardrobe;
@@ -20,8 +21,10 @@ import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
import java.io.File;
import java.nio.file.Path;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
@@ -30,6 +33,7 @@ public class CosmeticsMenu {
public static final String DEFAULT_MAIN_MENU = "main";
public static final String DEFAULT_DYE_MENU = "dye-menu";
public static final String DEFAULT_TOKEN_MENU = "token-menu";
private final HMCCosmetics plugin;
private final CosmeticManager cosmeticManager;
@@ -68,12 +72,16 @@ public class CosmeticsMenu {
}
}
public Set<String> getMenus() {
return this.guiMap.keySet();
}
public void openDefault(final HumanEntity humanEntity) {
this.openMenu(DEFAULT_MAIN_MENU, humanEntity);
}
public void reload() {
for (final ArmorItem armorItem : this.cosmeticManager.getAll()) {
for (final ArmorItem armorItem : this.cosmeticManager.getAllArmorItems()) {
Bukkit.getPluginManager().removePermission(new Permission(armorItem.getPermission()));
}
this.load();
@@ -108,6 +116,7 @@ public class CosmeticsMenu {
private static final String GUI_TYPE = "gui-type";
private static final String DYE_TYPE = "dye";
private static final String TOKEN_TYPE = "token";
public void load() {
this.guiMap.clear();
@@ -132,6 +141,15 @@ public class CosmeticsMenu {
);
}
if (!Path.of(this.plugin.getDataFolder().getPath(),
"menus",
DEFAULT_TOKEN_MENU + ".yml").toFile().exists()) {
this.plugin.saveResource(
new File("menus", DEFAULT_TOKEN_MENU + ".yml").getPath(),
false
);
}
if (!file.exists() ||
!file.isDirectory()) {
this.plugin.getLogger().severe("No directory found");
@@ -156,6 +174,7 @@ public class CosmeticsMenu {
build.register(WrappedGuiItem.class, ArmorItemSerializer.INSTANCE);
build.register(CosmeticGui.class, GuiSerializer.INSTANCE);
build.register(DyeSelectorGui.class, DyeGuiSerializer.INSTANCE);
build.register(TokenGui.class, TokenGuiSerializer.INSTANCE);
}))
.build();
@@ -177,6 +196,13 @@ public class CosmeticsMenu {
continue;
}
System.out.println("Type of gui is: " + type);
if (TOKEN_TYPE.equals(type)) {
this.guiMap.put(id, TokenGuiSerializer.INSTANCE.deserialize(TokenGui.class, source));
this.plugin.getLogger().info("Loaded token gui: " + id);
continue;
}
final CosmeticGui gui = source.get(CosmeticGui.class);
if (gui == null) continue;

View File

@@ -0,0 +1,29 @@
package io.github.fisher2911.hmccosmetics.gui;
import io.github.fisher2911.hmccosmetics.util.Keys;
import org.bukkit.inventory.ItemStack;
import org.bukkit.persistence.PersistentDataType;
public class Token {
private final ItemStack itemStack;
private final ArmorItem armorItem;
public Token(final ItemStack itemStack, final ArmorItem armorItem) {
this.itemStack = itemStack;
this.armorItem = armorItem;
Keys.setKey(this.itemStack, Keys.TOKEN_KEY, PersistentDataType.STRING, this.armorItem.getId());
}
public String getId() {
return this.armorItem.getId();
}
public ItemStack getItemStack() {
return itemStack;
}
public ArmorItem getArmorItem() {
return armorItem;
}
}

View File

@@ -0,0 +1,118 @@
package io.github.fisher2911.hmccosmetics.gui;
import com.google.common.collect.HashBiMap;
import dev.triumphteam.gui.guis.GuiItem;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.cosmetic.CosmeticManager;
import io.github.fisher2911.hmccosmetics.message.Messages;
import io.github.fisher2911.hmccosmetics.message.Placeholder;
import io.github.fisher2911.hmccosmetics.user.User;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import java.util.HashMap;
import java.util.Map;
public class TokenGui extends CosmeticGui {
private final int tokenSlot;
private final int cosmeticSlot;
private final CosmeticManager cosmeticManager;
public TokenGui(final CosmeticGui gui, final int tokenSlot, final int cosmeticSlot) {
this(gui.plugin, gui.title, gui.rows, gui.guiItemMap, tokenSlot, cosmeticSlot);
}
public TokenGui(final HMCCosmetics plugin, final String title, final int rows, final Map<Integer, GuiItem> guiItemMap, final int tokenSlot, final int cosmeticSlot) {
super(plugin, title, rows, guiItemMap);
this.tokenSlot = tokenSlot;
this.cosmeticSlot = cosmeticSlot;
this.cosmeticManager = this.plugin.getCosmeticManager();
}
@Override
public void open(final User user, final Player player) {
player.sendMessage("Opened GUI");
super.open(user, player);
this.gui.setDefaultClickAction(event -> {
player.sendMessage("Test");
final int slot = event.getSlot();
final Inventory inventory = event.getClickedInventory();
if (inventory == null) {
event.setCancelled(true);
return;
}
if (event.getClickedInventory().equals(event.getView().getBottomInventory())) {
player.sendMessage("Same inventory");
return;
}
player.sendMessage("Not same");
if (slot != tokenSlot && slot != this.cosmeticSlot) {
event.setCancelled(true);
return;
}
final ItemStack inHand = event.getCursor();
if (slot == this.tokenSlot) {
final Token token = this.cosmeticManager.getToken(inHand);
if (token == null) {
event.setCancelled(true);
return;
}
final ArmorItem item = token.getArmorItem();
inventory.setItem(this.cosmeticSlot, item.getItemStack(ArmorItem.Status.ALLOWED));
return;
}
final ItemStack tokenItem = event.getInventory().getItem(this.tokenSlot);
if (tokenItem == null) {
event.setCancelled(true);
return;
}
final Token token = this.cosmeticManager.getToken(tokenItem);
if (token == null) {
event.setCancelled(true);
return;
}
tokenItem.setAmount(tokenItem.getAmount() - 1);
inventory.setItem(this.tokenSlot, tokenItem);
final ItemStack clicked = event.getCurrentItem();
final ArmorItem armorItem = token.getArmorItem();
if (clicked == null) return;
if (user.hasPermissionToUse(armorItem)) {
this.messageHandler.sendMessage(
player,
Messages.ALREADY_UNLOCKED,
Map.of(Placeholder.ID, armorItem.getItemName())
);
return;
}
clicked.setAmount(0);
player.addAttachment(this.plugin, armorItem.getPermission(), true);
this.messageHandler.sendMessage(
player,
Messages.TRADED_TOKEN,
Map.of(Placeholder.ID, armorItem.getItemName())
);
});
this.gui.setCloseGuiAction(event -> {
final Inventory inventory = event.getInventory();
final ItemStack tokens = inventory.getItem(this.tokenSlot);
event.getPlayer().getInventory().addItem(tokens);
user.setOpenGui(null);
});
}
@Override
public TokenGui copy() {
return new TokenGui(
this.plugin,
super.title,
super.rows,
new HashMap<>(super.guiItemMap),
this.tokenSlot,
this.cosmeticSlot
);
}
}

View File

@@ -69,7 +69,7 @@ public class Messages {
<#5AE4B5>• <#40B7D6>/cosmetics - <#6D9DC5>Opens cosmetics GUI.
<#5AE4B5>• <#40B7D6>/cosmetics dye <gray><BACKPACK/HAT></gray> - <#6D9DC5>Opens dye menu for specified cosmetic.
<#5AE4B5>• <#40B7D6>/cosmetics dye <gray>\\BACKPACK/HAT></gray> - <#6D9DC5>Opens dye menu for specified cosmetic.
<#5AE4B5>• <#40B7D6>/cosmetics help - <#6D9DC5>Opens this menu.
@@ -88,7 +88,14 @@ public class Messages {
new Message("cannot-use-portable-wardrobe", "<red>You cannot use the portable wardrobe!");
public static final Message OPENED_OTHER_WARDROBE =
new Message("opened-other-wardrobe", "<green>Opening " + Placeholder.PLAYER + "'s wardrobe.");
public static final Message GAVE_TOKEN =
new Message("gave-token", "<green>You gave " + Placeholder.PLAYER + " a " + Placeholder.ID + " token");
public static final Message RECEIVED_TOKEN =
new Message("received-token", "<green>You were given a " + Placeholder.ID + " token");
public static final Message TRADED_TOKEN =
new Message("traded-token", "<green>You have received the cosmetic: " + Placeholder.ID);
public static final Message ALREADY_UNLOCKED =
new Message("alread-unlocked", "<green>You have already unlocked the cosmetic: " + Placeholder.ID);
public static final Message SET_OTHER_BACKPACK = new Message(
"set-other-backpack", "<green>You have set the backpack of " +
Placeholder.PLAYER + " to " + Placeholder.TYPE + "."

View File

@@ -10,5 +10,6 @@ public class Permission {
public static final String PORTABLE_WARDROBE = "hmccosmetics.cmd.wardrobe.portable";
public static final String WARDROBE = "hmccosmetics.cmd.wardrobe";
public static final String OPEN_OTHER_WARDROBE = "hmccosmetics.cmd.wardrobe.other";
public static final String GIVE_TOKEN = "hmccosmetics.cmd.token.give";
}

View File

@@ -5,12 +5,13 @@ import org.bukkit.NamespacedKey;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataType;
import org.checkerframework.checker.nullness.qual.Nullable;
public class Keys {
static HMCCosmetics plugin = HMCCosmetics.getPlugin(HMCCosmetics.class);
public static final NamespacedKey ITEM_KEY = new NamespacedKey(plugin, "cosmetic");
public static final NamespacedKey ARMOR_STAND_KEY = new NamespacedKey(plugin, "armor-stand");
public static final NamespacedKey TOKEN_KEY = new NamespacedKey(plugin, "token-key");
public static void setKey(final ItemStack itemStack) {
final ItemMeta itemMeta = itemStack.getItemMeta();
@@ -24,6 +25,22 @@ public class Keys {
itemStack.setItemMeta(itemMeta);
}
public static <T, Z> void setKey(
final ItemStack itemStack,
final NamespacedKey key,
final PersistentDataType<T, Z> type,
final Z value) {
final ItemMeta itemMeta = itemStack.getItemMeta();
if (itemMeta == null) {
return;
}
itemMeta.getPersistentDataContainer().set(key, type, value);
itemStack.setItemMeta(itemMeta);
}
public static boolean hasKey(final ItemStack itemStack) {
final ItemMeta itemMeta = itemStack.getItemMeta();
@@ -34,4 +51,24 @@ public class Keys {
return itemMeta.getPersistentDataContainer().has(ITEM_KEY, PersistentDataType.BYTE);
}
public static <T, Z> boolean hasKey(final ItemStack itemStack, final NamespacedKey key, final PersistentDataType<T, Z> type) {
final ItemMeta itemMeta = itemStack.getItemMeta();
if (itemMeta == null) {
return false;
}
return itemMeta.getPersistentDataContainer().has(key, type);
}
@Nullable
public static <T, Z> Z getValue(final ItemStack itemStack, final NamespacedKey key, final PersistentDataType<T, Z> type) {
final ItemMeta itemMeta = itemStack.getItemMeta();
if (itemMeta == null) {
return null;
}
return itemMeta.getPersistentDataContainer().get(key, type);
}
}

View File

@@ -0,0 +1,14 @@
title: "<white>Token Menu" #GUI Title
rows: 5 # Rows in the GUI
token-slot: 0
cosmetic-slot: 1
gui-type: token
items:
43:
material: PAPER
name: "<#40B7D6>Next Page"
amount: 1
model-data: 2
action:
any:
open-menu: menu-2

View File

@@ -45,7 +45,7 @@ help-command: "<#6D9DC5><st> </st> %prefix% <gradient:#40B7D6:
<#5AE4B5>- <#40B7D6>/cosmetics add <gray><USERNAME> <ID> (#HEX)</gray> - <#6D9DC5>Adds cosmetic to player.
<#5AE4B5>- <#40B7D6>/cosmetics remove <gray><USERNAME> <BACKPACK/HAT></gray> - <#6D9DC5>Removes cosmetic from a player.
<#5AE4B5>- <#40B7D6>/cosmetics remove <gray><USERNAME> \<BACKPACK/HAT></gray> - <#6D9DC5>Removes cosmetic from a player.
<#5AE4B5>- <#40B7D6>/cosmetics dye <gray><BACKPACK/HAT></gray> - <#6D9DC5>Opens dye menu for the specified cosmetic type.

View File

@@ -0,0 +1,5 @@
tokens:
1:
id: colorful_hat
material: emerald
name: "<green>Colorful hat token"