From 87f0183e4fdd8f5a28e61e378b4fe516b9dd1338 Mon Sep 17 00:00:00 2001 From: Oliver Date: Wed, 30 Jul 2025 19:47:36 +0200 Subject: [PATCH] fancyholograms v3: Add traits command --- .../api/trait/HologramTrait.java | 4 +- .../api/trait/HologramTraitTrait.java | 32 +++++++ .../fancyholograms/commands/HologramCMD.java | 9 +- .../commands/hologram/TraitsCMD.java | 94 +++++++++++++++++++ 4 files changed, 136 insertions(+), 3 deletions(-) create mode 100644 plugins/fancyholograms/src/main/java/com/fancyinnovations/fancyholograms/commands/hologram/TraitsCMD.java diff --git a/plugins/fancyholograms/fh-api/src/main/java/com/fancyinnovations/fancyholograms/api/trait/HologramTrait.java b/plugins/fancyholograms/fh-api/src/main/java/com/fancyinnovations/fancyholograms/api/trait/HologramTrait.java index de60f7b3..a8e0b8fa 100644 --- a/plugins/fancyholograms/fh-api/src/main/java/com/fancyinnovations/fancyholograms/api/trait/HologramTrait.java +++ b/plugins/fancyholograms/fh-api/src/main/java/com/fancyinnovations/fancyholograms/api/trait/HologramTrait.java @@ -107,7 +107,7 @@ public abstract class HologramTrait { throw new IllegalArgumentException("Trait class " + getClass() + " is not annotated with HologramTraitClass"); } - protected final boolean isTraitAttached(Class trait) { + public final boolean isTraitAttached(Class trait) { for (HologramTrait hologramTrait : hologram.getData().getTraitTrait().getTraits()) { if (hologramTrait.getClass().equals(trait)) { return true; @@ -117,7 +117,7 @@ public abstract class HologramTrait { return false; } - protected final T getTrait(Class trait) { + public final T getTrait(Class trait) { for (HologramTrait hologramTrait : hologram.getData().getTraitTrait().getTraits()) { if (hologramTrait.getClass().equals(trait)) { return (T) hologramTrait; diff --git a/plugins/fancyholograms/fh-api/src/main/java/com/fancyinnovations/fancyholograms/api/trait/HologramTraitTrait.java b/plugins/fancyholograms/fh-api/src/main/java/com/fancyinnovations/fancyholograms/api/trait/HologramTraitTrait.java index 1cf14737..bc1bdcde 100644 --- a/plugins/fancyholograms/fh-api/src/main/java/com/fancyinnovations/fancyholograms/api/trait/HologramTraitTrait.java +++ b/plugins/fancyholograms/fh-api/src/main/java/com/fancyinnovations/fancyholograms/api/trait/HologramTraitTrait.java @@ -28,6 +28,38 @@ public class HologramTraitTrait extends HologramTrait { } } + public void addTrait(Class trait) { + try { + HologramTrait newTrait = trait.getConstructor().newInstance(); + addTrait(newTrait); + } catch (Exception e) { + logger.error("Failed to instantiate trait " + trait.getSimpleName()); + logger.error(e); + } + } + + public void removeTrait(HologramTrait trait) { + if (this.traits.remove(trait)) { + // Detach the trait from the hologram if it was successfully removed + if (hologram != null) { + trait.onUnregister(); + logger.debug("Detached trait " + trait.getClass().getSimpleName() + " from hologram " + hologram.getData().getName()); + } + } else { + logger.warn("Trait " + trait.getClass().getSimpleName() + " not found in hologram " + hologram.getData().getName()); + } + } + + public void removeTrait(Class trait) { + for (HologramTrait t : this.traits) { + if (t.getClass().equals(trait)) { + removeTrait(t); + return; + } + } + logger.warn("Trait " + trait.getSimpleName() + " not found in hologram " + hologram.getData().getName()); + } + @Override public void onAttach() { // Attach all default traits to the hologram diff --git a/plugins/fancyholograms/src/main/java/com/fancyinnovations/fancyholograms/commands/HologramCMD.java b/plugins/fancyholograms/src/main/java/com/fancyinnovations/fancyholograms/commands/HologramCMD.java index 43af24f9..377bc6c3 100644 --- a/plugins/fancyholograms/src/main/java/com/fancyinnovations/fancyholograms/commands/HologramCMD.java +++ b/plugins/fancyholograms/src/main/java/com/fancyinnovations/fancyholograms/commands/HologramCMD.java @@ -191,7 +191,7 @@ public final class HologramCMD extends Command { final var usingNpcs = PluginUtils.isFancyNpcsEnabled(); - List suggestions = new ArrayList<>(Arrays.asList("position", "moveHere", "center", "moveTo", "rotate", "rotatepitch", "billboard", "scale", "translate", "visibilityDistance", "visibility", "shadowRadius", "shadowStrength", "brightness", usingNpcs ? "linkWithNpc" : "", usingNpcs ? "unlinkWithNpc" : "")); + List suggestions = new ArrayList<>(Arrays.asList("traits", "position", "moveHere", "center", "moveTo", "rotate", "rotatepitch", "billboard", "scale", "translate", "visibilityDistance", "visibility", "shadowRadius", "shadowStrength", "brightness", usingNpcs ? "linkWithNpc" : "", usingNpcs ? "unlinkWithNpc" : "")); suggestions.addAll(type.getCommands()); return suggestions.stream().filter(input -> input.toLowerCase().startsWith(args[2].toLowerCase(Locale.ROOT))).toList(); @@ -201,6 +201,10 @@ public final class HologramCMD extends Command { return Collections.emptyList(); } + if (args[2].equalsIgnoreCase("traits")) { + return new TraitsCMD().tabcompletion(sender, hologram, args); + } + // /holo edit [hologram] [option] {tab:contextual} if (args.length == 4) { final var suggestions = switch (args[2].toLowerCase(Locale.ROOT)) { @@ -349,6 +353,9 @@ public final class HologramCMD extends Command { } return switch (action) { + // hologram data + case "traits" -> new TraitsCMD().run(player, hologram, args); + // display data case "moveto" -> new MoveToCMD().run(player, hologram, args); case "rotate" -> new RotateCMD().run(player, hologram, args); diff --git a/plugins/fancyholograms/src/main/java/com/fancyinnovations/fancyholograms/commands/hologram/TraitsCMD.java b/plugins/fancyholograms/src/main/java/com/fancyinnovations/fancyholograms/commands/hologram/TraitsCMD.java new file mode 100644 index 00000000..52c0719f --- /dev/null +++ b/plugins/fancyholograms/src/main/java/com/fancyinnovations/fancyholograms/commands/hologram/TraitsCMD.java @@ -0,0 +1,94 @@ +package com.fancyinnovations.fancyholograms.commands.hologram; + +import com.fancyinnovations.fancyholograms.api.FancyHolograms; +import com.fancyinnovations.fancyholograms.api.hologram.Hologram; +import com.fancyinnovations.fancyholograms.api.trait.HologramTraitRegistry; +import com.fancyinnovations.fancyholograms.commands.Subcommand; +import de.oliver.fancylib.MessageHelper; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public class TraitsCMD implements Subcommand { + + @Override + public List tabcompletion(@NotNull CommandSender player, @Nullable Hologram hologram, @NotNull String[] args) { + if (args.length == 4) { + return List.of("add", "remove"); + } else if (args.length == 5) { + return FancyHolograms.get().getTraitRegistry().getTraits() + .stream() + .filter(ti -> !ti.isDefault()) + .filter(ti -> { + if (args[3].equalsIgnoreCase("add")) { + return !hologram.getData().getTraitTrait().isTraitAttached(ti.clazz()); + } else if (args[3].equalsIgnoreCase("remove")) { + return hologram.getData().getTraitTrait().isTraitAttached(ti.clazz()); + } + + return true; + }) + .map(HologramTraitRegistry.TraitInfo::name) + .toList(); + } + + return List.of(); + } + + @Override + public boolean run(@NotNull CommandSender player, @Nullable Hologram hologram, @NotNull String[] args) { + if (!(player.hasPermission("fancyholograms.hologram.edit.traits"))) { + MessageHelper.error(player, "You don't have the required permission to change traits of a hologram."); + return false; + } + + // /hologram edit traits + + if (args.length < 5) { + MessageHelper.error(player, "Usage: /hologram edit traits "); + return false; + } + + String action = args[3]; + String traitName = args[4]; + if (traitName == null || traitName.isEmpty()) { + MessageHelper.error(player, "You must specify a trait name."); + return false; + } + + HologramTraitRegistry.TraitInfo traitInfo = FancyHolograms.get().getTraitRegistry().getTrait(traitName); + if (traitInfo == null) { + MessageHelper.error(player, "Trait '" + traitName + "' does not exist."); + return false; + } + + switch (action.toLowerCase()) { + case "add": { + if (hologram.getData().getTraitTrait().isTraitAttached(traitInfo.clazz())) { + MessageHelper.error(player, "Trait '" + traitName + "' is already attached to hologram '" + hologram.getData().getName() + "'."); + return false; + } + + hologram.getData().getTraitTrait().addTrait(traitInfo.clazz()); + MessageHelper.success(player, "Trait '" + traitName + "' has been added to hologram '" + hologram.getData().getName() + "'."); + return true; + } + case "remove": { + if (!hologram.getData().getTraitTrait().isTraitAttached(traitInfo.clazz())) { + MessageHelper.error(player, "Trait '" + traitName + "' is not attached to hologram '" + hologram.getData().getName() + "'."); + return false; + } + + hologram.getData().getTraitTrait().removeTrait(traitInfo.clazz()); + MessageHelper.success(player, "Trait '" + traitName + "' has been removed from hologram '" + hologram.getData().getName() + "'."); + return true; + } + default: { + MessageHelper.error(player, "Invalid action. Use 'add' or 'remove'."); + return false; + } + } + } +}