From e6eefc995b22b0474150bfd118dbb31f7ed920c0 Mon Sep 17 00:00:00 2001 From: YouHaveTrouble Date: Sat, 22 Nov 2025 15:26:48 +0100 Subject: [PATCH] basic armor stand edit screen interaction --- .../me/youhavetrouble/standin/StandIn.java | 8 +- .../youhavetrouble/standin/StandinDialog.java | 35 +++++++-- .../stand/StandinInteractionListener.java | 77 +++++++++++++++++++ 3 files changed, 109 insertions(+), 11 deletions(-) create mode 100644 src/main/java/me/youhavetrouble/standin/stand/StandinInteractionListener.java diff --git a/src/main/java/me/youhavetrouble/standin/StandIn.java b/src/main/java/me/youhavetrouble/standin/StandIn.java index 955498f..7eefab7 100644 --- a/src/main/java/me/youhavetrouble/standin/StandIn.java +++ b/src/main/java/me/youhavetrouble/standin/StandIn.java @@ -1,5 +1,6 @@ package me.youhavetrouble.standin; +import me.youhavetrouble.standin.stand.StandinInteractionListener; import org.bukkit.NamespacedKey; import org.bukkit.plugin.java.JavaPlugin; @@ -9,12 +10,7 @@ public final class StandIn extends JavaPlugin { @Override public void onEnable() { - // Plugin startup logic - + getServer().getPluginManager().registerEvents(new StandinInteractionListener(), this); } - @Override - public void onDisable() { - // Plugin shutdown logic - } } diff --git a/src/main/java/me/youhavetrouble/standin/StandinDialog.java b/src/main/java/me/youhavetrouble/standin/StandinDialog.java index c95e30d..7aef413 100644 --- a/src/main/java/me/youhavetrouble/standin/StandinDialog.java +++ b/src/main/java/me/youhavetrouble/standin/StandinDialog.java @@ -8,7 +8,7 @@ import io.papermc.paper.registry.data.dialog.input.DialogInput; import io.papermc.paper.registry.data.dialog.type.DialogType; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.event.ClickCallback; -import net.kyori.adventure.util.TriState; +import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; import org.bukkit.entity.ArmorStand; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; @@ -30,9 +30,14 @@ public class StandinDialog { List inputs = new ArrayList<>(); + String currentName = ""; + if (armorStand.customName() != null) { + currentName = PlainTextComponentSerializer.plainText().serialize(armorStand.name()); + } + inputs.add( DialogInput.text("name", Component.text("Display name")) - .labelVisible(true) + .initial(currentName) .build() ); inputs.add( @@ -42,8 +47,20 @@ public class StandinDialog { ); inputs.add( - DialogInput.bool("onFire", Component.text("On fire")) - .initial(Boolean.TRUE.equals(armorStand.getVisualFire().toBoolean())) + DialogInput.bool("basePlate", Component.text("Base plate")) + .initial(armorStand.hasBasePlate()) + .build() + ); + + inputs.add( + DialogInput.bool("arms", Component.text("Arms")) + .initial(armorStand.hasArms()) + .build() + ); + + inputs.add( + DialogInput.bool("small", Component.text("Small")) + .initial(armorStand.isSmall()) .build() ); @@ -53,8 +70,16 @@ public class StandinDialog { Entity entity = callbackPlayer.getWorld().getEntity(armorStandId); if (!(entity instanceof ArmorStand stand)) return; if (stand.isDead()) return; + String customName = view.getText("name"); + if (customName == null || customName.isEmpty()) { + stand.customName(null); + } else { + stand.customName(Component.text(customName)); + } stand.setInvisible(Boolean.TRUE.equals(view.getBoolean("invisible"))); - stand.setVisualFire(TriState.byBoolean(Boolean.TRUE.equals(view.getBoolean("onFire")))); + stand.setBasePlate(Boolean.TRUE.equals(view.getBoolean("basePlate"))); + stand.setArms(Boolean.TRUE.equals(view.getBoolean("arms"))); + stand.setSmall(Boolean.TRUE.equals(view.getBoolean("small"))); }, ClickCallback.Options.builder().lifetime(Duration.ofHours(1)).uses(1).build()) ).build(); diff --git a/src/main/java/me/youhavetrouble/standin/stand/StandinInteractionListener.java b/src/main/java/me/youhavetrouble/standin/stand/StandinInteractionListener.java new file mode 100644 index 0000000..865eeb4 --- /dev/null +++ b/src/main/java/me/youhavetrouble/standin/stand/StandinInteractionListener.java @@ -0,0 +1,77 @@ +package me.youhavetrouble.standin.stand; + +import me.youhavetrouble.standin.StandinDialog; +import org.bukkit.attribute.Attribute; +import org.bukkit.attribute.AttributeInstance; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerInteractAtEntityEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.EquipmentSlot; +import org.bukkit.util.RayTraceResult; +import org.jetbrains.annotations.NotNull; + +public class StandinInteractionListener implements Listener { + + private boolean handleInteraction(@NotNull Player player, Entity entity) { + if (entity == null) return false; + if (!player.isOnline()) return false; + + if (entity instanceof ArmorStand armorStand) { + StandinDialog.openArmorStandDialog(player, armorStand); + return true; + } + + return false; + } + + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = false) + public void onInteractWithDisplays(PlayerInteractEvent event) { + if (!event.getPlayer().isSneaking()) return; + if (event.getHand() == EquipmentSlot.OFF_HAND) return; + Player player = event.getPlayer(); + + AttributeInstance instance = player.getAttribute(Attribute.ENTITY_INTERACTION_RANGE); + if (instance == null) return; + + double interactionRange = instance.getValue(); + + RayTraceResult result = player.getWorld().rayTraceEntities( + player.getEyeLocation(), + player.getEyeLocation().getDirection(), + interactionRange, + 0.5, + (entity -> { + switch (entity.getType()) { + case TEXT_DISPLAY, + BLOCK_DISPLAY, + ITEM_DISPLAY -> { + if (entity.getVehicle() == null) return true; + return !player.getUniqueId().equals(entity.getVehicle().getUniqueId()); + } + default -> { + return false; + } + } + }) + ); + if (result == null) return; + + Entity entity = result.getHitEntity(); + if (!handleInteraction(player, entity)) return; + event.setCancelled(true); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onInteractWithStands(PlayerInteractAtEntityEvent event) { + if (!event.getPlayer().isSneaking()) return; + if (!handleInteraction(event.getPlayer(), event.getRightClicked())) return; + event.setCancelled(true); + } + +}