diff --git a/build.gradle.kts b/build.gradle.kts index 1da5ccbb..378de7d9 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -79,6 +79,11 @@ allprojects { compileOnly("com.sk89q.worldguard:worldguard-bukkit:7.1.0-SNAPSHOT") compileOnly("it.unimi.dsi:fastutil:8.5.11") compileOnly("com.github.LeonMangler:SuperVanish:6.2.17") + compileOnly("org.projectlombok:lombok:1.18.2") + + annotationProcessor("org.projectlombok:lombok:1.18.28") + testCompileOnly("org.projectlombok:lombok:1.18.28") + testAnnotationProcessor("org.projectlombok:lombok:1.18.28") } } diff --git a/common/src/main/java/com/hibiscusmc/hmccosmetics/config/Settings.java b/common/src/main/java/com/hibiscusmc/hmccosmetics/config/Settings.java index 6ab43b89..4379d809 100644 --- a/common/src/main/java/com/hibiscusmc/hmccosmetics/config/Settings.java +++ b/common/src/main/java/com/hibiscusmc/hmccosmetics/config/Settings.java @@ -3,6 +3,7 @@ package com.hibiscusmc.hmccosmetics.config; import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin; import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticSlot; import com.hibiscusmc.hmccosmetics.util.MessagesUtil; +import lombok.Getter; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.util.Vector; import org.spongepowered.configurate.ConfigurationNode; @@ -51,6 +52,15 @@ public class Settings { private static final String COSMETIC_TYPE_SETTINGS_PATH = "cosmetic-type"; private static final String EQUIP_CLICK_TYPE = "equip-click"; private static final String UNEQUIP_CLICK_TYPE = "unequip-click"; + private static final String SHADING_PATH = "shading"; + private static final String FIRST_ROW_SHIFT_PATH = "first-row-shift"; + private static final String SEQUENT_ROW_SHIFT_PATH = "sequent-row-shift"; + private static final String INDIVIDUAL_COLUMN_SHIFT_PATH = "individual-column-shift"; + private static final String BACKGROUND_PATH = "background"; + private static final String EQUIPPED_COSMETIC_COLOR_PATH = "equipped-cosmetic-color"; + private static final String EQUIPABLE_COSMETIC_COLOR_PATH = "equipable-cosmetic-color"; + private static final String LOCKED_COSMETIC_COLOR_PATH = "locked-cosmetic-color"; + private static final String ENABLED_PATH = "enabled"; private static String defaultMenu; private static String dyeMenuName; @@ -79,10 +89,28 @@ public class Settings { private static boolean destroyLooseCosmetics; private static int viewDistance; private static int tickPeriod; + @Getter private static double emoteDistance; private static Vector balloonOffset; private static String cosmeticEquipClickType; private static String cosmeticUnEquipClickType; + @Getter + private static boolean defaultShading; + @Getter + private static String firstRowShift; + @Getter + private static String sequentRowShift; + @Getter + private static String individualColumnShift; + @Getter + private static String background; + @Getter + private static String equippedCosmeticColor; + @Getter + private static String equipableCosmeticColor; + @Getter + private static String lockedCosmeticColor; + public static void load(ConfigurationNode source) { @@ -123,6 +151,17 @@ public class Settings { viewDistance = cosmeticSettings.node(VIEW_DISTANCE_PATH).getInt(); ConfigurationNode menuSettings = source.node(MENU_SETTINGS_PATH); + + ConfigurationNode shadingSettings = menuSettings.node(SHADING_PATH); + defaultShading = shadingSettings.node(ENABLED_PATH).getBoolean(); + firstRowShift = shadingSettings.node(FIRST_ROW_SHIFT_PATH).getString(); + sequentRowShift = shadingSettings.node(SEQUENT_ROW_SHIFT_PATH).getString(); + individualColumnShift = shadingSettings.node(INDIVIDUAL_COLUMN_SHIFT_PATH).getString(); + background = shadingSettings.node(BACKGROUND_PATH).getString(); + equippedCosmeticColor = shadingSettings.node(EQUIPPED_COSMETIC_COLOR_PATH).getString(); + equipableCosmeticColor = shadingSettings.node(EQUIPABLE_COSMETIC_COLOR_PATH).getString(); + lockedCosmeticColor = shadingSettings.node(LOCKED_COSMETIC_COLOR_PATH).getString(); + ConfigurationNode cosmeticTypeSettings = menuSettings.node(COSMETIC_TYPE_SETTINGS_PATH); cosmeticEquipClickType = cosmeticTypeSettings.node(EQUIP_CLICK_TYPE).getString("ALL"); cosmeticUnEquipClickType = cosmeticTypeSettings.node(UNEQUIP_CLICK_TYPE).getString("ALL"); @@ -265,10 +304,6 @@ public class Settings { return debugMode; } - public static double getEmoteDistance() { - return emoteDistance; - } - public static boolean getCosmeticEmoteBlockCheck() { return cosmeticEmoteBlockCheck; } diff --git a/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/Menu.java b/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/Menu.java index 8cf32454..54a9157a 100644 --- a/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/Menu.java +++ b/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/Menu.java @@ -4,13 +4,17 @@ import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin; import com.hibiscusmc.hmccosmetics.api.events.PlayerMenuOpenEvent; import com.hibiscusmc.hmccosmetics.config.Settings; import com.hibiscusmc.hmccosmetics.config.serializer.ItemSerializer; +import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic; +import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetics; import com.hibiscusmc.hmccosmetics.gui.type.Type; import com.hibiscusmc.hmccosmetics.gui.type.Types; import com.hibiscusmc.hmccosmetics.hooks.Hooks; import com.hibiscusmc.hmccosmetics.user.CosmeticUser; import com.hibiscusmc.hmccosmetics.util.MessagesUtil; import com.hibiscusmc.hmccosmetics.util.misc.Adventure; +import com.hibiscusmc.hmccosmetics.util.misc.StringUtils; import dev.triumphteam.gui.builder.item.ItemBuilder; +import dev.triumphteam.gui.guis.BaseGui; import dev.triumphteam.gui.guis.Gui; import dev.triumphteam.gui.guis.GuiItem; import net.kyori.adventure.text.Component; @@ -36,8 +40,9 @@ public class Menu { private final int rows; private final ConfigurationNode config; private final String permissionNode; - private final ArrayList items; + private final HashMap items; private final int refreshRate; + private final boolean shading; public Menu(String id, @NotNull ConfigurationNode config) { this.id = id; @@ -47,8 +52,9 @@ public class Menu { rows = config.node("rows").getInt(1); permissionNode = config.node("permission").getString(""); refreshRate = config.node("refresh-rate").getInt(-1); + shading = config.node("shading").getBoolean(Settings.isDefaultShading()); - items = new ArrayList<>(); + items = new HashMap<>(); setupItems(); Menus.addMenu(this); @@ -94,7 +100,9 @@ public class Menu { if (Types.isType(typeId)) type = Types.getType(typeId); } - items.add(new MenuItem(slots, item, type, config)); + for (Integer slot : slots) { + items.put(slot, new MenuItem(slots, item, type, config)); + } } } @@ -124,10 +132,10 @@ public class Menu { } } final Component component = Adventure.MINI_MESSAGE.deserialize(Hooks.processPlaceholders(player, this.title)); - Gui gui = Gui.gui(). - title(component). - rows(this.rows). - create(); + Gui gui = Gui.gui() + .title(component) + .rows(this.rows) + .create(); gui.setDefaultClickAction(event -> event.setCancelled(true)); @@ -136,7 +144,7 @@ public class Menu { Runnable run = new Runnable() { @Override public void run() { - if (gui.getInventory().getViewers().size() == 0 && taskid.get() != -1) { + if (gui.getInventory().getViewers().isEmpty() && taskid.get() != -1) { Bukkit.getScheduler().cancelTask(taskid.get()); } @@ -165,25 +173,72 @@ public class Menu { Bukkit.getScheduler().runTask(HMCCosmeticsPlugin.getInstance(), () -> { gui.open(player); + updateMenu(user, gui); // fixes shading? I know I do this twice but it's easier than writing a whole new class to deal with this shit }); } private void updateMenu(CosmeticUser user, Gui gui) { - for (MenuItem item : items) { - Type type = item.getType(); - for (int slot : item.getSlots()) { - ItemStack modifiedItem = getMenuItem(user, type, item.getItemConfig(), item.getItem().clone(), slot); - GuiItem guiItem = ItemBuilder.from(modifiedItem).asGuiItem(); - guiItem.setAction(event -> { - MessagesUtil.sendDebugMessages("Selected slot " + slot); - final ClickType clickType = event.getClick(); - if (type != null) type.run(user, item.getItemConfig(), clickType); - updateMenu(user, gui); - }); + String title = this.title; - MessagesUtil.sendDebugMessages("Added " + slot + " as " + guiItem + " in the menu"); - gui.updateItem(slot, guiItem); + int row = 0; + if (shading) { + for (int i = 0; i < gui.getInventory().getSize(); i++) { + if (items.containsKey(i)) { + // Handles the items + MenuItem item = items.get(i); + updateItem(user, gui, item); + + // Handles the title + if (i % 9 == 0) { + if (row == 0) { + title += Settings.getFirstRowShift(); // Goes back to the start of the gui + } else { + title += Settings.getSequentRowShift(); + } + row += 1; + } else { + title += Settings.getIndividualColumnShift(); // Goes to the next slot + } + + if (item.getType().getId().equalsIgnoreCase("cosmetic")) { + Cosmetic cosmetic = Cosmetics.getCosmetic(item.getItemConfig().node("cosmetic").getString("")); + if (cosmetic == null) continue; + if (user.hasCosmeticInSlot(cosmetic)) { + title += Settings.getEquippedCosmeticColor(); + } else { + if (user.canEquipCosmetic(cosmetic)) { + title += Settings.getEquipableCosmeticColor(); + } else { + title += Settings.getLockedCosmeticColor(); + } + } + title += Settings.getBackground().replaceAll("", String.valueOf(row)); + } + } } + MessagesUtil.sendDebugMessages("Updated menu with title " + title); + gui.updateTitle(StringUtils.parseStringToString(Hooks.processPlaceholders(user.getPlayer(), title))); + } else { + for (MenuItem item : items.values()) { + updateItem(user, gui, item); + } + } + } + + private void updateItem(CosmeticUser user, Gui gui, MenuItem item) { + Type type = item.getType(); + for (int slot : item.getSlots()) { + ItemStack modifiedItem = getMenuItem(user, type, item.getItemConfig(), item.getItem().clone(), slot); + GuiItem guiItem = ItemBuilder.from(modifiedItem).asGuiItem(); + guiItem.setAction(event -> { + MessagesUtil.sendDebugMessages("Selected slot " + slot); + final ClickType clickType = event.getClick(); + if (type != null) type.run(user, item.getItemConfig(), clickType); + updateMenu(user, gui); + }); + + MessagesUtil.sendDebugMessages("Added " + slot + " as " + guiItem + " in the menu"); + gui.updateItem(slot, guiItem); } } diff --git a/common/src/main/resources/config.yml b/common/src/main/resources/config.yml index fb846cf1..dce3084f 100644 --- a/common/src/main/resources/config.yml +++ b/common/src/main/resources/config.yml @@ -49,6 +49,19 @@ cosmetic-settings: y: 3 z: 0.5 menu-settings: + shading: + # Below is the shading mechanism behind cosmetic items. This is a bit complicated, but it allows for a lot of customization. + # The shading is done through the title and by shifting textures around. This is done by offsets. + # Vanilla, ItemsAdder, and Oraxen are supported **BUT** requires some manual work. Default values are Vanilla. See below. + enabled: false # Default of menus having shading. This can be toggled individually in menus with "shading: true/false" + first-row-shift: "" # Oraxen: "" / ItemsAdder: ":offset_-169:" + sequent-row-shift: " " # Oraxen: " " / ItemsAdder: " :offset_-169:" (Space is important here!) + individual-column-shift: "" # Oraxen: "" / ItemsAdder: ":offset_-3:" + background: ":colorable> " # Oraxen: ":colorable> " / ItemsAdder: ":shade_row_:colorable: " + #These use MiniMessage for color! https://docs.advntr.dev/minimessage/format.html#color + equipped-cosmetic-color: "" + equipable-cosmetic-color: "" + locked-cosmetic-color: "" cosmetic-type: # This allows you to specify if it should require a special click type for the interaction to work. equip-click: "ANY" # ANY or ClickType, https://jd.papermc.io/paper/1.20/org/bukkit/event/inventory/ClickType.html