From 64fd48ead6a57f9f21f830ad7d14f86977cd2203 Mon Sep 17 00:00:00 2001 From: tastybento Date: Fri, 27 Dec 2024 08:36:13 -0800 Subject: [PATCH 1/5] WIP - store data on Display Entities --- pom.xml | 7 + .../blueprints/BlueprintClipboard.java | 6 + .../dataobjects/BlueprintEntity.java | 147 ++++++++++++++++++ .../json/adapters/MaterialTypeAdapter.java | 2 +- .../bentobox/hooks/FancyHologramsHook.java | 35 +++++ .../bentobox/util/DefaultPasteUtil.java | 2 + src/main/resources/plugin.yml | 2 + 7 files changed, 200 insertions(+), 1 deletion(-) create mode 100644 src/main/java/world/bentobox/bentobox/hooks/FancyHologramsHook.java diff --git a/pom.xml b/pom.xml index e29d7d061..3198bfad0 100644 --- a/pom.xml +++ b/pom.xml @@ -419,6 +419,13 @@ 2.0.0-SNAPSHOT provided + + + de.oliver + FancyHolograms + 2.4.1 + provided + diff --git a/src/main/java/world/bentobox/bentobox/blueprints/BlueprintClipboard.java b/src/main/java/world/bentobox/bentobox/blueprints/BlueprintClipboard.java index 6d678bd08..a5ae6ad1b 100644 --- a/src/main/java/world/bentobox/bentobox/blueprints/BlueprintClipboard.java +++ b/src/main/java/world/bentobox/bentobox/blueprints/BlueprintClipboard.java @@ -22,6 +22,7 @@ import org.bukkit.entity.AbstractHorse; import org.bukkit.entity.Ageable; import org.bukkit.entity.ChestedHorse; +import org.bukkit.entity.Display; import org.bukkit.entity.Entity; import org.bukkit.entity.Horse; import org.bukkit.entity.Player; @@ -356,6 +357,11 @@ private List setEntities(List ents) { mmh.filter(mm -> mm.isMythicMob(entity)).map(mm -> mm.getMythicMob(entity)) .ifPresent(bpe::setMythicMobsRecord); + // Display entities + if (entity instanceof Display disp) { + BentoBox.getInstance().logDebug(disp.getAsString()); + bpe.storeDisplay(disp); + } bpEnts.add(bpe); } return bpEnts; diff --git a/src/main/java/world/bentobox/bentobox/blueprints/dataobjects/BlueprintEntity.java b/src/main/java/world/bentobox/bentobox/blueprints/dataobjects/BlueprintEntity.java index 2ce285fee..b37bc3fe5 100644 --- a/src/main/java/world/bentobox/bentobox/blueprints/dataobjects/BlueprintEntity.java +++ b/src/main/java/world/bentobox/bentobox/blueprints/dataobjects/BlueprintEntity.java @@ -2,19 +2,32 @@ import java.util.Map; +import org.bukkit.Color; import org.bukkit.DyeColor; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.block.BlockFace; +import org.bukkit.block.data.BlockData; import org.bukkit.entity.AbstractHorse; import org.bukkit.entity.Ageable; +import org.bukkit.entity.BlockDisplay; import org.bukkit.entity.ChestedHorse; +import org.bukkit.entity.Display; +import org.bukkit.entity.Display.Billboard; +import org.bukkit.entity.Display.Brightness; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; import org.bukkit.entity.Horse; import org.bukkit.entity.Horse.Style; +import org.bukkit.entity.ItemDisplay; import org.bukkit.entity.Tameable; +import org.bukkit.entity.TextDisplay; +import org.bukkit.entity.TextDisplay.TextAlignment; import org.bukkit.entity.Villager; import org.bukkit.entity.Villager.Profession; import org.bukkit.inventory.ItemStack; import org.bukkit.material.Colorable; +import org.bukkit.util.Transformation; import com.google.gson.annotations.Expose; @@ -342,4 +355,138 @@ public String toString() { + (villagerType != null ? "villagerType=" + villagerType : "") + "]"; } + + + + @Expose + public DisplayRec displayRec; + @Expose + public TextDisplayRec textDisp; + @Expose + public BlockData blockDisp; + @Expose + public ItemStack itemDisp; + + public record DisplayRec(@Expose Billboard billboard, @Expose Brightness brightness, @Expose float height, + @Expose float width, @Expose Color glowColorOverride, @Expose int interpolationDelay, + @Expose int interpolationDuration, @Expose float shadowRadius, @Expose float shadowStrength, + @Expose int teleportDuration, @Expose Transformation transformation, @Expose float range) { + } + + public record TextDisplayRec(@Expose String text, @Expose TextAlignment alignment, @Expose Color bgColor, + @Expose BlockFace face, @Expose int lWidth, @Expose byte opacity, @Expose boolean isShadowed, + @Expose boolean isSeeThrough, @Expose boolean isDefaultBg) { + } + + /** + * BlockDisplay, ItemDisplay, TextDisplay + * @param disp display entity + */ + public void storeDisplay(Display disp) { + // Generic items + displayRec = new DisplayRec(disp.getBillboard(), disp.getBrightness(), disp.getDisplayHeight(), + disp.getDisplayWidth(), disp.getGlowColorOverride(), disp.getInterpolationDelay(), + disp.getInterpolationDuration(), disp.getShadowRadius(), disp.getShadowStrength(), + disp.getTeleportDuration(), disp.getTransformation(), disp.getViewRange()); + // Class specific items + if (disp instanceof BlockDisplay bd) { + this.blockDisp = bd.getBlock(); + } else if (disp instanceof ItemDisplay id) { + itemDisp = id.getItemStack(); + } else if (disp instanceof TextDisplay td) { + textDisp = new TextDisplayRec(td.getText(), td.getAlignment(), td.getBackgroundColor(), + td.getFacing(), td.getLineWidth(), td.getTextOpacity(), td.isShadowed(), td.isSeeThrough(), + td.isDefaultBackground()); + } + + // , getBrightness, getDisplayHeight, getDisplayWidth, getGlowColorOverride, getInterpolationDelay, getInterpolationDuration, + //getShadowRadius, getShadowStrength, getTeleportDuration, getTransformation, getViewRange, setBillboard, setBrightness, + // setDisplayHeight, setDisplayWidth, setGlowColorOverride, setInterpolationDelay, setInterpolationDuration, setShadowRadius, setShadowStrength, setTeleportDuration, setTransformation, setTransformationMatrix, setViewRange + } + + /** + * Sets any display entity properties to the location, e.g. holograms + * @param pos location + */ + public void setDisplay(Location pos) { + World world = pos.getWorld(); + Display d = null; + if (this.blockDisp != null) { + // Block Display + d = world.spawn(pos, BlockDisplay.class); + ((BlockDisplay) d).setBlock(this.blockDisp); + } else if (this.itemDisp != null) { + // Item Display + d = world.spawn(pos, ItemDisplay.class); + ((ItemDisplay) d).setItemStack(itemDisp); + } else if (this.textDisp != null) { + // Block Display + d = world.spawn(pos, TextDisplay.class); + ((TextDisplay) d).setText(textDisp.text()); + ((TextDisplay) d).setAlignment(textDisp.alignment()); + ((TextDisplay) d).setBackgroundColor(textDisp.bgColor()); + ((TextDisplay) d).setLineWidth(textDisp.lWidth()); + ((TextDisplay) d).setTextOpacity(textDisp.opacity()); + ((TextDisplay) d).setShadowed(textDisp.isShadowed()); + ((TextDisplay) d).setSeeThrough(textDisp.isSeeThrough()); + ((TextDisplay) d).setBackgroundColor(textDisp.bgColor()); + } + if (d != null && this.displayRec != null) { + d.setBillboard(displayRec.billboard()); + d.setBrightness(displayRec.brightness()); + d.setDisplayHeight(displayRec.height()); + d.setDisplayWidth(displayRec.width()); + d.setGlowColorOverride(displayRec.glowColorOverride()); + d.setInterpolationDelay(displayRec.interpolationDelay()); + d.setInterpolationDuration(displayRec.interpolationDuration()); + d.setShadowRadius(displayRec.shadowRadius()); + d.setShadowStrength(displayRec.shadowStrength()); + d.setTeleportDuration(displayRec.teleportDuration()); + d.setTransformation(displayRec.transformation()); + d.setViewRange(displayRec.range()); + } + } + + /** + * @return the displayRec + */ + public DisplayRec getDisplayRec() { + return displayRec; + } + + /** + * @param displayRec the displayRec to set + */ + public void setDisplayRec(DisplayRec displayRec) { + this.displayRec = displayRec; + } + + /** + * @return the blockDisp + */ + public BlockData getBlockDisp() { + return blockDisp; + } + + /** + * @param blockDisp the blockDisp to set + */ + public void setBlockDisp(BlockData blockDisp) { + this.blockDisp = blockDisp; + } + + /** + * @return the itemDisp + */ + public ItemStack getItemDisp() { + return itemDisp; + } + + /** + * @param itemDisp the itemDisp to set + */ + public void setItemDisp(ItemStack itemDisp) { + this.itemDisp = itemDisp; + } + } diff --git a/src/main/java/world/bentobox/bentobox/database/json/adapters/MaterialTypeAdapter.java b/src/main/java/world/bentobox/bentobox/database/json/adapters/MaterialTypeAdapter.java index e5efa70a9..13e5d3401 100644 --- a/src/main/java/world/bentobox/bentobox/database/json/adapters/MaterialTypeAdapter.java +++ b/src/main/java/world/bentobox/bentobox/database/json/adapters/MaterialTypeAdapter.java @@ -17,7 +17,7 @@ /** * Minecraft 1.20 changed GRASS to SHORT_GRASS. This class provides and backwards compatibility when loading - * databased files stored with previous versions. It can be extended in the future if further enum changes are made. + * database files stored with previous versions. It can be extended in the future if further enum changes are made. * @author tastybento * @since 2.0.0 */ diff --git a/src/main/java/world/bentobox/bentobox/hooks/FancyHologramsHook.java b/src/main/java/world/bentobox/bentobox/hooks/FancyHologramsHook.java new file mode 100644 index 000000000..650e39133 --- /dev/null +++ b/src/main/java/world/bentobox/bentobox/hooks/FancyHologramsHook.java @@ -0,0 +1,35 @@ +package world.bentobox.bentobox.hooks; + +import org.bukkit.Material; + +import world.bentobox.bentobox.BentoBox; +import world.bentobox.bentobox.api.hooks.Hook; + +/** + * Provides copy and pasting of FancyHolograms in blueprints + * + * @author tastybento + * @since 3.2.0 + */ +public class FancyHologramsHook extends Hook { + + public FancyHologramsHook() { + super("FancyHolograms", Material.END_PORTAL); + } + + + @Override + public boolean hook() { + boolean hooked = this.isPluginAvailable(); + if (!hooked) { + BentoBox.getInstance().logError("Could not hook into FancyHolograms"); + } + return hooked; // The hook process shouldn't fail + } + + @Override + public String getFailureCause() { + return null; // The hook process shouldn't fail + } + +} diff --git a/src/main/java/world/bentobox/bentobox/util/DefaultPasteUtil.java b/src/main/java/world/bentobox/bentobox/util/DefaultPasteUtil.java index 2e6083026..2de5ae600 100644 --- a/src/main/java/world/bentobox/bentobox/util/DefaultPasteUtil.java +++ b/src/main/java/world/bentobox/bentobox/util/DefaultPasteUtil.java @@ -189,6 +189,8 @@ public static CompletableFuture setEntity(Island island, Location location * @return true if Bukkit entity spawned, false another plugin entity spawned */ static boolean spawnBlueprintEntity(BlueprintEntity k, Location location, Island island) { + // Display Entity (holograms, etc.) + k.setDisplay(location); // FancyNpc entity if (k.getNpc() != null && plugin.getHooks().getHook("FancyNpcs").filter(mmh -> mmh instanceof FancyNpcsHook).map(mmh -> { diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 9ddec656a..d314626f3 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -25,6 +25,8 @@ softdepend: - EconomyPlus - MythicMobs - ZNPCsPlus + - FancyNpcs + - FancyHolograms libraries: - mysql:mysql-connector-java:${mysql.version} From 62a4f63040b9deae520b907c34d13c1f772fe96e Mon Sep 17 00:00:00 2001 From: tastybento Date: Sat, 28 Dec 2024 09:06:28 -0800 Subject: [PATCH 2/5] Working with debug --- .../blueprints/BlueprintClipboard.java | 22 +-- .../bentobox/blueprints/DisplayListener.java | 51 +++++++ .../dataobjects/BlueprintEntity.java | 139 +++++++----------- .../bentobox/managers/BlueprintsManager.java | 3 + .../bentobox/util/DefaultPasteUtil.java | 1 + 5 files changed, 124 insertions(+), 92 deletions(-) create mode 100644 src/main/java/world/bentobox/bentobox/blueprints/DisplayListener.java diff --git a/src/main/java/world/bentobox/bentobox/blueprints/BlueprintClipboard.java b/src/main/java/world/bentobox/bentobox/blueprints/BlueprintClipboard.java index a5ae6ad1b..f590469c7 100644 --- a/src/main/java/world/bentobox/bentobox/blueprints/BlueprintClipboard.java +++ b/src/main/java/world/bentobox/bentobox/blueprints/BlueprintClipboard.java @@ -18,6 +18,7 @@ import org.bukkit.block.BlockState; import org.bukkit.block.CreatureSpawner; import org.bukkit.block.Sign; +import org.bukkit.block.data.Attachable; import org.bukkit.block.sign.Side; import org.bukkit.entity.AbstractHorse; import org.bukkit.entity.Ageable; @@ -30,7 +31,6 @@ import org.bukkit.entity.Villager; import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.ItemStack; -import org.bukkit.material.Attachable; import org.bukkit.material.Colorable; import org.bukkit.scheduler.BukkitTask; import org.bukkit.util.BoundingBox; @@ -163,9 +163,8 @@ private void copyAsync(World world, User user, List vectorsToCopy, int s List ents = world.getEntities().stream() .filter(Objects::nonNull) .filter(e -> !(e instanceof Player)) - .filter(e -> new Vector(Math.rint(e.getLocation().getX()), - Math.rint(e.getLocation().getY()), - Math.rint(e.getLocation().getZ())).equals(v)) + .filter(e -> new Vector(e.getLocation().getBlockX(), e.getLocation().getBlockY(), + e.getLocation().getBlockZ()).equals(v)) .toList(); if (copyBlock(v.toLocation(world), copyAir, copyBiome, ents)) { count++; @@ -231,7 +230,7 @@ private boolean copyBlock(Location l, boolean copyAir, boolean copyBiome, List()); @@ -285,11 +287,11 @@ private BlueprintBlock bluePrintBlock(Vector pos, Block block, boolean copyBiome } } } - + BentoBox.getInstance().logDebug("Spawner"); if (blockState instanceof CreatureSpawner spawner) { b.setCreatureSpawner(getSpawner(spawner)); } - + BentoBox.getInstance().logDebug("Banners"); // Banners if (blockState instanceof Banner banner) { b.setBannerPatterns(banner.getPatterns()); @@ -359,7 +361,7 @@ private List setEntities(List ents) { // Display entities if (entity instanceof Display disp) { - BentoBox.getInstance().logDebug(disp.getAsString()); + BentoBox.getInstance().logDebug("Storing display: " + disp.getAsString()); bpe.storeDisplay(disp); } bpEnts.add(bpe); diff --git a/src/main/java/world/bentobox/bentobox/blueprints/DisplayListener.java b/src/main/java/world/bentobox/bentobox/blueprints/DisplayListener.java new file mode 100644 index 000000000..c893e19b4 --- /dev/null +++ b/src/main/java/world/bentobox/bentobox/blueprints/DisplayListener.java @@ -0,0 +1,51 @@ +package world.bentobox.bentobox.blueprints; + +import java.util.UUID; + +import org.bukkit.NamespacedKey; +import org.bukkit.Sound; +import org.bukkit.World; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.Display; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerInteractAtEntityEvent; +import org.bukkit.persistence.PersistentDataType; + +import world.bentobox.bentobox.BentoBox; +import world.bentobox.bentobox.api.user.User; + +/** + * Provides a listener for the Display Objects pasted when a hologram is interacted with + * https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/event/player/PlayerInteractAtEntityEvent.html + */ +public class DisplayListener implements Listener { + + @EventHandler + public void onPlayerInteractEntity(PlayerInteractAtEntityEvent event) { + BentoBox.getInstance().logDebug(event.getEventName()); + if (event.getRightClicked() instanceof ArmorStand) { + ArmorStand armorStand = (ArmorStand) event.getRightClicked(); + NamespacedKey key = new NamespacedKey(BentoBox.getInstance(), "associatedDisplayEntity"); + + if (armorStand.getPersistentDataContainer().has(key, PersistentDataType.STRING)) { + String displayEntityUUID = armorStand.getPersistentDataContainer().get(key, PersistentDataType.STRING); + + // Fetch the associated DisplayEntity by UUID + World world = armorStand.getWorld(); + world.getEntitiesByClass(Display.class).stream() + .filter(e -> e.getUniqueId().equals(UUID.fromString(displayEntityUUID))).findFirst() + .ifPresent(e -> { + User user = User.getInstance(event.getPlayer()); + user.sendRawMessage("You interacted with a DisplayEntity! "); + event.getPlayer().playSound(event.getPlayer().getLocation(), Sound.BLOCK_GLASS_BREAK, 1F, + 1F); + e.remove(); + + }); + // Perform actions related to the DisplayEntity + + } + } + } +} diff --git a/src/main/java/world/bentobox/bentobox/blueprints/dataobjects/BlueprintEntity.java b/src/main/java/world/bentobox/bentobox/blueprints/dataobjects/BlueprintEntity.java index b37bc3fe5..804cb165a 100644 --- a/src/main/java/world/bentobox/bentobox/blueprints/dataobjects/BlueprintEntity.java +++ b/src/main/java/world/bentobox/bentobox/blueprints/dataobjects/BlueprintEntity.java @@ -2,14 +2,17 @@ import java.util.Map; +import org.bukkit.Bukkit; import org.bukkit.Color; import org.bukkit.DyeColor; import org.bukkit.Location; +import org.bukkit.NamespacedKey; import org.bukkit.World; import org.bukkit.block.BlockFace; import org.bukkit.block.data.BlockData; import org.bukkit.entity.AbstractHorse; import org.bukkit.entity.Ageable; +import org.bukkit.entity.ArmorStand; import org.bukkit.entity.BlockDisplay; import org.bukkit.entity.ChestedHorse; import org.bukkit.entity.Display; @@ -20,6 +23,7 @@ import org.bukkit.entity.Horse; import org.bukkit.entity.Horse.Style; import org.bukkit.entity.ItemDisplay; +import org.bukkit.entity.ItemDisplay.ItemDisplayTransform; import org.bukkit.entity.Tameable; import org.bukkit.entity.TextDisplay; import org.bukkit.entity.TextDisplay.TextAlignment; @@ -27,10 +31,16 @@ import org.bukkit.entity.Villager.Profession; import org.bukkit.inventory.ItemStack; import org.bukkit.material.Colorable; +import org.bukkit.persistence.PersistentDataType; import org.bukkit.util.Transformation; +import org.bukkit.util.Vector; import com.google.gson.annotations.Expose; +import world.bentobox.bentobox.BentoBox; +import world.bentobox.bentobox.blueprints.dataobjects.BlueprintEntity.ItemDispRec.DisplayRec; +import world.bentobox.bentobox.blueprints.dataobjects.BlueprintEntity.ItemDispRec.TextDisplayRec; + /** * @author tastybento * @since 1.5.0 @@ -81,8 +91,16 @@ public record MythicMobRecord(String type, String displayName, double level, flo private Integer experience; @Expose private Villager.Type villagerType; + // Position within the block + @Expose + private double x; + @Expose + private double y; + @Expose + private double z; /** + * Adjusts the entity according to how it was stored * @since 1.8.0 */ public void configureEntity(Entity e) { @@ -115,6 +133,11 @@ public void configureEntity(Entity e) { if (style != null && e instanceof Horse horse) { horse.setStyle(style); } + // Shift to the in-block location + Vector add = new Vector(x, y, z); + BentoBox.getInstance().logDebug("entity is at " + e.getLocation().toVector() + " and adding " + add); + e.getLocation().add(add); + BentoBox.getInstance().logDebug("entity is now at " + e.getLocation().toVector()); } /** @@ -330,42 +353,22 @@ public String getNpc() { } /** - * @param citizen the citizen to set + * @param npc the citizen to set */ - public void setNpc(String citizen) { - this.npc = citizen; - } - - @Override - public String toString() { - return "BlueprintEntity [" + (npc != null ? "npc=" + npc + ", " : "") - + (MMtype != null ? "MMtype=" + MMtype + ", " : "") - + (MMLevel != null ? "MMLevel=" + MMLevel + ", " : "") - + (MMStance != null ? "MMStance=" + MMStance + ", " : "") - + (MMpower != null ? "MMpower=" + MMpower + ", " : "") + (color != null ? "color=" + color + ", " : "") - + (type != null ? "type=" + type + ", " : "") - + (customName != null ? "customName=" + customName + ", " : "") - + (tamed != null ? "tamed=" + tamed + ", " : "") + (chest != null ? "chest=" + chest + ", " : "") - + (adult != null ? "adult=" + adult + ", " : "") - + (domestication != null ? "domestication=" + domestication + ", " : "") - + (inventory != null ? "inventory=" + inventory + ", " : "") - + (style != null ? "style=" + style + ", " : "") + (level != null ? "level=" + level + ", " : "") - + (profession != null ? "profession=" + profession + ", " : "") - + (experience != null ? "experience=" + experience + ", " : "") - + (villagerType != null ? "villagerType=" + villagerType : "") + "]"; + public void setNpc(String npc) { + this.npc = npc; } - - - @Expose public DisplayRec displayRec; @Expose public TextDisplayRec textDisp; @Expose - public BlockData blockDisp; + public BlueprintBlock blockDisp; @Expose - public ItemStack itemDisp; + public ItemDispRec itemDisp; + + public record ItemDispRec(@Expose ItemStack item, @Expose ItemDisplayTransform itemDispTrans) {} public record DisplayRec(@Expose Billboard billboard, @Expose Brightness brightness, @Expose float height, @Expose float width, @Expose Color glowColorOverride, @Expose int interpolationDelay, @@ -390,18 +393,18 @@ public void storeDisplay(Display disp) { disp.getTeleportDuration(), disp.getTransformation(), disp.getViewRange()); // Class specific items if (disp instanceof BlockDisplay bd) { - this.blockDisp = bd.getBlock(); + this.blockDisp = new BlueprintBlock(bd.getBlock().getAsString()); } else if (disp instanceof ItemDisplay id) { - itemDisp = id.getItemStack(); + itemDisp = new ItemDispRec(id.getItemStack(), id.getItemDisplayTransform()); } else if (disp instanceof TextDisplay td) { textDisp = new TextDisplayRec(td.getText(), td.getAlignment(), td.getBackgroundColor(), td.getFacing(), td.getLineWidth(), td.getTextOpacity(), td.isShadowed(), td.isSeeThrough(), td.isDefaultBackground()); } - - // , getBrightness, getDisplayHeight, getDisplayWidth, getGlowColorOverride, getInterpolationDelay, getInterpolationDuration, - //getShadowRadius, getShadowStrength, getTeleportDuration, getTransformation, getViewRange, setBillboard, setBrightness, - // setDisplayHeight, setDisplayWidth, setGlowColorOverride, setInterpolationDelay, setInterpolationDuration, setShadowRadius, setShadowStrength, setTeleportDuration, setTransformation, setTransformationMatrix, setViewRange + // Store location within block + x = disp.getLocation().getX() - disp.getLocation().getBlockX(); + y = disp.getLocation().getY() - disp.getLocation().getBlockY(); + z = disp.getLocation().getZ() - disp.getLocation().getBlockZ(); } /** @@ -410,18 +413,22 @@ public void storeDisplay(Display disp) { */ public void setDisplay(Location pos) { World world = pos.getWorld(); + Location newPos = pos.clone().add(new Vector(x - 0.5D, y, z - 0.5D)); Display d = null; if (this.blockDisp != null) { // Block Display - d = world.spawn(pos, BlockDisplay.class); - ((BlockDisplay) d).setBlock(this.blockDisp); + d = world.spawn(newPos, BlockDisplay.class); + BlockData bd = Bukkit.createBlockData(this.blockDisp.getBlockData()); + ((BlockDisplay) d).setBlock(bd); } else if (this.itemDisp != null) { // Item Display - d = world.spawn(pos, ItemDisplay.class); - ((ItemDisplay) d).setItemStack(itemDisp); + d = world.spawn(newPos, ItemDisplay.class); + ((ItemDisplay) d).setItemStack(itemDisp.item()); + ((ItemDisplay) d).setItemDisplayTransform(itemDisp.itemDispTrans()); } else if (this.textDisp != null) { - // Block Display - d = world.spawn(pos, TextDisplay.class); + BentoBox.getInstance().logDebug("Text display - " + textDisp.text()); + // Text Display + d = world.spawn(newPos, TextDisplay.class); ((TextDisplay) d).setText(textDisp.text()); ((TextDisplay) d).setAlignment(textDisp.alignment()); ((TextDisplay) d).setBackgroundColor(textDisp.bgColor()); @@ -432,6 +439,8 @@ public void setDisplay(Location pos) { ((TextDisplay) d).setBackgroundColor(textDisp.bgColor()); } if (d != null && this.displayRec != null) { + BentoBox.getInstance().logDebug("General display"); + d.setCustomName(getCustomName()); d.setBillboard(displayRec.billboard()); d.setBrightness(displayRec.brightness()); d.setDisplayHeight(displayRec.height()); @@ -445,48 +454,14 @@ public void setDisplay(Location pos) { d.setTransformation(displayRec.transformation()); d.setViewRange(displayRec.range()); } + // Spawn an armor stand here so that we have a way to detect if a player interacts with the item + ArmorStand armorStand = (ArmorStand) world.spawnEntity(newPos, EntityType.ARMOR_STAND); + armorStand.setSmall(true); // Reduces size + armorStand.setGravity(false); // Prevents falling + //armorStand.setInvisible(true); + //armorStand.setMarker(true); // No hitbox + NamespacedKey key = new NamespacedKey(BentoBox.getInstance(), "associatedDisplayEntity"); + armorStand.getPersistentDataContainer().set(key, PersistentDataType.STRING, d.getUniqueId().toString()); + BentoBox.getInstance().logDebug("display set done"); } - - /** - * @return the displayRec - */ - public DisplayRec getDisplayRec() { - return displayRec; - } - - /** - * @param displayRec the displayRec to set - */ - public void setDisplayRec(DisplayRec displayRec) { - this.displayRec = displayRec; - } - - /** - * @return the blockDisp - */ - public BlockData getBlockDisp() { - return blockDisp; - } - - /** - * @param blockDisp the blockDisp to set - */ - public void setBlockDisp(BlockData blockDisp) { - this.blockDisp = blockDisp; - } - - /** - * @return the itemDisp - */ - public ItemStack getItemDisp() { - return itemDisp; - } - - /** - * @param itemDisp the itemDisp to set - */ - public void setItemDisp(ItemStack itemDisp) { - this.itemDisp = itemDisp; - } - } diff --git a/src/main/java/world/bentobox/bentobox/managers/BlueprintsManager.java b/src/main/java/world/bentobox/bentobox/managers/BlueprintsManager.java index d13332ed5..ca6a6cef6 100644 --- a/src/main/java/world/bentobox/bentobox/managers/BlueprintsManager.java +++ b/src/main/java/world/bentobox/bentobox/managers/BlueprintsManager.java @@ -44,6 +44,7 @@ import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.blueprints.Blueprint; import world.bentobox.bentobox.blueprints.BlueprintPaster; +import world.bentobox.bentobox.blueprints.DisplayListener; import world.bentobox.bentobox.blueprints.dataobjects.BlueprintBlock; import world.bentobox.bentobox.blueprints.dataobjects.BlueprintBundle; import world.bentobox.bentobox.database.json.BentoboxTypeAdapterFactory; @@ -113,6 +114,8 @@ public BlueprintsManager(@NonNull BentoBox plugin) { gson = builder.create(); // Loaded tracker blueprintsLoaded = new HashSet<>(); + // Register Display listeners + Bukkit.getPluginManager().registerEvents(new DisplayListener(), plugin); } /** diff --git a/src/main/java/world/bentobox/bentobox/util/DefaultPasteUtil.java b/src/main/java/world/bentobox/bentobox/util/DefaultPasteUtil.java index 2de5ae600..f688cb9de 100644 --- a/src/main/java/world/bentobox/bentobox/util/DefaultPasteUtil.java +++ b/src/main/java/world/bentobox/bentobox/util/DefaultPasteUtil.java @@ -189,6 +189,7 @@ public static CompletableFuture setEntity(Island island, Location location * @return true if Bukkit entity spawned, false another plugin entity spawned */ static boolean spawnBlueprintEntity(BlueprintEntity k, Location location, Island island) { + BentoBox.getInstance().logDebug("spawn blueprint entiy " + k + " at " + location); // Display Entity (holograms, etc.) k.setDisplay(location); // FancyNpc entity From 30d3fad81f68588381163c6a83f70c49bdf6afc2 Mon Sep 17 00:00:00 2001 From: tastybento Date: Sat, 28 Dec 2024 10:16:59 -0800 Subject: [PATCH 3/5] Fix pasting of other display entities. Remove debug. --- .../blueprints/BlueprintClipboard.java | 78 +-- .../bentobox/blueprints/DisplayListener.java | 6 - .../dataobjects/BlueprintEntity.java | 601 ++++++++++++------ .../bentobox/util/DefaultPasteUtil.java | 1 - 4 files changed, 402 insertions(+), 284 deletions(-) diff --git a/src/main/java/world/bentobox/bentobox/blueprints/BlueprintClipboard.java b/src/main/java/world/bentobox/bentobox/blueprints/BlueprintClipboard.java index f590469c7..5522ea867 100644 --- a/src/main/java/world/bentobox/bentobox/blueprints/BlueprintClipboard.java +++ b/src/main/java/world/bentobox/bentobox/blueprints/BlueprintClipboard.java @@ -12,6 +12,7 @@ import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.NamespacedKey; import org.bukkit.World; import org.bukkit.block.Banner; import org.bukkit.block.Block; @@ -20,18 +21,11 @@ import org.bukkit.block.Sign; import org.bukkit.block.data.Attachable; import org.bukkit.block.sign.Side; -import org.bukkit.entity.AbstractHorse; -import org.bukkit.entity.Ageable; -import org.bukkit.entity.ChestedHorse; -import org.bukkit.entity.Display; import org.bukkit.entity.Entity; -import org.bukkit.entity.Horse; import org.bukkit.entity.Player; -import org.bukkit.entity.Tameable; -import org.bukkit.entity.Villager; import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.ItemStack; -import org.bukkit.material.Colorable; +import org.bukkit.persistence.PersistentDataType; import org.bukkit.scheduler.BukkitTask; import org.bukkit.util.BoundingBox; import org.bukkit.util.Vector; @@ -58,6 +52,10 @@ */ public class BlueprintClipboard { + /** + * Used to filter out hidden DisplayEntity armor stands when copying + */ + private static final NamespacedKey KEY = new NamespacedKey(BentoBox.getInstance(), "associatedDisplayEntity"); private @Nullable Blueprint blueprint; private @Nullable Location pos1; private @Nullable Location pos2; @@ -75,6 +73,7 @@ public class BlueprintClipboard { private Optional npc; private Optional znpc; + /** * Create a clipboard for blueprint * @param blueprint - the blueprint to load into the clipboard @@ -149,6 +148,7 @@ private void copyAsync(World world, User user, List vectorsToCopy, int s // Add all the citizens for the area in one go. This is pretty fast. bpEntities.putAll(npc.get().getNpcsInArea(world, vectorsToCopy, origin)); } + // ZNPCsPlus NPCs if (znpc.isPresent()) { bpEntities.putAll(znpc.get().getNpcsInArea(world, vectorsToCopy, origin)); } @@ -163,6 +163,7 @@ private void copyAsync(World world, User user, List vectorsToCopy, int s List ents = world.getEntities().stream() .filter(Objects::nonNull) .filter(e -> !(e instanceof Player)) + .filter(e -> !e.getPersistentDataContainer().has(KEY, PersistentDataType.STRING)) // Do not copy hidden display entities .filter(e -> new Vector(e.getLocation().getBlockX(), e.getLocation().getBlockY(), e.getLocation().getBlockZ()).equals(v)) .toList(); @@ -230,7 +231,6 @@ private boolean copyBlock(Location l, boolean copyAir, boolean copyBiome, List()); @@ -287,11 +283,9 @@ private BlueprintBlock bluePrintBlock(Vector pos, Block block, boolean copyBiome } } } - BentoBox.getInstance().logDebug("Spawner"); if (blockState instanceof CreatureSpawner spawner) { b.setCreatureSpawner(getSpawner(spawner)); } - BentoBox.getInstance().logDebug("Banners"); // Banners if (blockState instanceof Banner banner) { b.setBannerPatterns(banner.getPatterns()); @@ -320,67 +314,15 @@ private BlueprintCreatureSpawner getSpawner(CreatureSpawner spawner) { private List setEntities(List ents) { List bpEnts = new ArrayList<>(); for (Entity entity : ents) { - BlueprintEntity bpe = new BlueprintEntity(); - - bpe.setType(entity.getType()); - bpe.setCustomName(entity.getCustomName()); - if (entity instanceof Villager villager) { - setVillager(villager, bpe); - } - if (entity instanceof Colorable c && c.getColor() != null) { - bpe.setColor(c.getColor()); - } - if (entity instanceof Tameable tameable) { - bpe.setTamed(tameable.isTamed()); - } - if (entity instanceof ChestedHorse chestedHorse) { - bpe.setChest(chestedHorse.isCarryingChest()); - } - // Only set if child. Most animals are adults - if (entity instanceof Ageable ageable && !ageable.isAdult()) { - bpe.setAdult(false); - } - if (entity instanceof AbstractHorse horse) { - bpe.setDomestication(horse.getDomestication()); - bpe.setInventory(new HashMap<>()); - for (int i = 0; i < horse.getInventory().getSize(); i++) { - ItemStack item = horse.getInventory().getItem(i); - if (item != null) { - bpe.getInventory().put(i, item); - } - } - } - - if (entity instanceof Horse horse) { - bpe.setStyle(horse.getStyle()); - } - + BlueprintEntity bpe = new BlueprintEntity(entity); // Mythic mob check mmh.filter(mm -> mm.isMythicMob(entity)).map(mm -> mm.getMythicMob(entity)) .ifPresent(bpe::setMythicMobsRecord); - - // Display entities - if (entity instanceof Display disp) { - BentoBox.getInstance().logDebug("Storing display: " + disp.getAsString()); - bpe.storeDisplay(disp); - } bpEnts.add(bpe); } return bpEnts; } - /** - * Set the villager stats - * @param v - villager - * @param bpe - Blueprint Entity - */ - private void setVillager(Villager v, BlueprintEntity bpe) { - bpe.setExperience(v.getVillagerExperience()); - bpe.setLevel(v.getVillagerLevel()); - bpe.setProfession(v.getProfession()); - bpe.setVillagerType(v.getVillagerType()); - } - /** * @return the origin */ diff --git a/src/main/java/world/bentobox/bentobox/blueprints/DisplayListener.java b/src/main/java/world/bentobox/bentobox/blueprints/DisplayListener.java index c893e19b4..efa1dccf3 100644 --- a/src/main/java/world/bentobox/bentobox/blueprints/DisplayListener.java +++ b/src/main/java/world/bentobox/bentobox/blueprints/DisplayListener.java @@ -13,7 +13,6 @@ import org.bukkit.persistence.PersistentDataType; import world.bentobox.bentobox.BentoBox; -import world.bentobox.bentobox.api.user.User; /** * Provides a listener for the Display Objects pasted when a hologram is interacted with @@ -23,7 +22,6 @@ public class DisplayListener implements Listener { @EventHandler public void onPlayerInteractEntity(PlayerInteractAtEntityEvent event) { - BentoBox.getInstance().logDebug(event.getEventName()); if (event.getRightClicked() instanceof ArmorStand) { ArmorStand armorStand = (ArmorStand) event.getRightClicked(); NamespacedKey key = new NamespacedKey(BentoBox.getInstance(), "associatedDisplayEntity"); @@ -36,15 +34,11 @@ public void onPlayerInteractEntity(PlayerInteractAtEntityEvent event) { world.getEntitiesByClass(Display.class).stream() .filter(e -> e.getUniqueId().equals(UUID.fromString(displayEntityUUID))).findFirst() .ifPresent(e -> { - User user = User.getInstance(event.getPlayer()); - user.sendRawMessage("You interacted with a DisplayEntity! "); event.getPlayer().playSound(event.getPlayer().getLocation(), Sound.BLOCK_GLASS_BREAK, 1F, 1F); e.remove(); }); - // Perform actions related to the DisplayEntity - } } } diff --git a/src/main/java/world/bentobox/bentobox/blueprints/dataobjects/BlueprintEntity.java b/src/main/java/world/bentobox/bentobox/blueprints/dataobjects/BlueprintEntity.java index 804cb165a..e41ebcc9b 100644 --- a/src/main/java/world/bentobox/bentobox/blueprints/dataobjects/BlueprintEntity.java +++ b/src/main/java/world/bentobox/bentobox/blueprints/dataobjects/BlueprintEntity.java @@ -1,5 +1,6 @@ package world.bentobox.bentobox.blueprints.dataobjects; +import java.util.HashMap; import java.util.Map; import org.bukkit.Bukkit; @@ -38,8 +39,6 @@ import com.google.gson.annotations.Expose; import world.bentobox.bentobox.BentoBox; -import world.bentobox.bentobox.blueprints.dataobjects.BlueprintEntity.ItemDispRec.DisplayRec; -import world.bentobox.bentobox.blueprints.dataobjects.BlueprintEntity.ItemDispRec.TextDisplayRec; /** * @author tastybento @@ -47,48 +46,82 @@ */ public class BlueprintEntity { - // Npc storage - @Expose - private String npc; - // MythicMobs storage public record MythicMobRecord(String type, String displayName, double level, float power, String stance) { } - // GSON can serialize records, but the record class needs to be know in advance. So this breaks out the record entries - @Expose - String MMtype; - @Expose - Double MMLevel; + /** + * Item Display Entity store + * @since 3.2.0 + */ + public record ItemDispRec(@Expose ItemStack item, @Expose ItemDisplayTransform itemDispTrans) {} + + /** + * Display Entity store + * @since 3.2.0 + */ + public record DisplayRec(@Expose Billboard billboard, @Expose Brightness brightness, @Expose float height, + @Expose float width, @Expose Color glowColorOverride, @Expose int interpolationDelay, + @Expose int interpolationDuration, @Expose float shadowRadius, @Expose float shadowStrength, + @Expose int teleportDuration, @Expose Transformation transformation, @Expose float range) { + } + + /** + * TextDisplay entity store + * @since 3.2.0 + */ + public record TextDisplayRec(@Expose String text, @Expose TextAlignment alignment, @Expose Color bgColor, + @Expose BlockFace face, @Expose int lWidth, @Expose byte opacity, @Expose boolean isShadowed, + @Expose boolean isSeeThrough, @Expose boolean isDefaultBg) { + } @Expose - String MMStance; + private Boolean adult; @Expose - Float MMpower; + public BlueprintBlock blockDisp; @Expose - private DyeColor color; + private Boolean chest; @Expose - private EntityType type; + private DyeColor color; @Expose private String customName; @Expose - private Boolean tamed; - @Expose - private Boolean chest; - @Expose - private Boolean adult; + public DisplayRec displayRec; @Expose private Integer domestication; @Expose + private Integer experience; + @Expose private Map inventory; @Expose - private Style style; + public ItemDispRec itemDisp; @Expose private Integer level; @Expose + Double MMLevel; + @Expose + Float MMpower; + @Expose + String MMStance; + // GSON can serialize records, but the record class needs to be know in advance. So this breaks out the record entries + @Expose + String MMtype; + // Npc storage + @Expose + private String npc; + @Expose private Profession profession; @Expose - private Integer experience; + private Style style; + + @Expose + private Boolean tamed; + + @Expose + public TextDisplayRec textDisp; + + @Expose + private EntityType type; @Expose private Villager.Type villagerType; // Position within the block @@ -98,12 +131,104 @@ public record MythicMobRecord(String type, String displayName, double level, flo private double y; @Expose private double z; + @Expose + private boolean glowing; + @Expose + private boolean gravity; + @Expose + private boolean visualFire; + @Expose + private boolean silent; + @Expose + private boolean invulnerable; + @Expose + private int fireTicks; + + /** + * Serializes an entity to a Blueprint Entity + * @param entity entity to serialize + * @since 3.2.0 + */ + public BlueprintEntity(Entity entity) { + this.setType(entity.getType()); + this.setCustomName(entity.getCustomName()); + this.setGlowing(entity.isGlowing()); + this.setGravity(entity.hasGravity()); + this.setVisualFire(entity.isVisualFire()); + this.setSilent(entity.isSilent()); + this.setInvulnerable(entity.isInvulnerable()); + this.setFireTicks(entity.getFireTicks()); + + if (entity instanceof Villager villager) { + configVillager(villager); + } + if (entity instanceof Colorable c && c.getColor() != null) { + this.setColor(c.getColor()); + } + if (entity instanceof Tameable tameable) { + this.setTamed(tameable.isTamed()); + } + if (entity instanceof ChestedHorse chestedHorse) { + this.setChest(chestedHorse.isCarryingChest()); + } + // Only set if child. Most animals are adults + if (entity instanceof Ageable ageable && !ageable.isAdult()) { + this.setAdult(false); + } + if (entity instanceof AbstractHorse horse) { + this.setDomestication(horse.getDomestication()); + this.setInventory(new HashMap<>()); + for (int i = 0; i < horse.getInventory().getSize(); i++) { + ItemStack item = horse.getInventory().getItem(i); + if (item != null) { + this.getInventory().put(i, item); + } + } + } + + if (entity instanceof Horse horse) { + this.setStyle(horse.getStyle()); + } + + // Display entities + if (entity instanceof Display disp) { + this.storeDisplay(disp); + } + + } + + /** + * Makes a blank BlueprintEntity + */ + public BlueprintEntity() { + // Blank constructor + } + + /** + * Set the villager stats + * @param v - villager + * @param bpe - Blueprint Entity + */ + private void configVillager(Villager v) { + this.setExperience(v.getVillagerExperience()); + this.setLevel(v.getVillagerLevel()); + this.setProfession(v.getProfession()); + this.setVillagerType(v.getVillagerType()); + } /** * Adjusts the entity according to how it was stored * @since 1.8.0 */ public void configureEntity(Entity e) { + // Set the general states + e.setGlowing(glowing); + e.setGravity(gravity); + e.setVisualFire(visualFire); + e.setSilent(silent); + e.setInvulnerable(invulnerable); + e.setFireTicks(fireTicks); + if (e instanceof Villager villager) { setVillager(villager); } @@ -133,47 +258,26 @@ public void configureEntity(Entity e) { if (style != null && e instanceof Horse horse) { horse.setStyle(style); } - // Shift to the in-block location - Vector add = new Vector(x, y, z); - BentoBox.getInstance().logDebug("entity is at " + e.getLocation().toVector() + " and adding " + add); - e.getLocation().add(add); - BentoBox.getInstance().logDebug("entity is now at " + e.getLocation().toVector()); - } - - /** - * @param v - villager - * @since 1.16.0 - */ - private void setVillager(Villager v) { - v.setProfession(profession == null ? Profession.NONE : profession); - v.setVillagerExperience(experience == null ? 0 : experience); - v.setVillagerLevel(level == null ? 0 : level); - v.setVillagerType(villagerType == null ? Villager.Type.PLAINS : villagerType); - } - - /** - * @return the color - */ - public DyeColor getColor() { - return color; + // Shift to the in-block location (remove the 0.5 that the location serializer used) + e.getLocation().add(new Vector(x - 0.5D, y, z - 0.5D)); } /** - * @param color the color to set + * @return the adult */ - public void setColor(DyeColor color) { - this.color = color; + public Boolean getAdult() { + return adult; } /** - * @return the type + * @return the chest */ - public EntityType getType() { - return type; + public Boolean getChest() { + return chest; } /** - * @param type the type to set + * @return the color */ - public void setType(EntityType type) { - this.type = type; + public DyeColor getColor() { + return color; } /** * @return the customName @@ -182,117 +286,173 @@ public String getCustomName() { return customName; } /** - * @param customName the customName to set + * @return the domestication */ - public void setCustomName(String customName) { - this.customName = customName; + public Integer getDomestication() { + return domestication; } /** - * @return the tamed + * @return the experience */ - public Boolean getTamed() { - return tamed; + public Integer getExperience() { + return experience; } /** - * @param tamed the tamed to set + * @return the inventory */ - public void setTamed(Boolean tamed) { - this.tamed = tamed; + public Map getInventory() { + return inventory; } /** - * @return the chest + * @return the level */ - public Boolean getChest() { - return chest; + public Integer getLevel() { + return level; } /** - * @param chest the chest to set + * @return the mythicMobsRecord */ - public void setChest(Boolean chest) { - this.chest = chest; + public MythicMobRecord getMythicMobsRecord() { + if (this.MMtype == null || this.MMLevel == null || this.MMpower == null || this.MMStance == null) { + return null; + } + return new MythicMobRecord(this.MMtype, this.getCustomName(), this.MMLevel, this.MMpower, this.MMStance); } /** - * @return the adult + * @return the npc */ - public Boolean getAdult() { - return adult; + public String getNpc() { + return npc; } /** - * @param adult the adult to set + * @return the profession */ - public void setAdult(Boolean adult) { - this.adult = adult; + public Profession getProfession() { + return profession; } /** - * @return the domestication + * @return the style */ - public Integer getDomestication() { - return domestication; + public Style getStyle() { + return style; } + /** - * @param domestication the domestication to set + * @return the tamed */ - public void setDomestication(int domestication) { - this.domestication = domestication; + public Boolean getTamed() { + return tamed; } + /** - * @return the inventory + * @return the type */ - public Map getInventory() { - return inventory; + public EntityType getType() { + return type; } + /** - * @param inventory the inventory to set + * @return the villagerType */ - public void setInventory(Map inventory) { - this.inventory = inventory; + public Villager.Type getVillagerType() { + return villagerType; } + /** - * @return the style + * @param adult the adult to set */ - public Style getStyle() { - return style; + public void setAdult(Boolean adult) { + this.adult = adult; } + /** - * @param style the style to set + * @param chest the chest to set */ - public void setStyle(Style style) { - this.style = style; + public void setChest(Boolean chest) { + this.chest = chest; } /** - * @return the level + * @param color the color to set */ - public Integer getLevel() { - return level; + public void setColor(DyeColor color) { + this.color = color; } /** - * @param level the level to set + * @param customName the customName to set */ - public void setLevel(Integer level) { - this.level = level; + public void setCustomName(String customName) { + this.customName = customName; } /** - * @return the profession + * Sets any display entity properties to the location, e.g. holograms + * @param pos location */ - public Profession getProfession() { - return profession; + public void setDisplay(Location pos) { + World world = pos.getWorld(); + Location newPos = pos.clone().add(new Vector(x - 0.5D, y, z - 0.5D)); + Display d = null; + if (this.blockDisp != null) { + // Block Display + d = world.spawn(newPos, BlockDisplay.class); + BlockData bd = Bukkit.createBlockData(this.blockDisp.getBlockData()); + ((BlockDisplay) d).setBlock(bd); + } else if (this.itemDisp != null) { + // Item Display + d = world.spawn(newPos, ItemDisplay.class); + ((ItemDisplay) d).setItemStack(itemDisp.item()); + ((ItemDisplay) d).setItemDisplayTransform(itemDisp.itemDispTrans()); + } else if (this.textDisp != null) { + // Text Display + d = world.spawn(newPos, TextDisplay.class); + ((TextDisplay) d).setText(textDisp.text()); + ((TextDisplay) d).setAlignment(textDisp.alignment()); + ((TextDisplay) d).setBackgroundColor(textDisp.bgColor()); + ((TextDisplay) d).setLineWidth(textDisp.lWidth()); + ((TextDisplay) d).setTextOpacity(textDisp.opacity()); + ((TextDisplay) d).setShadowed(textDisp.isShadowed()); + ((TextDisplay) d).setSeeThrough(textDisp.isSeeThrough()); + ((TextDisplay) d).setBackgroundColor(textDisp.bgColor()); + } + if (d != null && this.displayRec != null) { + d.setCustomName(getCustomName()); + d.setBillboard(displayRec.billboard()); + d.setBrightness(displayRec.brightness()); + d.setDisplayHeight(displayRec.height()); + d.setDisplayWidth(displayRec.width()); + d.setGlowColorOverride(displayRec.glowColorOverride()); + d.setInterpolationDelay(displayRec.interpolationDelay()); + d.setInterpolationDuration(displayRec.interpolationDuration()); + d.setShadowRadius(displayRec.shadowRadius()); + d.setShadowStrength(displayRec.shadowStrength()); + d.setTeleportDuration(displayRec.teleportDuration()); + d.setTransformation(displayRec.transformation()); + d.setViewRange(displayRec.range()); + + // Spawn an armor stand here so that we have a way to detect if a player interacts with the item + ArmorStand armorStand = (ArmorStand) world.spawnEntity(newPos, EntityType.ARMOR_STAND); + armorStand.setSmall(true); // Reduces size + armorStand.setGravity(false); // Prevents falling + armorStand.setInvisible(true); + NamespacedKey key = new NamespacedKey(BentoBox.getInstance(), "associatedDisplayEntity"); + armorStand.getPersistentDataContainer().set(key, PersistentDataType.STRING, d.getUniqueId().toString()); + } } /** - * @param profession the profession to set + * @param domestication the domestication to set */ - public void setProfession(Profession profession) { - this.profession = profession; + public void setDomestication(int domestication) { + this.domestication = domestication; } /** - * @return the experience + * @param domestication the domestication to set */ - public Integer getExperience() { - return experience; + public void setDomestication(Integer domestication) { + this.domestication = domestication; } /** @@ -303,34 +463,17 @@ public void setExperience(Integer experience) { } /** - * @return the villagerType - */ - public Villager.Type getVillagerType() { - return villagerType; - } - - /** - * @param villagerType the villagerType to set - */ - public void setVillagerType(Villager.Type villagerType) { - this.villagerType = villagerType; - } - - /** - * @param domestication the domestication to set + * @param inventory the inventory to set */ - public void setDomestication(Integer domestication) { - this.domestication = domestication; + public void setInventory(Map inventory) { + this.inventory = inventory; } /** - * @return the mythicMobsRecord + * @param level the level to set */ - public MythicMobRecord getMythicMobsRecord() { - if (this.MMtype == null || this.MMLevel == null || this.MMpower == null || this.MMStance == null) { - return null; - } - return new MythicMobRecord(this.MMtype, this.getCustomName(), this.MMLevel, this.MMpower, this.MMStance); + public void setLevel(Integer level) { + this.level = level; } /** @@ -344,41 +487,55 @@ public void setMythicMobsRecord(MythicMobRecord mmr) { this.MMStance = mmr.stance(); this.MMpower = mmr.power(); } - /** - * @return the npc + * @param npc the citizen to set */ - public String getNpc() { - return npc; + public void setNpc(String npc) { + this.npc = npc; + } + /** + * @param profession the profession to set + */ + public void setProfession(Profession profession) { + this.profession = profession; + } + /** + * @param style the style to set + */ + public void setStyle(Style style) { + this.style = style; } /** - * @param npc the citizen to set + * @param tamed the tamed to set */ - public void setNpc(String npc) { - this.npc = npc; + public void setTamed(Boolean tamed) { + this.tamed = tamed; } - @Expose - public DisplayRec displayRec; - @Expose - public TextDisplayRec textDisp; - @Expose - public BlueprintBlock blockDisp; - @Expose - public ItemDispRec itemDisp; - - public record ItemDispRec(@Expose ItemStack item, @Expose ItemDisplayTransform itemDispTrans) {} + /** + * @param type the type to set + */ + public void setType(EntityType type) { + this.type = type; + } - public record DisplayRec(@Expose Billboard billboard, @Expose Brightness brightness, @Expose float height, - @Expose float width, @Expose Color glowColorOverride, @Expose int interpolationDelay, - @Expose int interpolationDuration, @Expose float shadowRadius, @Expose float shadowStrength, - @Expose int teleportDuration, @Expose Transformation transformation, @Expose float range) { + /** + * @param v - villager + * @since 1.16.0 + */ + private void setVillager(Villager v) { + v.setProfession(profession == null ? Profession.NONE : profession); + v.setVillagerExperience(experience == null ? 0 : experience); + v.setVillagerLevel(level == null ? 0 : level); + v.setVillagerType(villagerType == null ? Villager.Type.PLAINS : villagerType); } - public record TextDisplayRec(@Expose String text, @Expose TextAlignment alignment, @Expose Color bgColor, - @Expose BlockFace face, @Expose int lWidth, @Expose byte opacity, @Expose boolean isShadowed, - @Expose boolean isSeeThrough, @Expose boolean isDefaultBg) { + /** + * @param villagerType the villagerType to set + */ + public void setVillagerType(Villager.Type villagerType) { + this.villagerType = villagerType; } /** @@ -408,60 +565,86 @@ public void storeDisplay(Display disp) { } /** - * Sets any display entity properties to the location, e.g. holograms - * @param pos location + * @return the glowing */ - public void setDisplay(Location pos) { - World world = pos.getWorld(); - Location newPos = pos.clone().add(new Vector(x - 0.5D, y, z - 0.5D)); - Display d = null; - if (this.blockDisp != null) { - // Block Display - d = world.spawn(newPos, BlockDisplay.class); - BlockData bd = Bukkit.createBlockData(this.blockDisp.getBlockData()); - ((BlockDisplay) d).setBlock(bd); - } else if (this.itemDisp != null) { - // Item Display - d = world.spawn(newPos, ItemDisplay.class); - ((ItemDisplay) d).setItemStack(itemDisp.item()); - ((ItemDisplay) d).setItemDisplayTransform(itemDisp.itemDispTrans()); - } else if (this.textDisp != null) { - BentoBox.getInstance().logDebug("Text display - " + textDisp.text()); - // Text Display - d = world.spawn(newPos, TextDisplay.class); - ((TextDisplay) d).setText(textDisp.text()); - ((TextDisplay) d).setAlignment(textDisp.alignment()); - ((TextDisplay) d).setBackgroundColor(textDisp.bgColor()); - ((TextDisplay) d).setLineWidth(textDisp.lWidth()); - ((TextDisplay) d).setTextOpacity(textDisp.opacity()); - ((TextDisplay) d).setShadowed(textDisp.isShadowed()); - ((TextDisplay) d).setSeeThrough(textDisp.isSeeThrough()); - ((TextDisplay) d).setBackgroundColor(textDisp.bgColor()); - } - if (d != null && this.displayRec != null) { - BentoBox.getInstance().logDebug("General display"); - d.setCustomName(getCustomName()); - d.setBillboard(displayRec.billboard()); - d.setBrightness(displayRec.brightness()); - d.setDisplayHeight(displayRec.height()); - d.setDisplayWidth(displayRec.width()); - d.setGlowColorOverride(displayRec.glowColorOverride()); - d.setInterpolationDelay(displayRec.interpolationDelay()); - d.setInterpolationDuration(displayRec.interpolationDuration()); - d.setShadowRadius(displayRec.shadowRadius()); - d.setShadowStrength(displayRec.shadowStrength()); - d.setTeleportDuration(displayRec.teleportDuration()); - d.setTransformation(displayRec.transformation()); - d.setViewRange(displayRec.range()); - } - // Spawn an armor stand here so that we have a way to detect if a player interacts with the item - ArmorStand armorStand = (ArmorStand) world.spawnEntity(newPos, EntityType.ARMOR_STAND); - armorStand.setSmall(true); // Reduces size - armorStand.setGravity(false); // Prevents falling - //armorStand.setInvisible(true); - //armorStand.setMarker(true); // No hitbox - NamespacedKey key = new NamespacedKey(BentoBox.getInstance(), "associatedDisplayEntity"); - armorStand.getPersistentDataContainer().set(key, PersistentDataType.STRING, d.getUniqueId().toString()); - BentoBox.getInstance().logDebug("display set done"); + public boolean isGlowing() { + return glowing; + } + + /** + * @param glowing the glowing to set + */ + public void setGlowing(boolean glowing) { + this.glowing = glowing; + } + + /** + * @return the gravity + */ + public boolean isGravity() { + return gravity; + } + + /** + * @param gravity the gravity to set + */ + public void setGravity(boolean gravity) { + this.gravity = gravity; + } + + /** + * @return the visualFire + */ + public boolean isVisualFire() { + return visualFire; + } + + /** + * @param visualFire the visualFire to set + */ + public void setVisualFire(boolean visualFire) { + this.visualFire = visualFire; + } + + /** + * @return the silent + */ + public boolean isSilent() { + return silent; + } + + /** + * @param silent the silent to set + */ + public void setSilent(boolean silent) { + this.silent = silent; + } + + /** + * @return the invulnerable + */ + public boolean isInvulnerable() { + return invulnerable; + } + + /** + * @param invulnerable the invulnerable to set + */ + public void setInvulnerable(boolean invulnerable) { + this.invulnerable = invulnerable; + } + + /** + * @return the fireTicks + */ + public int getFireTicks() { + return fireTicks; + } + + /** + * @param fireTicks the fireTicks to set + */ + public void setFireTicks(int fireTicks) { + this.fireTicks = fireTicks; } } diff --git a/src/main/java/world/bentobox/bentobox/util/DefaultPasteUtil.java b/src/main/java/world/bentobox/bentobox/util/DefaultPasteUtil.java index f688cb9de..2de5ae600 100644 --- a/src/main/java/world/bentobox/bentobox/util/DefaultPasteUtil.java +++ b/src/main/java/world/bentobox/bentobox/util/DefaultPasteUtil.java @@ -189,7 +189,6 @@ public static CompletableFuture setEntity(Island island, Location location * @return true if Bukkit entity spawned, false another plugin entity spawned */ static boolean spawnBlueprintEntity(BlueprintEntity k, Location location, Island island) { - BentoBox.getInstance().logDebug("spawn blueprint entiy " + k + " at " + location); // Display Entity (holograms, etc.) k.setDisplay(location); // FancyNpc entity From df814cce0f67587330990c84226241b3321fb1d2 Mon Sep 17 00:00:00 2001 From: tastybento Date: Sat, 28 Dec 2024 14:21:49 -0800 Subject: [PATCH 4/5] Fixed tests --- .../bentobox/bentobox/api/hooks/NPCHook.java | 41 +++++++++++++++++++ .../bentobox/hooks/FancyNpcsHook.java | 29 +++++++++++-- .../bentobox/hooks/ZNPCsPlusHook.java | 34 +++++++++++++-- .../bentobox/nms/CopyWorldRegenerator.java | 34 ++++++++++++--- .../AdminBlueprintCopyCommandTest.java | 10 +++-- .../AdminBlueprintLoadCommandTest.java | 2 + .../AdminBlueprintSaveCommandTest.java | 6 ++- .../blueprints/BlueprintClipboardTest.java | 2 + .../BlueprintClipboardManagerTest.java | 12 ++++-- 9 files changed, 150 insertions(+), 20 deletions(-) create mode 100644 src/main/java/world/bentobox/bentobox/api/hooks/NPCHook.java diff --git a/src/main/java/world/bentobox/bentobox/api/hooks/NPCHook.java b/src/main/java/world/bentobox/bentobox/api/hooks/NPCHook.java new file mode 100644 index 000000000..6a848215f --- /dev/null +++ b/src/main/java/world/bentobox/bentobox/api/hooks/NPCHook.java @@ -0,0 +1,41 @@ +package world.bentobox.bentobox.api.hooks; + +import java.util.List; +import java.util.Map; + +import org.bukkit.Chunk; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.configuration.InvalidConfigurationException; +import org.bukkit.util.Vector; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; + +import de.oliver.fancynpcs.api.Npc; +import lol.pyr.znpcsplus.api.npc.NpcEntry; +import world.bentobox.bentobox.blueprints.dataobjects.BlueprintEntity; + +/** + * NPC Hooks + * @author tastybento + * @since 3.2.0 + */ +public abstract class NPCHook extends Hook { + + protected NPCHook(@NonNull String pluginName, @NonNull Material icon) { + super(pluginName, icon); + } + + public abstract boolean spawnNpc(String yaml, Location pos) throws InvalidConfigurationException; + + public abstract Map> getNpcsInArea(World world, + List vectorsToCopy, @Nullable Vector origin); + + /** + * Remove all NPCs in chunk + * @param chunk chunk + */ + public abstract void removeNPCsInChunk(Chunk chunk); + +} diff --git a/src/main/java/world/bentobox/bentobox/hooks/FancyNpcsHook.java b/src/main/java/world/bentobox/bentobox/hooks/FancyNpcsHook.java index acc5ba7d8..c8c375f12 100644 --- a/src/main/java/world/bentobox/bentobox/hooks/FancyNpcsHook.java +++ b/src/main/java/world/bentobox/bentobox/hooks/FancyNpcsHook.java @@ -10,6 +10,7 @@ import java.util.concurrent.ConcurrentHashMap; import org.bukkit.Bukkit; +import org.bukkit.Chunk; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.World; @@ -29,9 +30,10 @@ import de.oliver.fancynpcs.api.actions.NpcAction; import de.oliver.fancynpcs.api.utils.NpcEquipmentSlot; import de.oliver.fancynpcs.api.utils.SkinFetcher; +import lol.pyr.znpcsplus.api.npc.NpcEntry; import net.kyori.adventure.text.format.NamedTextColor; import world.bentobox.bentobox.BentoBox; -import world.bentobox.bentobox.api.hooks.Hook; +import world.bentobox.bentobox.api.hooks.NPCHook; import world.bentobox.bentobox.blueprints.dataobjects.BlueprintEntity; /** @@ -40,13 +42,13 @@ * @author tastybento * @since 3.1.0 */ -public class FancyNpcsHook extends Hook { +public class FancyNpcsHook extends NPCHook { public FancyNpcsHook() { super("FancyNpcs", Material.PLAYER_HEAD); } - public String serializeNPC(Npc npc, Vector origin) { + String serializeNPC(Npc npc, Vector origin) { if (npc == null) { throw new IllegalArgumentException("NPC cannot be null."); } @@ -265,6 +267,26 @@ public String getFailureCause() { return null; // The hook process shouldn't fail } + /** + * Return all NPCs in the chunk + * @param chunk chunk + * @return list of NPCs + */ + public List getNPCsInChunk(Chunk chunk) { + return FancyNpcsPlugin.get().getNpcManager().getAllNpcs().stream() + .filter(npc -> npc.getData().getLocation().getChunk().equals(chunk)).toList(); + } + + /** + * Remove all NPCs in chunk + * @param chunk chunk + */ + @Override + public void removeNPCsInChunk(Chunk chunk) { + getNPCsInChunk(chunk).forEach(npc -> npc.removeForAll()); + } + + @Override public Map> getNpcsInArea(World world, List vectorsToCopy, @Nullable Vector origin) { Map> bpEntities = new HashMap<>(); @@ -290,4 +312,5 @@ public String getFailureCause() { } return bpEntities; } + } diff --git a/src/main/java/world/bentobox/bentobox/hooks/ZNPCsPlusHook.java b/src/main/java/world/bentobox/bentobox/hooks/ZNPCsPlusHook.java index d9a31dfef..9a538d7a5 100644 --- a/src/main/java/world/bentobox/bentobox/hooks/ZNPCsPlusHook.java +++ b/src/main/java/world/bentobox/bentobox/hooks/ZNPCsPlusHook.java @@ -5,6 +5,7 @@ import java.util.List; import java.util.Map; +import org.bukkit.Chunk; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.World; @@ -17,7 +18,7 @@ import lol.pyr.znpcsplus.api.npc.NpcEntry; import lol.pyr.znpcsplus.util.NpcLocation; import world.bentobox.bentobox.BentoBox; -import world.bentobox.bentobox.api.hooks.Hook; +import world.bentobox.bentobox.api.hooks.NPCHook; import world.bentobox.bentobox.blueprints.dataobjects.BlueprintEntity; import world.bentobox.bentobox.util.Util; @@ -27,7 +28,7 @@ * @author tastybento * @since 3.2.0 */ -public class ZNPCsPlusHook extends Hook { +public class ZNPCsPlusHook extends NPCHook { private static final String VERSION = "2.0.0-SNAPSHOT"; // Minimum version required @@ -35,13 +36,20 @@ public ZNPCsPlusHook() { super("ZNPCsPlus", Material.PLAYER_HEAD); } - public String serializeNPC(NpcEntry entry, Vector origin) { + /** + * Serialize a NpcEntry + * @param entry NPC entry + * @param origin origin point of blueprint + * @return string serializing the NPC Entry + */ + String serializeNPC(NpcEntry entry, Vector origin) { String result = NpcApiProvider.get().getNpcSerializerRegistry().getSerializer(YamlConfiguration.class) .serialize(entry) .saveToString(); return result; } + @Override public boolean spawnNpc(String yaml, Location pos) throws InvalidConfigurationException { YamlConfiguration yaml2 = new YamlConfiguration(); yaml2.loadFromString(yaml); @@ -75,6 +83,7 @@ public String getFailureCause() { + this.getPlugin().getDescription().getVersion(); } + @Override public Map> getNpcsInArea(World world, List vectorsToCopy, @Nullable Vector origin) { Map> bpEntities = new HashMap<>(); @@ -101,4 +110,23 @@ public String getFailureCause() { } return bpEntities; } + + /** + * Get a list of all the NPC IDs in this chunk + * @param chunk chunk + * @return list of NPC IDs + */ + public List getNPCsInChunk(Chunk chunk) { + return NpcApiProvider.get().getNpcRegistry().getAll().stream() + .filter(npc -> npc.getNpc().getWorld().equals(chunk.getWorld())) // Only NPCs in this world + .filter(npc -> npc.getNpc().getLocation().toBukkitLocation(chunk.getWorld()).getChunk().equals(chunk)) // Only in this chunk + .map(npc -> npc.getId()) // IDs + .toList(); + } + + @Override + public void removeNPCsInChunk(Chunk chunk) { + getNPCsInChunk(chunk).forEach(NpcApiProvider.get().getNpcRegistry()::delete); + } + } diff --git a/src/main/java/world/bentobox/bentobox/nms/CopyWorldRegenerator.java b/src/main/java/world/bentobox/bentobox/nms/CopyWorldRegenerator.java index c3ac17183..4be154439 100644 --- a/src/main/java/world/bentobox/bentobox/nms/CopyWorldRegenerator.java +++ b/src/main/java/world/bentobox/bentobox/nms/CopyWorldRegenerator.java @@ -43,8 +43,10 @@ import world.bentobox.bentobox.api.addons.GameModeAddon; import world.bentobox.bentobox.api.hooks.Hook; import world.bentobox.bentobox.database.objects.IslandDeletion; +import world.bentobox.bentobox.hooks.FancyNpcsHook; import world.bentobox.bentobox.hooks.ItemsAdderHook; import world.bentobox.bentobox.hooks.SlimefunHook; +import world.bentobox.bentobox.hooks.ZNPCsPlusHook; import world.bentobox.bentobox.util.MyBiomeGrid; /** @@ -56,9 +58,18 @@ public abstract class CopyWorldRegenerator implements WorldRegenerator { private final BentoBox plugin; + private Optional npc; + private Optional znpc; protected CopyWorldRegenerator() { this.plugin = BentoBox.getInstance(); + // Fancy NPCs Hook + npc = plugin.getHooks().getHook("FancyNpcs").filter(FancyNpcsHook.class::isInstance) + .map(FancyNpcsHook.class::cast); + // ZNPCs Plus Hook + znpc = plugin.getHooks().getHook("ZNPCsPlus").filter(ZNPCsPlusHook.class::isInstance) + .map(ZNPCsPlusHook.class::cast); + } /** @@ -179,11 +190,20 @@ private CompletableFuture cleanChunk(CompletableFuture chunkFuture, ); // Similarly, when the chunk is loaded, remove all the entities in the chunk apart from players - CompletableFuture entitiesFuture = chunkFuture.thenAccept(chunk -> - // Remove all entities in chunk, including any dropped items as a result of clearing the blocks above - Arrays.stream(chunk.getEntities()) - .filter(e -> !(e instanceof Player) && di.inBounds(e.getLocation().getBlockX(), e.getLocation().getBlockZ())) - .forEach(Entity::remove)); + CompletableFuture entitiesFuture = chunkFuture.thenAccept(chunk -> { + // Remove all entities in chunk, including any dropped items as a result of clearing the blocks above + Arrays.stream(chunk.getEntities()) + .filter(e -> !(e instanceof Player) + && di.inBounds(e.getLocation().getBlockX(), e.getLocation().getBlockZ())) + .forEach(Entity::remove); + // Remove any NPCs + // Fancy NPCs Hook + npc.ifPresent(hook -> hook.removeNPCsInChunk(chunk)); + // ZNPCs Plus Hook + znpc.ifPresent(hook -> hook.removeNPCsInChunk(chunk)); + + }); + return CompletableFuture.allOf(invFuture, entitiesFuture); } @@ -310,6 +330,10 @@ private void writeSign(Sign fromSign, Sign toSign, Side side) { public CompletableFuture regenerateSimple(GameModeAddon gm, IslandDeletion di, World world) { CompletableFuture bigFuture = new CompletableFuture<>(); + if (world == null) { + bigFuture.complete(null); + return bigFuture; + } new BukkitRunnable() { private int chunkX = di.getMinXChunk(); private int chunkZ = di.getMinZChunk(); diff --git a/src/test/java/world/bentobox/bentobox/api/commands/admin/blueprints/AdminBlueprintCopyCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/admin/blueprints/AdminBlueprintCopyCommandTest.java index cdcbe9bea..af3d086cd 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/admin/blueprints/AdminBlueprintCopyCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/admin/blueprints/AdminBlueprintCopyCommandTest.java @@ -47,13 +47,15 @@ @PrepareForTest({Bukkit.class, BentoBox.class, User.class }) public class AdminBlueprintCopyCommandTest { + @Mock + private BentoBox plugin; @Mock private AdminBlueprintCommand ac; @Mock private GameModeAddon addon; @Mock private User user; - @Mock + private BlueprintClipboard clip; private UUID uuid = UUID.randomUUID(); @Mock @@ -64,10 +66,12 @@ public class AdminBlueprintCopyCommandTest { */ @Before public void setUp() throws Exception { - // Set up plugin - BentoBox plugin = mock(BentoBox.class); + // Set up plugin // Set up plugin + // Required for NamespacedKey + when(plugin.getName()).thenReturn("BentoBox"); Whitebox.setInternalState(BentoBox.class, "instance", plugin); + clip = mock(BlueprintClipboard.class); // Blueprints Manager when(plugin.getBlueprintsManager()).thenReturn(bm); diff --git a/src/test/java/world/bentobox/bentobox/api/commands/admin/blueprints/AdminBlueprintLoadCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/admin/blueprints/AdminBlueprintLoadCommandTest.java index 284028a36..64c5963bc 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/admin/blueprints/AdminBlueprintLoadCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/admin/blueprints/AdminBlueprintLoadCommandTest.java @@ -76,6 +76,8 @@ public static void beforeClass() { @Before public void setUp() throws Exception { + // Required for NamespacedKey + when(plugin.getName()).thenReturn("BentoBox"); // Set up plugin Whitebox.setInternalState(BentoBox.class, "instance", plugin); diff --git a/src/test/java/world/bentobox/bentobox/api/commands/admin/blueprints/AdminBlueprintSaveCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/admin/blueprints/AdminBlueprintSaveCommandTest.java index ac5386a6c..a8d382fc4 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/admin/blueprints/AdminBlueprintSaveCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/admin/blueprints/AdminBlueprintSaveCommandTest.java @@ -55,6 +55,8 @@ @PrepareForTest({Bukkit.class, BentoBox.class, User.class }) public class AdminBlueprintSaveCommandTest { + @Mock + private BentoBox plugin; private AdminBlueprintSaveCommand absc; @Mock private AdminBlueprintCommand ac; @@ -76,8 +78,8 @@ public static void beforeClass() { @Before public void setUp() throws Exception { - // Set up plugin - BentoBox plugin = mock(BentoBox.class); + // Required for NamespacedKey + when(plugin.getName()).thenReturn("BentoBox"); Whitebox.setInternalState(BentoBox.class, "instance", plugin); // Hooks HooksManager hooksManager = mock(HooksManager.class); diff --git a/src/test/java/world/bentobox/bentobox/blueprints/BlueprintClipboardTest.java b/src/test/java/world/bentobox/bentobox/blueprints/BlueprintClipboardTest.java index 861b0f8be..b951aa4e8 100644 --- a/src/test/java/world/bentobox/bentobox/blueprints/BlueprintClipboardTest.java +++ b/src/test/java/world/bentobox/bentobox/blueprints/BlueprintClipboardTest.java @@ -58,6 +58,8 @@ public class BlueprintClipboardTest { */ @Before public void setUp() throws Exception { + // Required for NamespacedKey + when(plugin.getName()).thenReturn("BentoBox"); // Set up plugin Whitebox.setInternalState(BentoBox.class, "instance", plugin); // Hooks diff --git a/src/test/java/world/bentobox/bentobox/managers/BlueprintClipboardManagerTest.java b/src/test/java/world/bentobox/bentobox/managers/BlueprintClipboardManagerTest.java index d6e4fc354..390257852 100644 --- a/src/test/java/world/bentobox/bentobox/managers/BlueprintClipboardManagerTest.java +++ b/src/test/java/world/bentobox/bentobox/managers/BlueprintClipboardManagerTest.java @@ -57,7 +57,7 @@ public class BlueprintClipboardManagerTest { @Mock private BentoBox plugin; - @Mock + private BlueprintClipboard clipboard; private File blueprintFolder; @@ -129,15 +129,19 @@ private void zip(File targetFile) throws IOException { */ @Before public void setUp() throws Exception { + // Set up plugin + // Required for NamespacedKey + when(plugin.getName()).thenReturn("BentoBox"); + Whitebox.setInternalState(BentoBox.class, "instance", plugin); + + clipboard = mock(BlueprintClipboard.class); + server = ServerMocks.newServer(); PowerMockito.mockStatic(Bukkit.class, Mockito.RETURNS_MOCKS); blueprintFolder = new File("blueprints"); // Clear any residual files tearDown(); - // Set up plugin - BentoBox plugin = mock(BentoBox.class); - Whitebox.setInternalState(BentoBox.class, "instance", plugin); // Hooks HooksManager hooksManager = mock(HooksManager.class); when(hooksManager.getHook(anyString())).thenReturn(Optional.empty()); From f4060254962c459d246ff4d1b2499d4ad70f352c Mon Sep 17 00:00:00 2001 From: tastybento Date: Sat, 28 Dec 2024 15:03:38 -0800 Subject: [PATCH 5/5] Remove this for now --- .../bentobox/hooks/FancyHologramsHook.java | 35 ------------------- 1 file changed, 35 deletions(-) delete mode 100644 src/main/java/world/bentobox/bentobox/hooks/FancyHologramsHook.java diff --git a/src/main/java/world/bentobox/bentobox/hooks/FancyHologramsHook.java b/src/main/java/world/bentobox/bentobox/hooks/FancyHologramsHook.java deleted file mode 100644 index 650e39133..000000000 --- a/src/main/java/world/bentobox/bentobox/hooks/FancyHologramsHook.java +++ /dev/null @@ -1,35 +0,0 @@ -package world.bentobox.bentobox.hooks; - -import org.bukkit.Material; - -import world.bentobox.bentobox.BentoBox; -import world.bentobox.bentobox.api.hooks.Hook; - -/** - * Provides copy and pasting of FancyHolograms in blueprints - * - * @author tastybento - * @since 3.2.0 - */ -public class FancyHologramsHook extends Hook { - - public FancyHologramsHook() { - super("FancyHolograms", Material.END_PORTAL); - } - - - @Override - public boolean hook() { - boolean hooked = this.isPluginAvailable(); - if (!hooked) { - BentoBox.getInstance().logError("Could not hook into FancyHolograms"); - } - return hooked; // The hook process shouldn't fail - } - - @Override - public String getFailureCause() { - return null; // The hook process shouldn't fail - } - -}