From 470de3b749d30812b015148cf67f6f13659b6c49 Mon Sep 17 00:00:00 2001 From: yusshu Date: Sat, 1 Mar 2025 18:05:54 -0500 Subject: [PATCH 1/4] feat(api): add CosmeticHolder interface allows plugins to implement their custom cosmetic holders and open menus for them, will also allow to open the cosmetics menu of a player to another player (for administration purposes maybe) --- .../hmccosmetics/cosmetic/CosmeticHolder.java | 75 +++++++++++++++++++ .../com/hibiscusmc/hmccosmetics/gui/Menu.java | 59 +++++++++------ .../hmccosmetics/gui/action/Action.java | 10 +++ .../hmccosmetics/gui/action/Actions.java | 10 ++- .../gui/action/actions/ActionCloseMenu.java | 9 ++- .../action/actions/ActionConsoleCommand.java | 11 ++- .../action/actions/ActionCosmeticHide.java | 10 ++- .../action/actions/ActionCosmeticShow.java | 10 ++- .../action/actions/ActionCosmeticToggle.java | 10 ++- .../gui/action/actions/ActionEquip.java | 11 ++- .../gui/action/actions/ActionMenu.java | 11 ++- .../gui/action/actions/ActionMessage.java | 9 ++- .../gui/action/actions/ActionParticle.java | 10 ++- .../action/actions/ActionPlayerCommand.java | 10 ++- .../gui/action/actions/ActionSound.java | 11 ++- .../gui/action/actions/ActionUnequip.java | 12 ++- .../hmccosmetics/gui/special/DyeMenu.java | 31 ++++---- .../hmccosmetics/gui/type/Type.java | 27 ++++++- .../gui/type/types/TypeCosmetic.java | 56 ++++++++------ .../gui/type/types/TypeEmpty.java | 31 ++++++-- .../hmccosmetics/user/CosmeticUser.java | 48 ++++++------ 21 files changed, 357 insertions(+), 114 deletions(-) create mode 100644 common/src/main/java/com/hibiscusmc/hmccosmetics/cosmetic/CosmeticHolder.java diff --git a/common/src/main/java/com/hibiscusmc/hmccosmetics/cosmetic/CosmeticHolder.java b/common/src/main/java/com/hibiscusmc/hmccosmetics/cosmetic/CosmeticHolder.java new file mode 100644 index 00000000..2b4e8c8a --- /dev/null +++ b/common/src/main/java/com/hibiscusmc/hmccosmetics/cosmetic/CosmeticHolder.java @@ -0,0 +1,75 @@ +package com.hibiscusmc.hmccosmetics.cosmetic; + +import com.google.common.collect.ImmutableCollection; +import com.hibiscusmc.hmccosmetics.user.CosmeticUser; +import org.bukkit.Color; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Objects; + +/** + * Represents any object that can wear/hold cosmetics, + * users, for example. + */ +public interface CosmeticHolder { + @Nullable Cosmetic getCosmetic(CosmeticSlot slot); + + ImmutableCollection getCosmetics(); + + void addCosmetic(@NotNull Cosmetic cosmetic, @Nullable Color color); + + default void addCosmetic(@NotNull Cosmetic cosmetic) { + addCosmetic(cosmetic, null); + } + + default void removeCosmetics() { + // Small optimization could be made, but Concurrent modification prevents us from both getting and removing + for (CosmeticSlot slot : CosmeticSlot.values().values()) { + removeCosmeticSlot(slot); + } + } + + void removeCosmeticSlot(CosmeticSlot slot); + + default void removeCosmeticSlot(Cosmetic cosmetic) { + removeCosmeticSlot(cosmetic.getSlot()); + } + + default boolean hasCosmeticInSlot(CosmeticSlot slot) { + return getCosmetic(slot) != null; + } + + default boolean hasCosmeticInSlot(Cosmetic cosmetic) { + final var existingCosmetic = getCosmetic(cosmetic.getSlot()); + if (existingCosmetic == null) return false; + return Objects.equals(cosmetic.getId(), existingCosmetic.getId()); + } + + default boolean canEquipCosmetic(Cosmetic cosmetic) { + return canEquipCosmetic(cosmetic, false); + } + + boolean canEquipCosmetic(Cosmetic cosmetic, boolean ignoreWardrobe); + + void updateCosmetic(CosmeticSlot slot); + + /** + * Just for backwards compatibility, ensures that the given viewer and the given cosmetic holder + * represent the same user. + * + * @param viewer the viewer + * @param cosmeticHolder the cosmetic holder + */ + @ApiStatus.Internal + static @NotNull CosmeticUser ensureSingleCosmeticUser(@NotNull Player viewer, @NotNull CosmeticHolder cosmeticHolder) { + if (!(cosmeticHolder instanceof CosmeticUser user) || !user.getUniqueId().equals(viewer.getUniqueId())) { + throw new IllegalStateException("This method does not support having a different viewer than" + + " the same cosmetic holder. Needs to be updated to support the overload that takes a viewer and" + + " a cosmetic holder instead of a single CosmeticUser."); + } + return user; + } +} 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 8d990829..bac5ac3f 100644 --- a/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/Menu.java +++ b/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/Menu.java @@ -5,6 +5,7 @@ import com.hibiscusmc.hmccosmetics.api.events.PlayerMenuCloseEvent; import com.hibiscusmc.hmccosmetics.api.events.PlayerMenuOpenEvent; import com.hibiscusmc.hmccosmetics.config.Settings; import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic; +import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder; import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetics; import com.hibiscusmc.hmccosmetics.gui.type.Type; import com.hibiscusmc.hmccosmetics.gui.type.Types; @@ -136,13 +137,21 @@ public class Menu { public void openMenu(@NotNull CosmeticUser user, boolean ignorePermission) { Player player = user.getPlayer(); if (player == null) return; + openMenu(player, user, ignorePermission); + } + + public void openMenu(@NotNull Player viewer, @NotNull CosmeticHolder cosmeticHolder) { + openMenu(viewer, cosmeticHolder, false); + } + + public void openMenu(@NotNull Player viewer, @NotNull CosmeticHolder cosmeticHolder, boolean ignorePermission) { if (!ignorePermission && !permissionNode.isEmpty()) { - if (!player.hasPermission(permissionNode) && !player.isOp()) { - MessagesUtil.sendMessage(player, "no-permission"); + if (!viewer.hasPermission(permissionNode) && !viewer.isOp()) { + MessagesUtil.sendMessage(viewer, "no-permission"); return; } } - final Component component = AdventureUtils.MINI_MESSAGE.deserialize(Hooks.processPlaceholders(player, this.title)); + final Component component = AdventureUtils.MINI_MESSAGE.deserialize(Hooks.processPlaceholders(viewer, this.title)); Gui gui = Gui.gui() .title(component) .type(GuiType.CHEST) @@ -159,7 +168,7 @@ public class Menu { Bukkit.getScheduler().cancelTask(taskid.get()); } - updateMenu(user, gui); + updateMenu(viewer, cosmeticHolder, gui); }; if (refreshRate != -1) { @@ -170,25 +179,29 @@ public class Menu { }); gui.setCloseGuiAction(event -> { - PlayerMenuCloseEvent closeEvent = new PlayerMenuCloseEvent(user, this, event.getReason()); - Bukkit.getScheduler().runTask(HMCCosmeticsPlugin.getInstance(), () -> Bukkit.getPluginManager().callEvent(closeEvent)); + if (cosmeticHolder instanceof CosmeticUser user) { + PlayerMenuCloseEvent closeEvent = new PlayerMenuCloseEvent(user, this, event.getReason()); + Bukkit.getScheduler().runTask(HMCCosmeticsPlugin.getInstance(), () -> Bukkit.getPluginManager().callEvent(closeEvent)); + } if (taskid.get() != -1) Bukkit.getScheduler().cancelTask(taskid.get()); }); // API - PlayerMenuOpenEvent event = new PlayerMenuOpenEvent(user, this); - Bukkit.getScheduler().runTask(HMCCosmeticsPlugin.getInstance(), () -> Bukkit.getPluginManager().callEvent(event)); - if (event.isCancelled()) return; + if (cosmeticHolder instanceof CosmeticUser user) { + PlayerMenuOpenEvent event = new PlayerMenuOpenEvent(user, this); + Bukkit.getScheduler().runTask(HMCCosmeticsPlugin.getInstance(), () -> Bukkit.getPluginManager().callEvent(event)); + if (event.isCancelled()) return; + } // Internal 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 + gui.open(viewer); + updateMenu(viewer, cosmeticHolder, 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) { + private void updateMenu(Player viewer, CosmeticHolder cosmeticHolder, Gui gui) { StringBuilder title = new StringBuilder(this.title); int row = 0; @@ -212,15 +225,15 @@ public class Menu { // Handles the items List menuItems = items.get(i); MenuItem item = menuItems.get(0); - updateItem(user, gui, i); + updateItem(viewer, cosmeticHolder, gui, i); if (item.type() instanceof TypeCosmetic) { Cosmetic cosmetic = Cosmetics.getCosmetic(item.itemConfig().node("cosmetic").getString("")); if (cosmetic == null) continue; - if (user.hasCosmeticInSlot(cosmetic)) { + if (cosmeticHolder.hasCosmeticInSlot(cosmetic)) { title.append(Settings.getEquippedCosmeticColor()); } else { - if (user.canEquipCosmetic(cosmetic, true)) { + if (cosmeticHolder.canEquipCosmetic(cosmetic, true)) { title.append(Settings.getEquipableCosmeticColor()); } else { title.append(Settings.getLockedCosmeticColor()); @@ -236,17 +249,17 @@ public class Menu { } } MessagesUtil.sendDebugMessages("Updated menu with title " + title); - gui.updateTitle(StringUtils.parseStringToString(Hooks.processPlaceholders(user.getPlayer(), title.toString()))); + gui.updateTitle(StringUtils.parseStringToString(Hooks.processPlaceholders(viewer, title.toString()))); } else { for (int i = 0; i < gui.getInventory().getSize(); i++) { if (items.containsKey(i)) { - updateItem(user, gui, i); + updateItem(viewer, cosmeticHolder, gui, i); } } } } - private void updateItem(CosmeticUser user, Gui gui, int slot) { + private void updateItem(Player viewer, CosmeticHolder cosmeticHolder, Gui gui, int slot) { if (!items.containsKey(slot)) return; List menuItems = items.get(slot); if (menuItems.isEmpty()) return; @@ -257,21 +270,21 @@ public class Menu { if (modifiedItem.getType().isAir()) continue; GuiItem guiItem = ItemBuilder.from(modifiedItem).asGuiItem(); guiItem.setAction(event -> { - UUID uuid = user.getUniqueId(); + UUID uuid = viewer.getUniqueId(); if (Settings.isMenuClickCooldown()) { Long userCooldown = Menus.getCooldown(uuid); if (userCooldown != 0 && (System.currentTimeMillis() - Menus.getCooldown(uuid) <= getCooldown())) { - MessagesUtil.sendDebugMessages("Cooldown for " + user.getUniqueId() + " System time: " + System.currentTimeMillis() + " Cooldown: " + Menus.getCooldown(user.getUniqueId()) + " Difference: " + (System.currentTimeMillis() - Menus.getCooldown(user.getUniqueId()))); - MessagesUtil.sendMessage(user.getPlayer(), "on-click-cooldown"); + MessagesUtil.sendDebugMessages("Cooldown for " + viewer.getUniqueId() + " System time: " + System.currentTimeMillis() + " Cooldown: " + Menus.getCooldown(viewer.getUniqueId()) + " Difference: " + (System.currentTimeMillis() - Menus.getCooldown(viewer.getUniqueId()))); + MessagesUtil.sendMessage(viewer, "on-click-cooldown"); return; } else { - Menus.addCooldown(user.getUniqueId(), System.currentTimeMillis()); + Menus.addCooldown(uuid, System.currentTimeMillis()); } } MessagesUtil.sendDebugMessages("Updated Menu Item in slot number " + slot); final ClickType clickType = event.getClick(); if (type != null) type.run(user, item.itemConfig(), clickType); - updateMenu(user, gui); + updateMenu(viewer, cosmeticHolder, gui); }); MessagesUtil.sendDebugMessages("Set an item in slot " + slot + " in the menu of " + getId()); diff --git a/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/Action.java b/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/Action.java index 62db2c5a..d6d2f462 100644 --- a/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/Action.java +++ b/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/Action.java @@ -1,6 +1,8 @@ package com.hibiscusmc.hmccosmetics.gui.action; +import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder; import com.hibiscusmc.hmccosmetics.user.CosmeticUser; +import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; public abstract class Action { @@ -16,5 +18,13 @@ public abstract class Action { return this.id; } + public void run(Player viewer, CosmeticHolder cosmeticHolder, String raw) { + run(CosmeticHolder.ensureSingleCosmeticUser(viewer, cosmeticHolder), raw); + } + + /** + * @deprecated Override {@link #run(Player, CosmeticHolder, String)} instead. + */ + @Deprecated public abstract void run(CosmeticUser user, String raw); } diff --git a/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/Actions.java b/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/Actions.java index e093dbc0..4d17a343 100644 --- a/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/Actions.java +++ b/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/Actions.java @@ -1,9 +1,11 @@ package com.hibiscusmc.hmccosmetics.gui.action; +import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder; import com.hibiscusmc.hmccosmetics.gui.action.actions.*; import com.hibiscusmc.hmccosmetics.user.CosmeticUser; import com.hibiscusmc.hmccosmetics.util.MessagesUtil; import org.apache.commons.lang3.StringUtils; +import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import java.util.HashMap; @@ -41,16 +43,20 @@ public class Actions { actions.put(action.getId().toUpperCase(), action); } - public static void runActions(CosmeticUser user, @NotNull List raw) { + public static void runActions(Player viewer, CosmeticHolder cosmeticHolder, @NotNull List raw) { for (String a : raw) { String id = StringUtils.substringBetween(a, "[", "]").toUpperCase(); String message = StringUtils.substringAfter(a, "] "); MessagesUtil.sendDebugMessages("ID is " + id + " // Raw Data is " + message); if (isAction(id)) { - getAction(id).run(user, message); + getAction(id).run(viewer, cosmeticHolder, message); } else { MessagesUtil.sendDebugMessages("Possible ids: " + actions.keySet()); } } } + + public static void runActions(CosmeticUser user, @NotNull List raw) { + runActions(user.getPlayer(), user, raw); + } } diff --git a/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionCloseMenu.java b/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionCloseMenu.java index 10263744..7136f2c0 100644 --- a/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionCloseMenu.java +++ b/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionCloseMenu.java @@ -1,7 +1,9 @@ package com.hibiscusmc.hmccosmetics.gui.action.actions; +import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder; import com.hibiscusmc.hmccosmetics.gui.action.Action; import com.hibiscusmc.hmccosmetics.user.CosmeticUser; +import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; public class ActionCloseMenu extends Action { @@ -10,8 +12,13 @@ public class ActionCloseMenu extends Action { super("close"); } + @Override + public void run(Player viewer, CosmeticHolder cosmeticHolder, String raw) { + viewer.closeInventory(); + } + @Override public void run(@NotNull CosmeticUser user, String raw) { - user.getPlayer().closeInventory(); + run(user.getPlayer(), user, raw); } } diff --git a/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionConsoleCommand.java b/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionConsoleCommand.java index d866297c..2daf8e70 100644 --- a/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionConsoleCommand.java +++ b/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionConsoleCommand.java @@ -1,10 +1,12 @@ package com.hibiscusmc.hmccosmetics.gui.action.actions; import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin; +import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder; import com.hibiscusmc.hmccosmetics.gui.action.Action; import com.hibiscusmc.hmccosmetics.user.CosmeticUser; import me.lojosho.hibiscuscommons.hooks.Hooks; import org.bukkit.Bukkit; +import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; public class ActionConsoleCommand extends Action { @@ -13,8 +15,15 @@ public class ActionConsoleCommand extends Action { super("console-command"); } + @Override + public void run(Player viewer, CosmeticHolder cosmeticHolder, String raw) { + // todo: some of these generalizations may require more specific implementations, for example, + // todo: what if we wanted to execute console commands only for the cosmetic holder? + HMCCosmeticsPlugin.getInstance().getServer().dispatchCommand(Bukkit.getConsoleSender(), Hooks.processPlaceholders(viewer, raw)); + } + @Override public void run(@NotNull CosmeticUser user, String raw) { - HMCCosmeticsPlugin.getInstance().getServer().dispatchCommand(Bukkit.getConsoleSender(), Hooks.processPlaceholders(user.getPlayer(), raw)); + run(user.getPlayer(), user, raw); } } diff --git a/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionCosmeticHide.java b/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionCosmeticHide.java index 7f30c698..f486be38 100644 --- a/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionCosmeticHide.java +++ b/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionCosmeticHide.java @@ -1,7 +1,9 @@ package com.hibiscusmc.hmccosmetics.gui.action.actions; +import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder; import com.hibiscusmc.hmccosmetics.gui.action.Action; import com.hibiscusmc.hmccosmetics.user.CosmeticUser; +import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; public class ActionCosmeticHide extends Action { @@ -11,8 +13,14 @@ public class ActionCosmeticHide extends Action { } @Override - public void run(@NotNull CosmeticUser user, String raw) { + public void run(Player viewer, CosmeticHolder cosmeticHolder, String raw) { + if (!(cosmeticHolder instanceof CosmeticUser user)) return; if (user.isHidden()) return; user.hideCosmetics(CosmeticUser.HiddenReason.ACTION); } + + @Override + public void run(@NotNull CosmeticUser user, String raw) { + run(user.getPlayer(), user, raw); + } } diff --git a/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionCosmeticShow.java b/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionCosmeticShow.java index 143b856c..0486b7ea 100644 --- a/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionCosmeticShow.java +++ b/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionCosmeticShow.java @@ -1,7 +1,9 @@ package com.hibiscusmc.hmccosmetics.gui.action.actions; +import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder; import com.hibiscusmc.hmccosmetics.gui.action.Action; import com.hibiscusmc.hmccosmetics.user.CosmeticUser; +import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; public class ActionCosmeticShow extends Action { @@ -11,11 +13,17 @@ public class ActionCosmeticShow extends Action { } @Override - public void run(@NotNull CosmeticUser user, String raw) { + public void run(Player viewer, CosmeticHolder cosmeticHolder, String raw) { + if (!(cosmeticHolder instanceof CosmeticUser user)) return; if (!user.isHidden()) return; // Do not hide if it's already off for WG if (!user.isHidden(CosmeticUser.HiddenReason.ACTION) && !user.isHidden(CosmeticUser.HiddenReason.COMMAND)) return; user.showCosmetics(CosmeticUser.HiddenReason.ACTION); } + + @Override + public void run(@NotNull CosmeticUser user, String raw) { + run(user.getPlayer(), user, raw); + } } diff --git a/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionCosmeticToggle.java b/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionCosmeticToggle.java index 95544cb2..567e4375 100644 --- a/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionCosmeticToggle.java +++ b/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionCosmeticToggle.java @@ -1,7 +1,9 @@ package com.hibiscusmc.hmccosmetics.gui.action.actions; +import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder; import com.hibiscusmc.hmccosmetics.gui.action.Action; import com.hibiscusmc.hmccosmetics.user.CosmeticUser; +import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; public class ActionCosmeticToggle extends Action { @@ -11,7 +13,8 @@ public class ActionCosmeticToggle extends Action { } @Override - public void run(@NotNull CosmeticUser user, String raw) { + public void run(Player viewer, CosmeticHolder cosmeticHolder, String raw) { + if (!(cosmeticHolder instanceof CosmeticUser user)) return; if (user.isHidden()) { if (!user.isHidden(CosmeticUser.HiddenReason.ACTION) && !user.isHidden(CosmeticUser.HiddenReason.COMMAND)) return; user.showCosmetics(CosmeticUser.HiddenReason.ACTION); @@ -20,4 +23,9 @@ public class ActionCosmeticToggle extends Action { user.hideCosmetics(CosmeticUser.HiddenReason.ACTION); } + + @Override + public void run(@NotNull CosmeticUser user, String raw) { + run(user.getPlayer(), user, raw); + } } diff --git a/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionEquip.java b/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionEquip.java index 37558d1e..ffbe9ae5 100644 --- a/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionEquip.java +++ b/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionEquip.java @@ -1,9 +1,11 @@ package com.hibiscusmc.hmccosmetics.gui.action.actions; import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic; +import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder; import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetics; import com.hibiscusmc.hmccosmetics.gui.action.Action; import com.hibiscusmc.hmccosmetics.user.CosmeticUser; +import org.bukkit.entity.Player; public class ActionEquip extends Action { @@ -12,10 +14,15 @@ public class ActionEquip extends Action { } @Override - public void run(CosmeticUser user, String raw) { + public void run(Player viewer, CosmeticHolder cosmeticHolder, String raw) { Cosmetic cosmetic = Cosmetics.getCosmetic(raw); if (cosmetic == null) return; - user.addPlayerCosmetic(cosmetic); + cosmeticHolder.addCosmetic(cosmetic); + } + + @Override + public void run(CosmeticUser user, String raw) { + run(user.getPlayer(), user, raw); } } diff --git a/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionMenu.java b/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionMenu.java index 232081ba..429097e4 100644 --- a/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionMenu.java +++ b/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionMenu.java @@ -1,10 +1,12 @@ package com.hibiscusmc.hmccosmetics.gui.action.actions; +import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder; import com.hibiscusmc.hmccosmetics.gui.Menu; import com.hibiscusmc.hmccosmetics.gui.Menus; import com.hibiscusmc.hmccosmetics.gui.action.Action; import com.hibiscusmc.hmccosmetics.user.CosmeticUser; import com.hibiscusmc.hmccosmetics.util.MessagesUtil; +import org.bukkit.entity.Player; import java.util.logging.Level; @@ -15,7 +17,7 @@ public class ActionMenu extends Action { } @Override - public void run(CosmeticUser user, String raw) { + public void run(Player viewer, CosmeticHolder cosmeticHolder, String raw) { boolean ignorePermission = false; raw = raw.replaceAll(" ", ""); // Removes all spaces @@ -32,6 +34,11 @@ public class ActionMenu extends Action { Menu menu = Menus.getMenu(raw); MessagesUtil.sendDebugMessages(raw + " | " + ignorePermission); - menu.openMenu(user, ignorePermission); + menu.openMenu(viewer, cosmeticHolder, ignorePermission); + } + + @Override + public void run(CosmeticUser user, String raw) { + run(user.getPlayer(), user, raw); } } diff --git a/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionMessage.java b/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionMessage.java index d02516d6..c37fb7bc 100644 --- a/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionMessage.java +++ b/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionMessage.java @@ -1,8 +1,10 @@ package com.hibiscusmc.hmccosmetics.gui.action.actions; +import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder; import com.hibiscusmc.hmccosmetics.gui.action.Action; import com.hibiscusmc.hmccosmetics.user.CosmeticUser; import com.hibiscusmc.hmccosmetics.util.MessagesUtil; +import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; public class ActionMessage extends Action { @@ -11,8 +13,13 @@ public class ActionMessage extends Action { super("message"); } + @Override + public void run(Player viewer, CosmeticHolder cosmeticHolder, String raw) { + MessagesUtil.sendMessageNoKey(viewer, raw); + } + @Override public void run(@NotNull CosmeticUser user, String raw) { - MessagesUtil.sendMessageNoKey(user.getPlayer(), raw); + run(user.getPlayer(), user, raw); } } diff --git a/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionParticle.java b/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionParticle.java index 4a3f0f1b..d9a00a81 100644 --- a/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionParticle.java +++ b/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionParticle.java @@ -1,5 +1,6 @@ package com.hibiscusmc.hmccosmetics.gui.action.actions; +import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder; import com.hibiscusmc.hmccosmetics.gui.action.Action; import com.hibiscusmc.hmccosmetics.user.CosmeticUser; import com.hibiscusmc.hmccosmetics.util.MessagesUtil; @@ -24,7 +25,7 @@ public class ActionParticle extends Action { @Override @SuppressWarnings("ConstantConditions") - public void run(CosmeticUser user, @NotNull String raw) { + public void run(Player viewer, CosmeticHolder cosmeticHolder, String raw) { String[] rawString = raw.split(" "); ParticleType particleType = Particles.fromKey(NamespacedKey.minecraft(rawString[0].toLowerCase())); if (particleType == null) { @@ -43,9 +44,14 @@ public class ActionParticle extends Action { } particle = HMCCServerUtils.addParticleValues(particle, rawString); - Location location = user.getPlayer().getLocation(); + Location location = viewer.getLocation(); for (Player player : HMCCPacketManager.getViewers(location)) { particle.compile().send(player, location); } } + + @Override + public void run(CosmeticUser user, @NotNull String raw) { + run(user.getPlayer(), user, raw); + } } diff --git a/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionPlayerCommand.java b/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionPlayerCommand.java index 2f95b5e3..3d89b5ff 100644 --- a/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionPlayerCommand.java +++ b/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionPlayerCommand.java @@ -1,9 +1,11 @@ package com.hibiscusmc.hmccosmetics.gui.action.actions; +import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder; import com.hibiscusmc.hmccosmetics.gui.action.Action; import com.hibiscusmc.hmccosmetics.user.CosmeticUser; import com.hibiscusmc.hmccosmetics.util.MessagesUtil; import me.lojosho.hibiscuscommons.hooks.Hooks; +import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; public class ActionPlayerCommand extends Action { @@ -12,8 +14,14 @@ public class ActionPlayerCommand extends Action { super("player-command"); } + @Override + public void run(Player viewer, CosmeticHolder cosmeticHolder, String raw) { + // todo: what if we wanted the cosmetic holder to execute the command instead + viewer.performCommand(MessagesUtil.processStringNoKeyString(viewer, Hooks.processPlaceholders(viewer, raw))); + } + @Override public void run(@NotNull CosmeticUser user, String raw) { - user.getPlayer().performCommand(MessagesUtil.processStringNoKeyString(user.getPlayer(), Hooks.processPlaceholders(user.getPlayer(), raw))); + run(user.getPlayer(), user, raw); } } \ No newline at end of file diff --git a/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionSound.java b/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionSound.java index d2da1cf4..10446285 100644 --- a/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionSound.java +++ b/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionSound.java @@ -1,5 +1,6 @@ package com.hibiscusmc.hmccosmetics.gui.action.actions; +import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder; import com.hibiscusmc.hmccosmetics.gui.action.Action; import com.hibiscusmc.hmccosmetics.user.CosmeticUser; import com.hibiscusmc.hmccosmetics.util.MessagesUtil; @@ -16,8 +17,7 @@ public class ActionSound extends Action { } @Override - public void run(@NotNull CosmeticUser user, @NotNull String raw) { - Player player = user.getPlayer(); + public void run(Player viewer, CosmeticHolder cosmeticHolder, String raw) { String[] processedString = raw.split(" "); String soundName = processedString[0]; @@ -31,6 +31,11 @@ public class ActionSound extends Action { MessagesUtil.sendDebugMessages("Attempting to play " + soundName, Level.INFO); - player.playSound(player.getLocation(), soundName, volume, pitch); + viewer.playSound(viewer.getLocation(), soundName, volume, pitch); + } + + @Override + public void run(@NotNull CosmeticUser user, @NotNull String raw) { + run(user.getPlayer(), user, raw); } } diff --git a/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionUnequip.java b/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionUnequip.java index 636845a3..cbade786 100644 --- a/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionUnequip.java +++ b/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/action/actions/ActionUnequip.java @@ -1,9 +1,10 @@ package com.hibiscusmc.hmccosmetics.gui.action.actions; +import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder; import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticSlot; import com.hibiscusmc.hmccosmetics.gui.action.Action; import com.hibiscusmc.hmccosmetics.user.CosmeticUser; -import org.apache.commons.lang3.EnumUtils; +import org.bukkit.entity.Player; public class ActionUnequip extends Action { @@ -12,10 +13,15 @@ public class ActionUnequip extends Action { } @Override - public void run(CosmeticUser user, String raw) { + public void run(Player viewer, CosmeticHolder cosmeticHolder, String raw) { if (!CosmeticSlot.contains(raw)) return; CosmeticSlot slot = CosmeticSlot.valueOf(raw); - user.removeCosmeticSlot(slot); + cosmeticHolder.removeCosmeticSlot(slot); + } + + @Override + public void run(CosmeticUser user, String raw) { + run(user.getPlayer(), user, raw); } } diff --git a/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/special/DyeMenu.java b/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/special/DyeMenu.java index 9486b4b7..952340be 100644 --- a/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/special/DyeMenu.java +++ b/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/special/DyeMenu.java @@ -6,6 +6,7 @@ import com.hibiscusmc.hmccolor.shaded.gui.guis.GuiItem; import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin; import com.hibiscusmc.hmccosmetics.config.Settings; import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic; +import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder; import com.hibiscusmc.hmccosmetics.user.CosmeticUser; import me.lojosho.hibiscuscommons.hooks.Hooks; import me.lojosho.hibiscuscommons.util.ColorBuilder; @@ -18,19 +19,16 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public class DyeMenu { - - public static void openMenu(@NotNull CosmeticUser user, Cosmetic cosmetic) { - Player player = user.getPlayer(); - if (player == null) return; + public static void openMenu(@NotNull Player viewer, @NotNull CosmeticHolder cosmeticHolder, Cosmetic cosmetic) { if (!Hooks.isActiveHook("HMCColor")) { - addCosmetic(user, cosmetic, null); + addCosmetic(viewer, cosmeticHolder, cosmetic, null); return; } ItemStack originalItem = cosmetic.getItem(); if (originalItem == null || !cosmetic.isDyable()) return; - Gui gui = HMCColorApi.createColorMenu(player); - gui.updateTitle(Hooks.processPlaceholders(player, StringUtils.parseStringToString(Settings.getDyeMenuName()))); + Gui gui = HMCColorApi.createColorMenu(viewer); + gui.updateTitle(Hooks.processPlaceholders(viewer, StringUtils.parseStringToString(Settings.getDyeMenuName()))); gui.setItem(Settings.getDyeMenuInputSlot(), new GuiItem(originalItem)); gui.setDefaultTopClickAction(event -> { if (event.getSlot() == Settings.getDyeMenuOutputSlot()) { @@ -54,23 +52,28 @@ public class DyeMenu { } if (color == null) return; - addCosmetic(user, cosmetic, color); + addCosmetic(viewer, cosmeticHolder, cosmetic, color); event.setCancelled(true); } else event.setCancelled(true); }); gui.setPlayerInventoryAction(event -> event.setCancelled(true)); gui.setCloseGuiAction(event -> {}); - gui.open(player); + gui.open(viewer); } - private static void addCosmetic(@NotNull CosmeticUser user, @NotNull Cosmetic cosmetic, @Nullable Color color) { + public static void openMenu(@NotNull CosmeticUser user, Cosmetic cosmetic) { Player player = user.getPlayer(); - user.addPlayerCosmetic(cosmetic, color); - player.setItemOnCursor(new ItemStack(Material.AIR)); + if (player == null) return; + openMenu(player, user, cosmetic); + } + + private static void addCosmetic(@NotNull Player viewer, @NotNull CosmeticHolder cosmeticHolder, @NotNull Cosmetic cosmetic, @Nullable Color color) { + cosmeticHolder.addCosmetic(cosmetic, color); + viewer.setItemOnCursor(new ItemStack(Material.AIR)); Bukkit.getScheduler().runTaskLater(HMCCosmeticsPlugin.getInstance(), () -> { - player.closeInventory(); - user.updateCosmetic(cosmetic.getSlot()); + viewer.closeInventory(); + cosmeticHolder.updateCosmetic(cosmetic.getSlot()); }, 2); } } diff --git a/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/type/Type.java b/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/type/Type.java index 49b2768a..cd0cb355 100644 --- a/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/type/Type.java +++ b/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/type/Type.java @@ -1,7 +1,9 @@ package com.hibiscusmc.hmccosmetics.gui.type; +import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder; import com.hibiscusmc.hmccosmetics.user.CosmeticUser; import me.lojosho.shaded.configurate.ConfigurationNode; +import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; @@ -18,11 +20,32 @@ public abstract class Type { return this.id; } - public void run(CosmeticUser user, ConfigurationNode config) { - run(user, config, null); + public void run(Player viewer, CosmeticHolder cosmeticHolder, ConfigurationNode config) { + run(viewer, cosmeticHolder, config, null); } + public void run(Player viewer, CosmeticHolder cosmeticHolder, ConfigurationNode config, ClickType clickType) { + run(CosmeticHolder.ensureSingleCosmeticUser(viewer, cosmeticHolder), config, clickType); + } + + public void run(CosmeticUser user, ConfigurationNode config) { + final var player = user.getPlayer(); + if (player == null) return; + run(player, user, config, null); + } + + /** + * @deprecated Override {@link #run(Player, CosmeticHolder, ConfigurationNode, ClickType)} instead. + */ + @Deprecated public abstract void run(CosmeticUser user, ConfigurationNode config, ClickType clickType); + public ItemStack setItem(Player viewer, CosmeticHolder cosmeticHolder, ConfigurationNode config, ItemStack itemStack, int slot) { + return setItem(CosmeticHolder.ensureSingleCosmeticUser(viewer, cosmeticHolder), config, itemStack, slot); + } + + /** + * @deprecated Override {@link #setItem(Player, CosmeticHolder, ConfigurationNode, ItemStack, int)} instead. + */ public abstract ItemStack setItem(CosmeticUser user, ConfigurationNode config, ItemStack itemStack, int slot); } diff --git a/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/type/types/TypeCosmetic.java b/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/type/types/TypeCosmetic.java index 7c927c3d..c4679812 100644 --- a/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/type/types/TypeCosmetic.java +++ b/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/type/types/TypeCosmetic.java @@ -3,6 +3,7 @@ package com.hibiscusmc.hmccosmetics.gui.type.types; import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin; import com.hibiscusmc.hmccosmetics.config.Settings; import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic; +import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder; import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetics; import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticArmorType; import com.hibiscusmc.hmccosmetics.gui.action.Actions; @@ -38,7 +39,7 @@ public class TypeCosmetic extends Type { } @Override - public void run(CosmeticUser user, @NotNull ConfigurationNode config, ClickType clickType) { + public void run(Player viewer, CosmeticHolder cosmeticHolder, ConfigurationNode config, ClickType clickType) { MessagesUtil.sendDebugMessages("Running Cosmetic Click Type"); if (config.node("cosmetic").virtual()) { MessagesUtil.sendDebugMessages("Cosmetic Config Field Virtual"); @@ -46,21 +47,20 @@ public class TypeCosmetic extends Type { } String cosmeticName = config.node("cosmetic").getString(); Cosmetic cosmetic = Cosmetics.getCosmetic(cosmeticName); - Player player = user.getPlayer(); if (cosmetic == null) { MessagesUtil.sendDebugMessages("No Cosmetic Found"); - MessagesUtil.sendMessage(player, "invalid-cosmetic"); + MessagesUtil.sendMessage(viewer, "invalid-cosmetic"); return; } - if (!user.canEquipCosmetic(cosmetic)) { + if (!cosmeticHolder.canEquipCosmetic(cosmetic)) { MessagesUtil.sendDebugMessages("No Cosmetic Permission"); - MessagesUtil.sendMessage(player, "no-cosmetic-permission"); + MessagesUtil.sendMessage(viewer, "no-cosmetic-permission"); return; } boolean isUnEquippingCosmetic = false; - if (user.getCosmetic(cosmetic.getSlot()) == cosmetic) isUnEquippingCosmetic = true; + if (cosmeticHolder.getCosmetic(cosmetic.getSlot()) == cosmetic) isUnEquippingCosmetic = true; String requiredClick; if (isUnEquippingCosmetic) requiredClick = Settings.getCosmeticUnEquipClickType(); @@ -69,7 +69,7 @@ public class TypeCosmetic extends Type { MessagesUtil.sendDebugMessages("Required click type: " + requiredClick); MessagesUtil.sendDebugMessages("Click type: " + clickType.name()); if (!requiredClick.equalsIgnoreCase("ANY") && !requiredClick.equalsIgnoreCase(clickType.name())) { - MessagesUtil.sendMessage(user.getPlayer(), "invalid-click-type"); + MessagesUtil.sendMessage(viewer.getPlayer(), "invalid-click-type"); return; } @@ -99,25 +99,25 @@ public class TypeCosmetic extends Type { if (isUnEquippingCosmetic) { if (!actionConfig.node("on-unequip").virtual()) actionStrings.addAll(actionConfig.node("on-unequip").getList(String.class)); MessagesUtil.sendDebugMessages("on-unequip"); - user.removeCosmeticSlot(cosmetic); + cosmeticHolder.removeCosmeticSlot(cosmetic); } else { if (!actionConfig.node("on-equip").virtual()) actionStrings.addAll(actionConfig.node("on-equip").getList(String.class)); MessagesUtil.sendDebugMessages("on-equip"); // TODO: Redo this if (cosmetic.isDyable() && Hooks.isActiveHook("HMCColor")) { - DyeMenu.openMenu(user, cosmetic); + DyeMenu.openMenu(viewer, cosmeticHolder, cosmetic); } else { - user.addPlayerCosmetic(cosmetic); + cosmeticHolder.addCosmetic(cosmetic); } } - Actions.runActions(user, actionStrings); + Actions.runActions(viewer, cosmeticHolder, actionStrings); } catch (SerializationException e) { e.printStackTrace(); } // Fixes issue with offhand cosmetics not appearing. Yes, I know this is dumb - Runnable run = () -> user.updateCosmetic(cosmetic.getSlot()); + Runnable run = () -> cosmeticHolder.updateCosmetic(cosmetic.getSlot()); if (cosmetic instanceof CosmeticArmorType) { if (((CosmeticArmorType) cosmetic).getEquipSlot().equals(EquipmentSlot.OFF_HAND)) { Bukkit.getScheduler().runTaskLater(HMCCosmeticsPlugin.getInstance(), run, 1); @@ -128,8 +128,18 @@ public class TypeCosmetic extends Type { } @Override - public ItemStack setItem(@NotNull CosmeticUser user, @NotNull ConfigurationNode config, @NotNull ItemStack itemStack, int slot) { - if (itemStack.hasItemMeta()) itemStack.setItemMeta(processLoreLines(user, itemStack.getItemMeta())); + public void run(CosmeticUser user, @NotNull ConfigurationNode config, ClickType clickType) { + run(user.getPlayer(), user, config, clickType); + } + + @Override + public ItemStack setItem(CosmeticUser user, ConfigurationNode config, ItemStack itemStack, int slot) { + return setItem(user.getPlayer(), user, config, itemStack, slot); + } + + @Override + public ItemStack setItem(@NotNull Player viewer, @NotNull CosmeticHolder cosmeticHolder, @NotNull ConfigurationNode config, @NotNull ItemStack itemStack, int slot) { + if (itemStack.hasItemMeta()) itemStack.setItemMeta(processLoreLines(viewer, itemStack.getItemMeta())); else MessagesUtil.sendDebugMessages("ItemStack has no ItemMeta?"); if (config.node("cosmetic").virtual()) { @@ -141,9 +151,9 @@ public class TypeCosmetic extends Type { return itemStack; } - if (user.hasCosmeticInSlot(cosmetic) && (!config.node("equipped-item").virtual() || !config.node("locked-equipped-item").virtual())) { + if (cosmeticHolder.hasCosmeticInSlot(cosmetic) && (!config.node("equipped-item").virtual() || !config.node("locked-equipped-item").virtual())) { MessagesUtil.sendDebugMessages("GUI Equipped Item"); - ConfigurationNode equippedItem = config.node(user.canEquipCosmetic(cosmetic, true) && !config.node("equipped-item").virtual() ? "equipped-item" : "locked-equipped-item"); + ConfigurationNode equippedItem = config.node(cosmeticHolder.canEquipCosmetic(cosmetic, true) && !config.node("equipped-item").virtual() ? "equipped-item" : "locked-equipped-item"); try { if (equippedItem.node("material").virtual()) equippedItem.node("material").set(config.node("item", "material").getString()); } catch (SerializationException e) { @@ -154,12 +164,12 @@ public class TypeCosmetic extends Type { } catch (SerializationException e) { throw new RuntimeException(e); } - if (itemStack.hasItemMeta()) itemStack.setItemMeta(processLoreLines(user, itemStack.getItemMeta())); + if (itemStack.hasItemMeta()) itemStack.setItemMeta(processLoreLines(viewer, itemStack.getItemMeta())); else MessagesUtil.sendDebugMessages("ItemStack has no ItemMeta in equipped item?"); return itemStack; } - if (!user.canEquipCosmetic(cosmetic, true) && !config.node("locked-item").virtual()) { + if (!cosmeticHolder.canEquipCosmetic(cosmetic, true) && !config.node("locked-item").virtual()) { MessagesUtil.sendDebugMessages("GUI Locked Item"); ConfigurationNode lockedItem = config.node("locked-item"); try { @@ -172,7 +182,7 @@ public class TypeCosmetic extends Type { } catch (SerializationException e) { throw new RuntimeException(e); } - if (itemStack.hasItemMeta()) itemStack.setItemMeta(processLoreLines(user, itemStack.getItemMeta())); + if (itemStack.hasItemMeta()) itemStack.setItemMeta(processLoreLines(viewer, itemStack.getItemMeta())); else MessagesUtil.sendDebugMessages("ItemStack has no ItemMeta in locked item?"); return itemStack; } @@ -182,22 +192,22 @@ public class TypeCosmetic extends Type { @Contract("_, _ -> param2") @NotNull @SuppressWarnings("Duplicates") - private ItemMeta processLoreLines(CosmeticUser user, @NotNull ItemMeta itemMeta) { + private ItemMeta processLoreLines(Player viewer, @NotNull ItemMeta itemMeta) { List processedLore = new ArrayList<>(); if (itemMeta.hasDisplayName()) { - itemMeta.setDisplayName(Hooks.processPlaceholders(user.getPlayer(), itemMeta.getDisplayName())); + itemMeta.setDisplayName(Hooks.processPlaceholders(viewer, itemMeta.getDisplayName())); } if (itemMeta.hasLore()) { for (String loreLine : itemMeta.getLore()) { - processedLore.add(Hooks.processPlaceholders(user.getPlayer(), loreLine)); + processedLore.add(Hooks.processPlaceholders(viewer, loreLine)); } } if (itemMeta instanceof SkullMeta skullMeta) { if (skullMeta.hasOwner() && skullMeta.getOwner() != null) { - skullMeta.setOwner(Hooks.processPlaceholders(user.getPlayer(), skullMeta.getOwner())); + skullMeta.setOwner(Hooks.processPlaceholders(viewer, skullMeta.getOwner())); } } itemMeta.setLore(processedLore); diff --git a/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/type/types/TypeEmpty.java b/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/type/types/TypeEmpty.java index 447da1fd..38d52f85 100644 --- a/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/type/types/TypeEmpty.java +++ b/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/type/types/TypeEmpty.java @@ -1,11 +1,13 @@ package com.hibiscusmc.hmccosmetics.gui.type.types; +import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder; import com.hibiscusmc.hmccosmetics.gui.action.Actions; import com.hibiscusmc.hmccosmetics.gui.type.Type; import com.hibiscusmc.hmccosmetics.user.CosmeticUser; import me.lojosho.hibiscuscommons.hooks.Hooks; import me.lojosho.shaded.configurate.ConfigurationNode; import me.lojosho.shaded.configurate.serialize.SerializationException; +import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; @@ -23,9 +25,10 @@ public class TypeEmpty extends Type { // This is an empty type, meaning, when a menu item has a type of "empty" it will run the code in the method run. } - // This is the code that's run when the item is clicked. + // This is the code that's run when the item is clicked. The item is clicked by the "viewer" player in a menu for the + // given "cosmeticHolder". They're the same player by default, but it's not guaranteed. @Override - public void run(CosmeticUser user, @NotNull ConfigurationNode config, ClickType clickType) { + public void run(Player viewer, CosmeticHolder cosmeticHolder, @NotNull ConfigurationNode config, ClickType clickType) { List actionStrings = new ArrayList<>(); // List where we keep the actions the server will execute. ConfigurationNode actionConfig = config.node("actions"); // Configuration node that actions are under. @@ -52,31 +55,45 @@ public class TypeEmpty extends Type { } // We run the actions once we got the raw strings from the config. - Actions.runActions(user, actionStrings); + Actions.runActions(viewer, cosmeticHolder, actionStrings); } catch (SerializationException e) { throw new RuntimeException(e); } } + // backward-compatibility method, will not be required in the future + @Override + public void run(CosmeticUser user, ConfigurationNode config, ClickType clickType) { + final var player = user.getPlayer(); + if (player == null) return; + run(player, user, config, clickType); + } + + // backward-compatibility method, will not be required in the future + @Override + public ItemStack setItem(CosmeticUser user, ConfigurationNode config, ItemStack itemStack, int slot) { + return setItem(user.getPlayer(), user, config, itemStack, slot); + } + @Override @SuppressWarnings("Duplicates") - public ItemStack setItem(CosmeticUser user, ConfigurationNode config, @NotNull ItemStack itemStack, int slot) { + public ItemStack setItem(Player viewer, CosmeticHolder cosmeticHolder, ConfigurationNode config, @NotNull ItemStack itemStack, int slot) { List processedLore = new ArrayList<>(); ItemMeta itemMeta = itemStack.getItemMeta(); if (itemMeta.hasDisplayName()) { - itemMeta.setDisplayName(Hooks.processPlaceholders(user.getPlayer(), itemMeta.getDisplayName())); + itemMeta.setDisplayName(Hooks.processPlaceholders(viewer, itemMeta.getDisplayName())); } if (itemMeta.hasLore()) { for (String loreLine : itemMeta.getLore()) { - processedLore.add(Hooks.processPlaceholders(user.getPlayer(), loreLine)); + processedLore.add(Hooks.processPlaceholders(viewer, loreLine)); } } if (itemMeta instanceof SkullMeta skullMeta) { if (skullMeta.hasOwner() && skullMeta.getOwner() != null) { - skullMeta.setOwner(Hooks.processPlaceholders(user.getPlayer(), skullMeta.getOwner())); + skullMeta.setOwner(Hooks.processPlaceholders(viewer, skullMeta.getOwner())); } } diff --git a/common/src/main/java/com/hibiscusmc/hmccosmetics/user/CosmeticUser.java b/common/src/main/java/com/hibiscusmc/hmccosmetics/user/CosmeticUser.java index 8d446eb4..f5904d67 100644 --- a/common/src/main/java/com/hibiscusmc/hmccosmetics/user/CosmeticUser.java +++ b/common/src/main/java/com/hibiscusmc/hmccosmetics/user/CosmeticUser.java @@ -8,6 +8,7 @@ import com.hibiscusmc.hmccosmetics.config.Settings; import com.hibiscusmc.hmccosmetics.config.Wardrobe; import com.hibiscusmc.hmccosmetics.config.WardrobeSettings; import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic; +import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder; import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticSlot; import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticArmorType; import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticBackpackType; @@ -44,7 +45,7 @@ import org.jetbrains.annotations.Nullable; import java.util.*; import java.util.logging.Level; -public class CosmeticUser { +public class CosmeticUser implements CosmeticHolder { @Getter private final UUID uniqueId; private int taskId = -1; @@ -207,19 +208,18 @@ public class CosmeticUser { despawnBalloon(); } + @Override public Cosmetic getCosmetic(CosmeticSlot slot) { return playerCosmetics.get(slot); } + @Override public ImmutableCollection getCosmetics() { return ImmutableList.copyOf(playerCosmetics.values()); } - public void addPlayerCosmetic(@NotNull Cosmetic cosmetic) { - addPlayerCosmetic(cosmetic, null); - } - - public void addPlayerCosmetic(@NotNull Cosmetic cosmetic, @Nullable Color color) { + @Override + public void addCosmetic(@NotNull Cosmetic cosmetic, @Nullable Color color) { // API PlayerCosmeticEquipEvent event = new PlayerCosmeticEquipEvent(this, cosmetic); Bukkit.getPluginManager().callEvent(event); @@ -251,13 +251,23 @@ public class CosmeticUser { Bukkit.getPluginManager().callEvent(postEquipEvent); } - public void removeCosmetics() { - // Small optimization could be made, but Concurrent modification prevents us from both getting and removing - for (CosmeticSlot slot : CosmeticSlot.values().values()) { - removeCosmeticSlot(slot); - } + /** + * @deprecated Use {@link #addCosmetic(Cosmetic)} instead + */ + @Deprecated + public void addPlayerCosmetic(@NotNull Cosmetic cosmetic) { + addCosmetic(cosmetic); } + /** + * @deprecated Use {@link #addCosmetic(Cosmetic, Color)} instead + */ + @Deprecated + public void addPlayerCosmetic(@NotNull Cosmetic cosmetic, @Nullable Color color) { + addCosmetic(cosmetic, color); + } + + @Override public void removeCosmeticSlot(CosmeticSlot slot) { // API PlayerCosmeticRemoveEvent event = new PlayerCosmeticRemoveEvent(this, getCosmetic(slot)); @@ -280,23 +290,16 @@ public class CosmeticUser { removeArmor(slot); } - public void removeCosmeticSlot(Cosmetic cosmetic) { - removeCosmeticSlot(cosmetic.getSlot()); - } - + @Override public boolean hasCosmeticInSlot(CosmeticSlot slot) { return playerCosmetics.containsKey(slot); } - public boolean hasCosmeticInSlot(Cosmetic cosmetic) { - if (getCosmetic(cosmetic.getSlot()) == null) return false; - return Objects.equals(cosmetic.getId(), getCosmetic(cosmetic.getSlot()).getId()); - } - public Set getSlotsWithCosmetics() { return Set.copyOf(playerCosmetics.keySet()); } + @Override public void updateCosmetic(CosmeticSlot slot) { if (getCosmetic(slot) == null) { return; @@ -637,10 +640,7 @@ public class CosmeticUser { return dyableSlots; } - public boolean canEquipCosmetic(Cosmetic cosmetic) { - return canEquipCosmetic(cosmetic, false); - } - + @Override public boolean canEquipCosmetic(Cosmetic cosmetic, boolean ignoreWardrobe) { if (!cosmetic.requiresPermission()) return true; if (isInWardrobe() && !ignoreWardrobe) { From f470e551429da3da6a46f6019d13f8b2ae9b68e3 Mon Sep 17 00:00:00 2001 From: yusshu Date: Sat, 1 Mar 2025 18:12:27 -0500 Subject: [PATCH 2/4] chore: bump up minor version --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index b6835c1c..82d46ea9 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,7 @@ plugins { } group = "com.hibiscusmc" -version = "2.7.6${getGitCommitHash()}" +version = "2.8.0${getGitCommitHash()}" allprojects { apply(plugin = "java") From 52de7425e4d21b965bd76af69be1ad1b5fd0c765 Mon Sep 17 00:00:00 2001 From: yusshu Date: Sat, 1 Mar 2025 18:14:25 -0500 Subject: [PATCH 3/4] fix: fix compiling error --- .../java/com/hibiscusmc/hmccosmetics/gui/Menu.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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 bac5ac3f..f177c097 100644 --- a/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/Menu.java +++ b/common/src/main/java/com/hibiscusmc/hmccosmetics/gui/Menu.java @@ -266,7 +266,7 @@ public class Menu { for (MenuItem item : menuItems) { Type type = item.type(); - ItemStack modifiedItem = getMenuItem(user, type, item.itemConfig(), item.item().clone(), slot); + ItemStack modifiedItem = getMenuItem(viewer, cosmeticHolder, type, item.itemConfig(), item.item().clone(), slot); if (modifiedItem.getType().isAir()) continue; GuiItem guiItem = ItemBuilder.from(modifiedItem).asGuiItem(); guiItem.setAction(event -> { @@ -283,7 +283,7 @@ public class Menu { } MessagesUtil.sendDebugMessages("Updated Menu Item in slot number " + slot); final ClickType clickType = event.getClick(); - if (type != null) type.run(user, item.itemConfig(), clickType); + if (type != null) type.run(viewer, cosmeticHolder, item.itemConfig(), clickType); updateMenu(viewer, cosmeticHolder, gui); }); @@ -319,11 +319,11 @@ public class Menu { return slots; } - @Contract("_, _, _, _, _ -> param2") + @Contract("_, _, _, _, _, _ -> param4") @NotNull - private ItemStack getMenuItem(CosmeticUser user, Type type, ConfigurationNode config, ItemStack itemStack, int slot) { + private ItemStack getMenuItem(Player viewer, CosmeticHolder cosmeticHolder, Type type, ConfigurationNode config, ItemStack itemStack, int slot) { if (!itemStack.hasItemMeta()) return itemStack; - return type.setItem(user, config, itemStack, slot); + return type.setItem(viewer, cosmeticHolder, config, itemStack, slot); } public boolean canOpen(Player player) { From 4136d19396ec948df2db7d24c1bb46c48315ec48 Mon Sep 17 00:00:00 2001 From: yusshu Date: Mon, 3 Mar 2025 00:05:19 -0500 Subject: [PATCH 4/4] *: go back to 2.7.7, add @NotNull and @Nullable annotations for CosmeticHolder interface --- build.gradle.kts | 2 +- .../hmccosmetics/cosmetic/CosmeticHolder.java | 18 +++++++++--------- .../hmccosmetics/user/CosmeticUser.java | 12 ++++++------ 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 82d46ea9..8757c67a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,7 @@ plugins { } group = "com.hibiscusmc" -version = "2.8.0${getGitCommitHash()}" +version = "2.7.7${getGitCommitHash()}" allprojects { apply(plugin = "java") diff --git a/common/src/main/java/com/hibiscusmc/hmccosmetics/cosmetic/CosmeticHolder.java b/common/src/main/java/com/hibiscusmc/hmccosmetics/cosmetic/CosmeticHolder.java index 2b4e8c8a..8f41ee4f 100644 --- a/common/src/main/java/com/hibiscusmc/hmccosmetics/cosmetic/CosmeticHolder.java +++ b/common/src/main/java/com/hibiscusmc/hmccosmetics/cosmetic/CosmeticHolder.java @@ -15,9 +15,9 @@ import java.util.Objects; * users, for example. */ public interface CosmeticHolder { - @Nullable Cosmetic getCosmetic(CosmeticSlot slot); + @Nullable Cosmetic getCosmetic(@NotNull CosmeticSlot slot); - ImmutableCollection getCosmetics(); + @NotNull ImmutableCollection getCosmetics(); void addCosmetic(@NotNull Cosmetic cosmetic, @Nullable Color color); @@ -32,29 +32,29 @@ public interface CosmeticHolder { } } - void removeCosmeticSlot(CosmeticSlot slot); + void removeCosmeticSlot(@NotNull CosmeticSlot slot); - default void removeCosmeticSlot(Cosmetic cosmetic) { + default void removeCosmeticSlot(@NotNull Cosmetic cosmetic) { removeCosmeticSlot(cosmetic.getSlot()); } - default boolean hasCosmeticInSlot(CosmeticSlot slot) { + default boolean hasCosmeticInSlot(@NotNull CosmeticSlot slot) { return getCosmetic(slot) != null; } - default boolean hasCosmeticInSlot(Cosmetic cosmetic) { + default boolean hasCosmeticInSlot(@NotNull Cosmetic cosmetic) { final var existingCosmetic = getCosmetic(cosmetic.getSlot()); if (existingCosmetic == null) return false; return Objects.equals(cosmetic.getId(), existingCosmetic.getId()); } - default boolean canEquipCosmetic(Cosmetic cosmetic) { + default boolean canEquipCosmetic(@NotNull Cosmetic cosmetic) { return canEquipCosmetic(cosmetic, false); } - boolean canEquipCosmetic(Cosmetic cosmetic, boolean ignoreWardrobe); + boolean canEquipCosmetic(@NotNull Cosmetic cosmetic, boolean ignoreWardrobe); - void updateCosmetic(CosmeticSlot slot); + void updateCosmetic(@NotNull CosmeticSlot slot); /** * Just for backwards compatibility, ensures that the given viewer and the given cosmetic holder diff --git a/common/src/main/java/com/hibiscusmc/hmccosmetics/user/CosmeticUser.java b/common/src/main/java/com/hibiscusmc/hmccosmetics/user/CosmeticUser.java index f5904d67..70f78d0a 100644 --- a/common/src/main/java/com/hibiscusmc/hmccosmetics/user/CosmeticUser.java +++ b/common/src/main/java/com/hibiscusmc/hmccosmetics/user/CosmeticUser.java @@ -209,12 +209,12 @@ public class CosmeticUser implements CosmeticHolder { } @Override - public Cosmetic getCosmetic(CosmeticSlot slot) { + public Cosmetic getCosmetic(@NotNull CosmeticSlot slot) { return playerCosmetics.get(slot); } @Override - public ImmutableCollection getCosmetics() { + public @NotNull ImmutableCollection getCosmetics() { return ImmutableList.copyOf(playerCosmetics.values()); } @@ -268,7 +268,7 @@ public class CosmeticUser implements CosmeticHolder { } @Override - public void removeCosmeticSlot(CosmeticSlot slot) { + public void removeCosmeticSlot(@NotNull CosmeticSlot slot) { // API PlayerCosmeticRemoveEvent event = new PlayerCosmeticRemoveEvent(this, getCosmetic(slot)); Bukkit.getPluginManager().callEvent(event); @@ -291,7 +291,7 @@ public class CosmeticUser implements CosmeticHolder { } @Override - public boolean hasCosmeticInSlot(CosmeticSlot slot) { + public boolean hasCosmeticInSlot(@NotNull CosmeticSlot slot) { return playerCosmetics.containsKey(slot); } @@ -300,7 +300,7 @@ public class CosmeticUser implements CosmeticHolder { } @Override - public void updateCosmetic(CosmeticSlot slot) { + public void updateCosmetic(@NotNull CosmeticSlot slot) { if (getCosmetic(slot) == null) { return; } @@ -641,7 +641,7 @@ public class CosmeticUser implements CosmeticHolder { } @Override - public boolean canEquipCosmetic(Cosmetic cosmetic, boolean ignoreWardrobe) { + public boolean canEquipCosmetic(@NotNull Cosmetic cosmetic, boolean ignoreWardrobe) { if (!cosmetic.requiresPermission()) return true; if (isInWardrobe() && !ignoreWardrobe) { if (WardrobeSettings.isTryCosmeticsInWardrobe() && userWardrobeManager.getWardrobeStatus().equals(UserWardrobeManager.WardrobeStatus.RUNNING)) return true;