From 7b3273174cff7373a30172ffb9b2da32f814c293 Mon Sep 17 00:00:00 2001 From: Oak Date: Fri, 21 Jun 2024 11:10:02 +0100 Subject: [PATCH] Generalised entities within holograms and added 'dropped_item' hologram type --- .../api/data/DroppedItemHologramData.java | 58 ++++++++++++ .../fancyholograms/api/hologram/Hologram.java | 7 +- .../api/hologram/HologramType.java | 3 +- .../hologram/version/Hologram1_19_4.java | 84 +++++++++-------- .../hologram/version/Hologram1_20_1.java | 84 +++++++++-------- .../hologram/version/Hologram1_20_2.java | 81 +++++++++-------- .../hologram/version/Hologram1_20_4.java | 81 +++++++++-------- .../hologram/version/Hologram1_20_6.java | 82 +++++++++-------- .../hologram/version/Hologram1_21.java | 89 ++++++++++--------- .../fancyholograms/commands/HologramCMD.java | 2 +- .../commands/hologram/CreateCMD.java | 19 ++-- .../commands/hologram/ItemCMD.java | 65 +++++++++----- .../storage/FlatFileHologramStorage.java | 19 ++-- 13 files changed, 397 insertions(+), 277 deletions(-) create mode 100644 api/src/main/java/de/oliver/fancyholograms/api/data/DroppedItemHologramData.java diff --git a/api/src/main/java/de/oliver/fancyholograms/api/data/DroppedItemHologramData.java b/api/src/main/java/de/oliver/fancyholograms/api/data/DroppedItemHologramData.java new file mode 100644 index 00000000..36554918 --- /dev/null +++ b/api/src/main/java/de/oliver/fancyholograms/api/data/DroppedItemHologramData.java @@ -0,0 +1,58 @@ +package de.oliver.fancyholograms.api.data; + +import de.oliver.fancyholograms.api.hologram.HologramType; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.inventory.ItemStack; + +public class DroppedItemHologramData extends HologramData { + + public static final ItemStack DEFAULT_ITEM = new ItemStack(Material.APPLE); + + private ItemStack item = DEFAULT_ITEM; + + /** + * @param name Name of hologram + * @param location Location of hologram + * Default values are already set + */ + public DroppedItemHologramData(String name, Location location) { + super(name, HologramType.DROPPED_ITEM, location); + } + + public ItemStack getItemStack() { + return item; + } + + public DroppedItemHologramData setItemStack(ItemStack item) { + this.item = item; + setHasChanges(true); + return this; + } + + @Override + public void read(ConfigurationSection section, String name) { + super.read(section, name); + item = section.getItemStack("item", DEFAULT_ITEM); + } + + @Override + public void write(ConfigurationSection section, String name) { + super.write(section, name); + section.set("item", item); + } + + @Override + public DroppedItemHologramData copy(String name) { + DroppedItemHologramData droppedItemHologramData = new DroppedItemHologramData(name, getLocation()); + droppedItemHologramData + .setItemStack(this.getItemStack()) + .setVisibilityDistance(this.getVisibilityDistance()) + .setVisibility(this.getVisibility()) + .setPersistent(this.isPersistent()) + .setLinkedNpcName(this.getLinkedNpcName()); + + return droppedItemHologramData; + } +} diff --git a/api/src/main/java/de/oliver/fancyholograms/api/hologram/Hologram.java b/api/src/main/java/de/oliver/fancyholograms/api/hologram/Hologram.java index 666d36d2..85948362 100644 --- a/api/src/main/java/de/oliver/fancyholograms/api/hologram/Hologram.java +++ b/api/src/main/java/de/oliver/fancyholograms/api/hologram/Hologram.java @@ -7,7 +7,7 @@ import org.bukkit.Bukkit; import org.bukkit.Color; import org.bukkit.World; -import org.bukkit.entity.Display; +import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -53,13 +53,12 @@ public String getName() { } /** - * Returns the Display entity of this Hologram object. * The entity is not registered in the world or server. * Only use this method if you know what you're doing. * - * @return the Display entity of this Hologram object + * @return the Hologram's entity object */ - public abstract @Nullable Display getDisplayEntity(); + public abstract @Nullable Entity getEntity(); protected abstract void create(); diff --git a/api/src/main/java/de/oliver/fancyholograms/api/hologram/HologramType.java b/api/src/main/java/de/oliver/fancyholograms/api/hologram/HologramType.java index 432fcdd8..2f2364c9 100644 --- a/api/src/main/java/de/oliver/fancyholograms/api/hologram/HologramType.java +++ b/api/src/main/java/de/oliver/fancyholograms/api/hologram/HologramType.java @@ -6,7 +6,8 @@ public enum HologramType { TEXT(Arrays.asList("background", "textshadow", "textalignment", "seethrough", "setline", "removeline", "addline", "insertbefore", "insertafter", "updatetextinterval")), ITEM(List.of("item")), - BLOCK(List.of("block")); + BLOCK(List.of("block")), + DROPPED_ITEM(List.of("item")); private final List commands; diff --git a/implementation_1_19_4/src/main/java/de/oliver/fancyholograms/hologram/version/Hologram1_19_4.java b/implementation_1_19_4/src/main/java/de/oliver/fancyholograms/hologram/version/Hologram1_19_4.java index 7c8a3009..5d0c93fe 100644 --- a/implementation_1_19_4/src/main/java/de/oliver/fancyholograms/hologram/version/Hologram1_19_4.java +++ b/implementation_1_19_4/src/main/java/de/oliver/fancyholograms/hologram/version/Hologram1_19_4.java @@ -22,7 +22,9 @@ import net.minecraft.util.Brightness; import net.minecraft.world.entity.Display; import net.minecraft.world.entity.Display.TextDisplay; +import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.Block; import org.bukkit.craftbukkit.v1_19_R3.CraftWorld; @@ -39,15 +41,15 @@ public final class Hologram1_19_4 extends Hologram { @Nullable - private Display display; + private Entity entity; public Hologram1_19_4(@NotNull final HologramData data) { super(data); } @Override - public @Nullable org.bukkit.entity.Display getDisplayEntity() { - return display != null ? (org.bukkit.entity.Display) display.getBukkitEntity() : null; + public @Nullable org.bukkit.entity.Entity getEntity() { + return entity != null ? entity.getBukkitEntity() : null; } @Override @@ -60,29 +62,32 @@ public void create() { ServerLevel world = ((CraftWorld) location.getWorld()).getHandle(); switch (data.getType()) { - case TEXT -> this.display = new Display.TextDisplay(EntityType.TEXT_DISPLAY, world); - case BLOCK -> this.display = new Display.BlockDisplay(EntityType.BLOCK_DISPLAY, world); - case ITEM -> this.display = new Display.ItemDisplay(EntityType.ITEM_DISPLAY, world); + case TEXT -> this.entity = new Display.TextDisplay(EntityType.TEXT_DISPLAY, world); + case BLOCK -> this.entity = new Display.BlockDisplay(EntityType.BLOCK_DISPLAY, world); + case ITEM -> this.entity = new Display.ItemDisplay(EntityType.ITEM_DISPLAY, world); + case DROPPED_ITEM -> { + this.entity = new ItemEntity(EntityType.ITEM, world); + this.entity.setNoGravity(true); + } } - final var DATA_INTERPOLATION_DURATION_ID = ReflectionUtils.getStaticValue(Display.class, MappingKeys1_19_4.DATA_INTERPOLATION_DURATION_ID.getMapping()); - display.getEntityData().set((EntityDataAccessor) DATA_INTERPOLATION_DURATION_ID, 1); - - final var DATA_INTERPOLATION_START_DELTA_TICKS_ID = ReflectionUtils.getStaticValue(Display.class, MappingKeys1_19_4.DATA_INTERPOLATION_START_DELTA_TICKS_ID.getMapping()); - display.getEntityData().set((EntityDataAccessor) DATA_INTERPOLATION_START_DELTA_TICKS_ID, 0); + if (this.entity instanceof Display display) { + display.setInterpolationDuration(1); + display.setInterpolationDelay(0); + } update(); } @Override public void delete() { - this.display = null; + this.entity = null; } @Override public void update() { - final var display = this.display; - if (display == null) { + final var entity = this.entity; + if (entity == null) { return; // doesn't exist, nothing to update } @@ -91,26 +96,26 @@ public void update() { if (!location.isWorldLoaded()) { return; } else { - display.setPosRaw(location.x(), location.y(), location.z()); - display.setYRot(location.getYaw()); - display.setXRot(location.getPitch()); + entity.setPosRaw(location.x(), location.y(), location.z()); + entity.setYRot(location.getYaw()); + entity.setXRot(location.getPitch()); } - if (display instanceof TextDisplay textDisplay && data instanceof TextHologramData textData) { + if (entity instanceof TextDisplay textDisplay && data instanceof TextHologramData textData) { // line width final var DATA_LINE_WIDTH_ID = ReflectionUtils.getStaticValue(TextDisplay.class, MappingKeys1_19_4.DATA_LINE_WIDTH_ID.getMapping()); - display.getEntityData().set((EntityDataAccessor) DATA_LINE_WIDTH_ID, Hologram.LINE_WIDTH); + entity.getEntityData().set((EntityDataAccessor) DATA_LINE_WIDTH_ID, Hologram.LINE_WIDTH); // background final var DATA_BACKGROUND_COLOR_ID = ReflectionUtils.getStaticValue(TextDisplay.class, MappingKeys1_19_4.DATA_BACKGROUND_COLOR_ID.getMapping()); final var background = textData.getBackground(); if (background == null) { - display.getEntityData().set((EntityDataAccessor) DATA_BACKGROUND_COLOR_ID, TextDisplay.INITIAL_BACKGROUND); + entity.getEntityData().set((EntityDataAccessor) DATA_BACKGROUND_COLOR_ID, TextDisplay.INITIAL_BACKGROUND); } else if (background == Hologram.TRANSPARENT) { - display.getEntityData().set((EntityDataAccessor) DATA_BACKGROUND_COLOR_ID, 0); + entity.getEntityData().set((EntityDataAccessor) DATA_BACKGROUND_COLOR_ID, 0); } else { - display.getEntityData().set((EntityDataAccessor) DATA_BACKGROUND_COLOR_ID, background.asARGB()); + entity.getEntityData().set((EntityDataAccessor) DATA_BACKGROUND_COLOR_ID, background.asARGB()); } // text shadow @@ -140,16 +145,19 @@ public void update() { textDisplay.setFlags((byte) (textDisplay.getFlags() & ~TextDisplay.FLAG_ALIGN_RIGHT)); } - } else if (display instanceof Display.ItemDisplay itemDisplay && data instanceof ItemHologramData itemData) { + } else if (entity instanceof Display.ItemDisplay itemDisplay && data instanceof ItemHologramData itemData) { // item itemDisplay.setItemStack(ItemStack.fromBukkitCopy(itemData.getItemStack())); - } else if (display instanceof Display.BlockDisplay blockDisplay && data instanceof BlockHologramData blockData) { + } else if (entity instanceof Display.BlockDisplay blockDisplay && data instanceof BlockHologramData blockData) { Block block = BuiltInRegistries.BLOCK.get(ResourceLocation.of("minecraft:" + blockData.getBlock().name().toLowerCase(), ':')); blockDisplay.setBlockState(block.defaultBlockState()); + } else if (entity instanceof ItemEntity item && data instanceof DroppedItemHologramData itemData) { + // item + item.setItem(ItemStack.fromBukkitCopy(itemData.getItemStack())); } - if (data instanceof DisplayHologramData displayData) { + if (entity instanceof Display display && data instanceof DisplayHologramData displayData) { // billboard data display.setBillboardConstraints(switch (displayData.getBillboard()) { case FIXED -> Display.BillboardConstraints.FIXED; @@ -184,12 +192,12 @@ public boolean show(@NotNull final Player player) { return false; } - if (this.display == null) { + if (this.entity == null) { create(); // try to create it if it doesn't exist every time } - final var display = this.display; - if (display == null) { + final var entity = this.entity; + if (entity == null) { return false; // could not be created, nothing to show } @@ -206,7 +214,7 @@ public boolean show(@NotNull final Player player) { // return false; // } - serverPlayer.connection.send(new ClientboundAddEntityPacket(display)); + serverPlayer.connection.send(new ClientboundAddEntityPacket(entity)); this.viewers.add(player.getUniqueId()); refreshHologram(player); @@ -219,12 +227,12 @@ public boolean hide(@NotNull final Player player) { return false; } - final var display = this.display; - if (display == null) { + final var entity = this.entity; + if (entity == null) { return false; // doesn't exist, nothing to hide } - ((CraftPlayer) player).getHandle().connection.send(new ClientboundRemoveEntitiesPacket(display.getId())); + ((CraftPlayer) player).getHandle().connection.send(new ClientboundRemoveEntitiesPacket(entity.getId())); this.viewers.remove(player.getUniqueId()); return true; @@ -233,8 +241,8 @@ public boolean hide(@NotNull final Player player) { @Override public void refresh(@NotNull final Player player) { - final var display = this.display; - if (display == null) { + final var entity = this.entity; + if (entity == null) { return; // doesn't exist, nothing to refresh } @@ -242,20 +250,20 @@ public void refresh(@NotNull final Player player) { return; } - ((CraftPlayer) player).getHandle().connection.send(new ClientboundTeleportEntityPacket(display)); + ((CraftPlayer) player).getHandle().connection.send(new ClientboundTeleportEntityPacket(entity)); - if (display instanceof TextDisplay textDisplay) { + if (entity instanceof TextDisplay textDisplay) { textDisplay.setText(PaperAdventure.asVanilla(getShownText(player))); } final var values = new ArrayList>(); //noinspection unchecked - for (final var item : ((Int2ObjectMap>) getValue(display.getEntityData(), "e")).values()) { + for (final var item : ((Int2ObjectMap>) getValue(entity.getEntityData(), "e")).values()) { values.add(item.value()); } - ((CraftPlayer) player).getHandle().connection.send(new ClientboundSetEntityDataPacket(display.getId(), values)); + ((CraftPlayer) player).getHandle().connection.send(new ClientboundSetEntityDataPacket(entity.getId(), values)); } } diff --git a/implementation_1_20_1/src/main/java/de/oliver/fancyholograms/hologram/version/Hologram1_20_1.java b/implementation_1_20_1/src/main/java/de/oliver/fancyholograms/hologram/version/Hologram1_20_1.java index fc5918b5..78a3c57e 100644 --- a/implementation_1_20_1/src/main/java/de/oliver/fancyholograms/hologram/version/Hologram1_20_1.java +++ b/implementation_1_20_1/src/main/java/de/oliver/fancyholograms/hologram/version/Hologram1_20_1.java @@ -22,7 +22,9 @@ import net.minecraft.util.Brightness; import net.minecraft.world.entity.Display; import net.minecraft.world.entity.Display.TextDisplay; +import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.Block; import org.bukkit.craftbukkit.v1_20_R1.CraftWorld; @@ -39,15 +41,15 @@ public final class Hologram1_20_1 extends Hologram { @Nullable - private Display display; + private Entity entity; public Hologram1_20_1(@NotNull final HologramData data) { super(data); } @Override - public @Nullable org.bukkit.entity.Display getDisplayEntity() { - return display != null ? (org.bukkit.entity.Display) display.getBukkitEntity() : null; + public @Nullable org.bukkit.entity.Entity getEntity() { + return entity != null ? entity.getBukkitEntity() : null; } @Override @@ -60,29 +62,32 @@ public void create() { ServerLevel world = ((CraftWorld) location.getWorld()).getHandle(); switch (data.getType()) { - case TEXT -> this.display = new Display.TextDisplay(EntityType.TEXT_DISPLAY, world); - case BLOCK -> this.display = new Display.BlockDisplay(EntityType.BLOCK_DISPLAY, world); - case ITEM -> this.display = new Display.ItemDisplay(EntityType.ITEM_DISPLAY, world); + case TEXT -> this.entity = new Display.TextDisplay(EntityType.TEXT_DISPLAY, world); + case BLOCK -> this.entity = new Display.BlockDisplay(EntityType.BLOCK_DISPLAY, world); + case ITEM -> this.entity = new Display.ItemDisplay(EntityType.ITEM_DISPLAY, world); + case DROPPED_ITEM -> { + this.entity = new ItemEntity(EntityType.ITEM, world); + this.entity.setNoGravity(true); + } } - final var DATA_INTERPOLATION_DURATION_ID = ReflectionUtils.getStaticValue(Display.class, MappingKeys1_20_1.DATA_INTERPOLATION_DURATION_ID.getMapping()); - display.getEntityData().set((EntityDataAccessor) DATA_INTERPOLATION_DURATION_ID, 1); - - final var DATA_INTERPOLATION_START_DELTA_TICKS_ID = ReflectionUtils.getStaticValue(Display.class, MappingKeys1_20_1.DATA_INTERPOLATION_START_DELTA_TICKS_ID.getMapping()); - display.getEntityData().set((EntityDataAccessor) DATA_INTERPOLATION_START_DELTA_TICKS_ID, 0); + if (this.entity instanceof Display display) { + display.setInterpolationDuration(1); + display.setInterpolationDelay(0); + } update(); } @Override public void delete() { - this.display = null; + this.entity = null; } @Override public void update() { - final var display = this.display; - if (display == null) { + final var entity = this.entity; + if (entity == null) { return; // doesn't exist, nothing to update } @@ -91,26 +96,26 @@ public void update() { if (location.getWorld() == null || !location.isWorldLoaded()) { return; } else { - display.setPosRaw(location.x(), location.y(), location.z()); - display.setYRot(location.getYaw()); - display.setXRot(location.getPitch()); + entity.setPosRaw(location.x(), location.y(), location.z()); + entity.setYRot(location.getYaw()); + entity.setXRot(location.getPitch()); } - if (display instanceof TextDisplay textDisplay && data instanceof TextHologramData textData) { + if (entity instanceof TextDisplay textDisplay && data instanceof TextHologramData textData) { // line width final var DATA_LINE_WIDTH_ID = ReflectionUtils.getStaticValue(TextDisplay.class, MappingKeys1_20_1.DATA_LINE_WIDTH_ID.getMapping()); - display.getEntityData().set((EntityDataAccessor) DATA_LINE_WIDTH_ID, Hologram.LINE_WIDTH); + entity.getEntityData().set((EntityDataAccessor) DATA_LINE_WIDTH_ID, Hologram.LINE_WIDTH); // background final var DATA_BACKGROUND_COLOR_ID = ReflectionUtils.getStaticValue(TextDisplay.class, MappingKeys1_20_1.DATA_BACKGROUND_COLOR_ID.getMapping()); //DATA_BACKGROUND_COLOR_ID final var background = textData.getBackground(); if (background == null) { - display.getEntityData().set((EntityDataAccessor) DATA_BACKGROUND_COLOR_ID, TextDisplay.INITIAL_BACKGROUND); + entity.getEntityData().set((EntityDataAccessor) DATA_BACKGROUND_COLOR_ID, TextDisplay.INITIAL_BACKGROUND); } else if (background == Hologram.TRANSPARENT) { - display.getEntityData().set((EntityDataAccessor) DATA_BACKGROUND_COLOR_ID, 0); + entity.getEntityData().set((EntityDataAccessor) DATA_BACKGROUND_COLOR_ID, 0); } else { - display.getEntityData().set((EntityDataAccessor) DATA_BACKGROUND_COLOR_ID, background.asARGB()); + entity.getEntityData().set((EntityDataAccessor) DATA_BACKGROUND_COLOR_ID, background.asARGB()); } // text shadow @@ -140,16 +145,19 @@ public void update() { textDisplay.setFlags((byte) (textDisplay.getFlags() & ~TextDisplay.FLAG_ALIGN_RIGHT)); } - } else if (display instanceof Display.ItemDisplay itemDisplay && data instanceof ItemHologramData itemData) { + } else if (entity instanceof Display.ItemDisplay itemDisplay && data instanceof ItemHologramData itemData) { // item itemDisplay.setItemStack(ItemStack.fromBukkitCopy(itemData.getItemStack())); - } else if (display instanceof Display.BlockDisplay blockDisplay && data instanceof BlockHologramData blockData) { + } else if (entity instanceof Display.BlockDisplay blockDisplay && data instanceof BlockHologramData blockData) { Block block = BuiltInRegistries.BLOCK.get(ResourceLocation.of("minecraft:" + blockData.getBlock().name().toLowerCase(), ':')); blockDisplay.setBlockState(block.defaultBlockState()); + } else if (entity instanceof ItemEntity item && data instanceof DroppedItemHologramData itemData) { + // item + item.setItem(ItemStack.fromBukkitCopy(itemData.getItemStack())); } - if (data instanceof DisplayHologramData displayData) { + if (entity instanceof Display display && data instanceof DisplayHologramData displayData) { // billboard data display.setBillboardConstraints(switch (displayData.getBillboard()) { case FIXED -> Display.BillboardConstraints.FIXED; @@ -184,12 +192,12 @@ public boolean show(@NotNull final Player player) { return false; } - if (this.display == null) { + if (this.entity == null) { create(); // try to create it if it doesn't exist every time } - final var display = this.display; - if (display == null) { + final var entity = this.entity; + if (entity == null) { return false; // could not be created, nothing to show } @@ -206,7 +214,7 @@ public boolean show(@NotNull final Player player) { // return false; // } - serverPlayer.connection.send(new ClientboundAddEntityPacket(display)); + serverPlayer.connection.send(new ClientboundAddEntityPacket(entity)); this.viewers.add(player.getUniqueId()); refreshHologram(player); @@ -219,12 +227,12 @@ public boolean hide(@NotNull final Player player) { return false; } - final var display = this.display; - if (display == null) { + final var entity = this.entity; + if (entity == null) { return false; // doesn't exist, nothing to hide } - ((CraftPlayer) player).getHandle().connection.send(new ClientboundRemoveEntitiesPacket(display.getId())); + ((CraftPlayer) player).getHandle().connection.send(new ClientboundRemoveEntitiesPacket(entity.getId())); this.viewers.remove(player.getUniqueId()); return true; @@ -233,8 +241,8 @@ public boolean hide(@NotNull final Player player) { @Override public void refresh(@NotNull final Player player) { - final var display = this.display; - if (display == null) { + final var entity = this.entity; + if (entity == null) { return; // doesn't exist, nothing to refresh } @@ -242,20 +250,20 @@ public void refresh(@NotNull final Player player) { return; } - ((CraftPlayer) player).getHandle().connection.send(new ClientboundTeleportEntityPacket(display)); + ((CraftPlayer) player).getHandle().connection.send(new ClientboundTeleportEntityPacket(entity)); - if (display instanceof TextDisplay textDisplay) { + if (entity instanceof TextDisplay textDisplay) { textDisplay.setText(PaperAdventure.asVanilla(getShownText(player))); } final var values = new ArrayList>(); //noinspection unchecked - for (final var item : ((Int2ObjectMap>) getValue(display.getEntityData(), "e")).values()) { + for (final var item : ((Int2ObjectMap>) getValue(entity.getEntityData(), "e")).values()) { values.add(item.value()); } - ((CraftPlayer) player).getHandle().connection.send(new ClientboundSetEntityDataPacket(display.getId(), values)); + ((CraftPlayer) player).getHandle().connection.send(new ClientboundSetEntityDataPacket(entity.getId(), values)); } } diff --git a/implementation_1_20_2/src/main/java/de/oliver/fancyholograms/hologram/version/Hologram1_20_2.java b/implementation_1_20_2/src/main/java/de/oliver/fancyholograms/hologram/version/Hologram1_20_2.java index 1a51aa84..28e1d1a1 100644 --- a/implementation_1_20_2/src/main/java/de/oliver/fancyholograms/hologram/version/Hologram1_20_2.java +++ b/implementation_1_20_2/src/main/java/de/oliver/fancyholograms/hologram/version/Hologram1_20_2.java @@ -22,7 +22,9 @@ import net.minecraft.util.Brightness; import net.minecraft.world.entity.Display; import net.minecraft.world.entity.Display.TextDisplay; +import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.Block; import org.bukkit.craftbukkit.v1_20_R2.CraftWorld; @@ -39,15 +41,15 @@ public final class Hologram1_20_2 extends Hologram { @Nullable - private Display display; + private Entity entity; public Hologram1_20_2(@NotNull final HologramData data) { super(data); } @Override - public @Nullable org.bukkit.entity.Display getDisplayEntity() { - return display != null ? (org.bukkit.entity.Display) display.getBukkitEntity() : null; + public @Nullable org.bukkit.entity.Entity getEntity() { + return entity != null ? entity.getBukkitEntity() : null; } @Override @@ -60,29 +62,32 @@ public void create() { ServerLevel world = ((CraftWorld) location.getWorld()).getHandle(); switch (data.getType()) { - case TEXT -> this.display = new Display.TextDisplay(EntityType.TEXT_DISPLAY, world); - case BLOCK -> this.display = new Display.BlockDisplay(EntityType.BLOCK_DISPLAY, world); - case ITEM -> this.display = new Display.ItemDisplay(EntityType.ITEM_DISPLAY, world); + case TEXT -> this.entity = new Display.TextDisplay(EntityType.TEXT_DISPLAY, world); + case BLOCK -> this.entity = new Display.BlockDisplay(EntityType.BLOCK_DISPLAY, world); + case ITEM -> this.entity = new Display.ItemDisplay(EntityType.ITEM_DISPLAY, world); + case DROPPED_ITEM -> { + this.entity = new ItemEntity(EntityType.ITEM, world); + this.entity.setNoGravity(true); + } } - final var DATA_INTERPOLATION_DURATION_ID = ReflectionUtils.getStaticValue(Display.class, MappingKeys1_20_2.DATA_INTERPOLATION_DURATION_ID.getMapping()); - display.getEntityData().set((EntityDataAccessor) DATA_INTERPOLATION_DURATION_ID, 1); - - final var DATA_INTERPOLATION_START_DELTA_TICKS_ID = ReflectionUtils.getStaticValue(Display.class, MappingKeys1_20_2.DATA_INTERPOLATION_START_DELTA_TICKS_ID.getMapping()); - display.getEntityData().set((EntityDataAccessor) DATA_INTERPOLATION_START_DELTA_TICKS_ID, 0); + if (this.entity instanceof Display display) { + display.setTransformationInterpolationDuration(1); + display.setTransformationInterpolationDelay(0); + } update(); } @Override public void delete() { - this.display = null; + this.entity = null; } @Override public void update() { - final var display = this.display; - if (display == null) { + final var entity = this.entity; + if (entity == null) { return; // doesn't exist, nothing to update } @@ -91,26 +96,26 @@ public void update() { if (location.getWorld() == null || !location.isWorldLoaded()) { return; } else { - display.setPosRaw(location.x(), location.y(), location.z()); - display.setYRot(location.getYaw()); - display.setXRot(location.getPitch()); + entity.setPosRaw(location.x(), location.y(), location.z()); + entity.setYRot(location.getYaw()); + entity.setXRot(location.getPitch()); } - if (display instanceof TextDisplay textDisplay && data instanceof TextHologramData textData) { + if (entity instanceof TextDisplay textDisplay && data instanceof TextHologramData textData) { // line width final var DATA_LINE_WIDTH_ID = ReflectionUtils.getStaticValue(TextDisplay.class, MappingKeys1_20_2.DATA_LINE_WIDTH_ID.getMapping()); - display.getEntityData().set((EntityDataAccessor) DATA_LINE_WIDTH_ID, Hologram.LINE_WIDTH); + entity.getEntityData().set((EntityDataAccessor) DATA_LINE_WIDTH_ID, Hologram.LINE_WIDTH); // background final var DATA_BACKGROUND_COLOR_ID = ReflectionUtils.getStaticValue(TextDisplay.class, MappingKeys1_20_2.DATA_BACKGROUND_COLOR_ID.getMapping()); final var background = textData.getBackground(); if (background == null) { - display.getEntityData().set((EntityDataAccessor) DATA_BACKGROUND_COLOR_ID, TextDisplay.INITIAL_BACKGROUND); + entity.getEntityData().set((EntityDataAccessor) DATA_BACKGROUND_COLOR_ID, TextDisplay.INITIAL_BACKGROUND); } else if (background == Hologram.TRANSPARENT) { - display.getEntityData().set((EntityDataAccessor) DATA_BACKGROUND_COLOR_ID, 0); + entity.getEntityData().set((EntityDataAccessor) DATA_BACKGROUND_COLOR_ID, 0); } else { - display.getEntityData().set((EntityDataAccessor) DATA_BACKGROUND_COLOR_ID, background.asARGB()); + entity.getEntityData().set((EntityDataAccessor) DATA_BACKGROUND_COLOR_ID, background.asARGB()); } // text shadow @@ -140,16 +145,16 @@ public void update() { textDisplay.setFlags((byte) (textDisplay.getFlags() & ~TextDisplay.FLAG_ALIGN_RIGHT)); } - } else if (display instanceof Display.ItemDisplay itemDisplay && data instanceof ItemHologramData itemData) { + } else if (entity instanceof Display.ItemDisplay itemDisplay && data instanceof ItemHologramData itemData) { // item itemDisplay.setItemStack(ItemStack.fromBukkitCopy(itemData.getItemStack())); - } else if (display instanceof Display.BlockDisplay blockDisplay && data instanceof BlockHologramData blockData) { + } else if (entity instanceof Display.BlockDisplay blockDisplay && data instanceof BlockHologramData blockData) { Block block = BuiltInRegistries.BLOCK.get(ResourceLocation.of("minecraft:" + blockData.getBlock().name().toLowerCase(), ':')); blockDisplay.setBlockState(block.defaultBlockState()); } - if (data instanceof DisplayHologramData displayData) { + if (entity instanceof Display display && data instanceof DisplayHologramData displayData) { // billboard data display.setBillboardConstraints(switch (displayData.getBillboard()) { case FIXED -> Display.BillboardConstraints.FIXED; @@ -184,12 +189,12 @@ public boolean show(@NotNull final Player player) { return false; } - if (this.display == null) { + if (this.entity == null) { create(); // try to create it if it doesn't exist every time } - final var display = this.display; - if (display == null) { + final var entity = this.entity; + if (entity == null) { return false; // could not be created, nothing to show } @@ -206,7 +211,7 @@ public boolean show(@NotNull final Player player) { // return false; // } - serverPlayer.connection.send(new ClientboundAddEntityPacket(display)); + serverPlayer.connection.send(new ClientboundAddEntityPacket(entity)); this.viewers.add(player.getUniqueId()); refreshHologram(player); @@ -219,12 +224,12 @@ public boolean hide(@NotNull final Player player) { return false; } - final var display = this.display; - if (display == null) { + final var entity = this.entity; + if (entity == null) { return false; // doesn't exist, nothing to hide } - ((CraftPlayer) player).getHandle().connection.send(new ClientboundRemoveEntitiesPacket(display.getId())); + ((CraftPlayer) player).getHandle().connection.send(new ClientboundRemoveEntitiesPacket(entity.getId())); this.viewers.remove(player.getUniqueId()); return true; @@ -233,8 +238,8 @@ public boolean hide(@NotNull final Player player) { @Override public void refresh(@NotNull final Player player) { - final var display = this.display; - if (display == null) { + final var entity = this.entity; + if (entity == null) { return; // doesn't exist, nothing to refresh } @@ -242,20 +247,20 @@ public void refresh(@NotNull final Player player) { return; } - ((CraftPlayer) player).getHandle().connection.send(new ClientboundTeleportEntityPacket(display)); + ((CraftPlayer) player).getHandle().connection.send(new ClientboundTeleportEntityPacket(entity)); - if (display instanceof TextDisplay textDisplay) { + if (entity instanceof TextDisplay textDisplay) { textDisplay.setText(PaperAdventure.asVanilla(getShownText(player))); } final var values = new ArrayList>(); //noinspection unchecked - for (final var item : ((Int2ObjectMap>) getValue(display.getEntityData(), "e")).values()) { + for (final var item : ((Int2ObjectMap>) getValue(entity.getEntityData(), "e")).values()) { values.add(item.value()); } - ((CraftPlayer) player).getHandle().connection.send(new ClientboundSetEntityDataPacket(display.getId(), values)); + ((CraftPlayer) player).getHandle().connection.send(new ClientboundSetEntityDataPacket(entity.getId(), values)); } } diff --git a/implementation_1_20_4/src/main/java/de/oliver/fancyholograms/hologram/version/Hologram1_20_4.java b/implementation_1_20_4/src/main/java/de/oliver/fancyholograms/hologram/version/Hologram1_20_4.java index 8a71fb6d..6c829143 100644 --- a/implementation_1_20_4/src/main/java/de/oliver/fancyholograms/hologram/version/Hologram1_20_4.java +++ b/implementation_1_20_4/src/main/java/de/oliver/fancyholograms/hologram/version/Hologram1_20_4.java @@ -22,7 +22,9 @@ import net.minecraft.util.Brightness; import net.minecraft.world.entity.Display; import net.minecraft.world.entity.Display.TextDisplay; +import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.Block; import org.bukkit.craftbukkit.v1_20_R3.CraftWorld; @@ -39,15 +41,15 @@ public final class Hologram1_20_4 extends Hologram { @Nullable - private Display display; + private Entity entity; public Hologram1_20_4(@NotNull final HologramData data) { super(data); } @Override - public @Nullable org.bukkit.entity.Display getDisplayEntity() { - return display != null ? (org.bukkit.entity.Display) display.getBukkitEntity() : null; + public @Nullable org.bukkit.entity.Entity getEntity() { + return entity != null ? entity.getBukkitEntity() : null; } @Override @@ -60,29 +62,32 @@ public void create() { ServerLevel world = ((CraftWorld) location.getWorld()).getHandle(); switch (data.getType()) { - case TEXT -> this.display = new Display.TextDisplay(EntityType.TEXT_DISPLAY, world); - case BLOCK -> this.display = new Display.BlockDisplay(EntityType.BLOCK_DISPLAY, world); - case ITEM -> this.display = new Display.ItemDisplay(EntityType.ITEM_DISPLAY, world); + case TEXT -> this.entity = new Display.TextDisplay(EntityType.TEXT_DISPLAY, world); + case BLOCK -> this.entity = new Display.BlockDisplay(EntityType.BLOCK_DISPLAY, world); + case ITEM -> this.entity = new Display.ItemDisplay(EntityType.ITEM_DISPLAY, world); + case DROPPED_ITEM -> { + this.entity = new ItemEntity(EntityType.ITEM, world); + this.entity.setNoGravity(true); + } } - final var DATA_TRANSFORMATION_INTERPOLATION_DURATION_ID = ReflectionUtils.getStaticValue(Display.class, MappingKeys1_20_4.DISPLAY__DATA_TRANSFORMATION_INTERPOLATION_DURATION_ID.getMapping()); - display.getEntityData().set((EntityDataAccessor) DATA_TRANSFORMATION_INTERPOLATION_DURATION_ID, 1); - - final var DATA_TRANSFORMATION_INTERPOLATION_START_DELTA_TICKS_ID = ReflectionUtils.getStaticValue(Display.class, MappingKeys1_20_4.DISPLAY__DATA_TRANSFORMATION_INTERPOLATION_START_DELTA_TICKS_ID.getMapping()); - display.getEntityData().set((EntityDataAccessor) DATA_TRANSFORMATION_INTERPOLATION_START_DELTA_TICKS_ID, 0); + if (this.entity instanceof Display display) { + display.setTransformationInterpolationDuration(1); + display.setTransformationInterpolationDelay(0); + } update(); } @Override public void delete() { - this.display = null; + this.entity = null; } @Override public void update() { - final var display = this.display; - if (display == null) { + final var entity = this.entity; + if (entity == null) { return; // doesn't exist, nothing to update } @@ -91,26 +96,26 @@ public void update() { if (location.getWorld() == null || !location.isWorldLoaded()) { return; } else { - display.setPosRaw(location.x(), location.y(), location.z()); - display.setYRot(location.getYaw()); - display.setXRot(location.getPitch()); + entity.setPosRaw(location.x(), location.y(), location.z()); + entity.setYRot(location.getYaw()); + entity.setXRot(location.getPitch()); } - if (display instanceof TextDisplay textDisplay && data instanceof TextHologramData textData) { + if (entity instanceof TextDisplay textDisplay && data instanceof TextHologramData textData) { // line width final var DATA_LINE_WIDTH_ID = ReflectionUtils.getStaticValue(TextDisplay.class, MappingKeys1_20_4.TEXT_DISPLAY__DATA_LINE_WIDTH_ID.getMapping()); - display.getEntityData().set((EntityDataAccessor) DATA_LINE_WIDTH_ID, Hologram.LINE_WIDTH); + entity.getEntityData().set((EntityDataAccessor) DATA_LINE_WIDTH_ID, Hologram.LINE_WIDTH); // background final var DATA_BACKGROUND_COLOR_ID = ReflectionUtils.getStaticValue(TextDisplay.class, MappingKeys1_20_4.TEXT_DISPLAY__DATA_BACKGROUND_COLOR_ID.getMapping()); final var background = textData.getBackground(); if (background == null) { - display.getEntityData().set((EntityDataAccessor) DATA_BACKGROUND_COLOR_ID, TextDisplay.INITIAL_BACKGROUND); + entity.getEntityData().set((EntityDataAccessor) DATA_BACKGROUND_COLOR_ID, TextDisplay.INITIAL_BACKGROUND); } else if (background == Hologram.TRANSPARENT) { - display.getEntityData().set((EntityDataAccessor) DATA_BACKGROUND_COLOR_ID, 0); + entity.getEntityData().set((EntityDataAccessor) DATA_BACKGROUND_COLOR_ID, 0); } else { - display.getEntityData().set((EntityDataAccessor) DATA_BACKGROUND_COLOR_ID, background.asARGB()); + entity.getEntityData().set((EntityDataAccessor) DATA_BACKGROUND_COLOR_ID, background.asARGB()); } // text shadow @@ -140,16 +145,16 @@ public void update() { textDisplay.setFlags((byte) (textDisplay.getFlags() & ~TextDisplay.FLAG_ALIGN_RIGHT)); } - } else if (display instanceof Display.ItemDisplay itemDisplay && data instanceof ItemHologramData itemData) { + } else if (entity instanceof Display.ItemDisplay itemDisplay && data instanceof ItemHologramData itemData) { // item itemDisplay.setItemStack(ItemStack.fromBukkitCopy(itemData.getItemStack())); - } else if (display instanceof Display.BlockDisplay blockDisplay && data instanceof BlockHologramData blockData) { + } else if (entity instanceof Display.BlockDisplay blockDisplay && data instanceof BlockHologramData blockData) { Block block = BuiltInRegistries.BLOCK.get(ResourceLocation.of("minecraft:" + blockData.getBlock().name().toLowerCase(), ':')); blockDisplay.setBlockState(block.defaultBlockState()); } - if (data instanceof DisplayHologramData displayData) { + if (entity instanceof Display display && data instanceof DisplayHologramData displayData) { // billboard data display.setBillboardConstraints(switch (displayData.getBillboard()) { case FIXED -> Display.BillboardConstraints.FIXED; @@ -184,12 +189,12 @@ public boolean show(@NotNull final Player player) { return false; } - if (this.display == null) { + if (this.entity == null) { create(); // try to create it if it doesn't exist every time } - final var display = this.display; - if (display == null) { + final var entity = this.entity; + if (entity == null) { return false; // could not be created, nothing to show } @@ -207,7 +212,7 @@ public boolean show(@NotNull final Player player) { // return false; // } - serverPlayer.connection.send(new ClientboundAddEntityPacket(display)); + serverPlayer.connection.send(new ClientboundAddEntityPacket(entity)); this.viewers.add(player.getUniqueId()); refreshHologram(player); @@ -220,12 +225,12 @@ public boolean hide(@NotNull final Player player) { return false; } - final var display = this.display; - if (display == null) { + final var entity = this.entity; + if (entity == null) { return false; // doesn't exist, nothing to hide } - ((CraftPlayer) player).getHandle().connection.send(new ClientboundRemoveEntitiesPacket(display.getId())); + ((CraftPlayer) player).getHandle().connection.send(new ClientboundRemoveEntitiesPacket(entity.getId())); this.viewers.remove(player.getUniqueId()); return true; @@ -234,8 +239,8 @@ public boolean hide(@NotNull final Player player) { @Override public void refresh(@NotNull final Player player) { - final var display = this.display; - if (display == null) { + final var entity = this.entity; + if (entity == null) { return; // doesn't exist, nothing to refresh } @@ -243,20 +248,20 @@ public void refresh(@NotNull final Player player) { return; } - ((CraftPlayer) player).getHandle().connection.send(new ClientboundTeleportEntityPacket(display)); + ((CraftPlayer) player).getHandle().connection.send(new ClientboundTeleportEntityPacket(entity)); - if (display instanceof TextDisplay textDisplay) { + if (entity instanceof TextDisplay textDisplay) { textDisplay.setText(PaperAdventure.asVanilla(getShownText(player))); } final var values = new ArrayList>(); //noinspection unchecked - for (final var item : ((Int2ObjectMap>) getValue(display.getEntityData(), "e")).values()) { + for (final var item : ((Int2ObjectMap>) getValue(entity.getEntityData(), "e")).values()) { values.add(item.value()); } - ((CraftPlayer) player).getHandle().connection.send(new ClientboundSetEntityDataPacket(display.getId(), values)); + ((CraftPlayer) player).getHandle().connection.send(new ClientboundSetEntityDataPacket(entity.getId(), values)); } } diff --git a/implementation_1_20_6/src/main/java/de/oliver/fancyholograms/hologram/version/Hologram1_20_6.java b/implementation_1_20_6/src/main/java/de/oliver/fancyholograms/hologram/version/Hologram1_20_6.java index 704b2c21..d791c574 100644 --- a/implementation_1_20_6/src/main/java/de/oliver/fancyholograms/hologram/version/Hologram1_20_6.java +++ b/implementation_1_20_6/src/main/java/de/oliver/fancyholograms/hologram/version/Hologram1_20_6.java @@ -21,7 +21,9 @@ import net.minecraft.util.Brightness; import net.minecraft.world.entity.Display; import net.minecraft.world.entity.Display.TextDisplay; +import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.Block; import org.bukkit.craftbukkit.CraftWorld; @@ -38,15 +40,15 @@ public final class Hologram1_20_6 extends Hologram { @Nullable - private Display display; + private Entity entity; public Hologram1_20_6(@NotNull final HologramData data) { super(data); } @Override - public @Nullable org.bukkit.entity.Display getDisplayEntity() { - return display != null ? (org.bukkit.entity.Display) display.getBukkitEntity() : null; + public @Nullable org.bukkit.entity.Entity getEntity() { + return entity != null ? entity.getBukkitEntity() : null; } @Override @@ -59,29 +61,32 @@ public void create() { ServerLevel world = ((CraftWorld) location.getWorld()).getHandle(); switch (data.getType()) { - case TEXT -> this.display = new Display.TextDisplay(EntityType.TEXT_DISPLAY, world); - case BLOCK -> this.display = new Display.BlockDisplay(EntityType.BLOCK_DISPLAY, world); - case ITEM -> this.display = new Display.ItemDisplay(EntityType.ITEM_DISPLAY, world); + case TEXT -> this.entity = new Display.TextDisplay(EntityType.TEXT_DISPLAY, world); + case BLOCK -> this.entity = new Display.BlockDisplay(EntityType.BLOCK_DISPLAY, world); + case ITEM -> this.entity = new Display.ItemDisplay(EntityType.ITEM_DISPLAY, world); + case DROPPED_ITEM -> { + this.entity = new ItemEntity(EntityType.ITEM, world); + this.entity.setNoGravity(true); + } } - final var DATA_TRANSFORMATION_INTERPOLATION_DURATION_ID = ReflectionUtils.getStaticValue(Display.class, MappingKeys1_20_6.DISPLAY__DATA_TRANSFORMATION_INTERPOLATION_DURATION_ID.getMapping()); - display.getEntityData().set((EntityDataAccessor) DATA_TRANSFORMATION_INTERPOLATION_DURATION_ID, 1); - - final var DATA_TRANSFORMATION_INTERPOLATION_START_DELTA_TICKS_ID = ReflectionUtils.getStaticValue(Display.class, MappingKeys1_20_6.DISPLAY__DATA_TRANSFORMATION_INTERPOLATION_START_DELTA_TICKS_ID.getMapping()); - display.getEntityData().set((EntityDataAccessor) DATA_TRANSFORMATION_INTERPOLATION_START_DELTA_TICKS_ID, 0); + if (this.entity instanceof Display display) { + display.setTransformationInterpolationDuration(1); + display.setTransformationInterpolationDelay(0); + } update(); } @Override public void delete() { - this.display = null; + this.entity = null; } @Override public void update() { - final var display = this.display; - if (display == null) { + final var entity = this.entity; + if (entity == null) { return; // doesn't exist, nothing to update } @@ -90,26 +95,26 @@ public void update() { if (location.getWorld() == null || !location.isWorldLoaded()) { return; } else { - display.setPosRaw(location.x(), location.y(), location.z()); - display.setYRot(location.getYaw()); - display.setXRot(location.getPitch()); + entity.setPosRaw(location.x(), location.y(), location.z()); + entity.setYRot(location.getYaw()); + entity.setXRot(location.getPitch()); } - if (display instanceof TextDisplay textDisplay && data instanceof TextHologramData textData) { + if (entity instanceof TextDisplay textDisplay && data instanceof TextHologramData textData) { // line width final var DATA_LINE_WIDTH_ID = ReflectionUtils.getStaticValue(TextDisplay.class, MappingKeys1_20_6.TEXT_DISPLAY__DATA_LINE_WIDTH_ID.getMapping()); - display.getEntityData().set((EntityDataAccessor) DATA_LINE_WIDTH_ID, Hologram.LINE_WIDTH); + entity.getEntityData().set((EntityDataAccessor) DATA_LINE_WIDTH_ID, Hologram.LINE_WIDTH); // background final var DATA_BACKGROUND_COLOR_ID = ReflectionUtils.getStaticValue(TextDisplay.class, MappingKeys1_20_6.TEXT_DISPLAY__DATA_BACKGROUND_COLOR_ID.getMapping()); final var background = textData.getBackground(); if (background == null) { - display.getEntityData().set((EntityDataAccessor) DATA_BACKGROUND_COLOR_ID, TextDisplay.INITIAL_BACKGROUND); + entity.getEntityData().set((EntityDataAccessor) DATA_BACKGROUND_COLOR_ID, TextDisplay.INITIAL_BACKGROUND); } else if (background == Hologram.TRANSPARENT) { - display.getEntityData().set((EntityDataAccessor) DATA_BACKGROUND_COLOR_ID, 0); + entity.getEntityData().set((EntityDataAccessor) DATA_BACKGROUND_COLOR_ID, 0); } else { - display.getEntityData().set((EntityDataAccessor) DATA_BACKGROUND_COLOR_ID, background.asARGB()); + entity.getEntityData().set((EntityDataAccessor) DATA_BACKGROUND_COLOR_ID, background.asARGB()); } // text shadow @@ -139,16 +144,16 @@ public void update() { textDisplay.setFlags((byte) (textDisplay.getFlags() & ~TextDisplay.FLAG_ALIGN_RIGHT)); } - } else if (display instanceof Display.ItemDisplay itemDisplay && data instanceof ItemHologramData itemData) { + } else if (entity instanceof Display.ItemDisplay itemDisplay && data instanceof ItemHologramData itemData) { // item itemDisplay.setItemStack(ItemStack.fromBukkitCopy(itemData.getItemStack())); - } else if (display instanceof Display.BlockDisplay blockDisplay && data instanceof BlockHologramData blockData) { + } else if (entity instanceof Display.BlockDisplay blockDisplay && data instanceof BlockHologramData blockData) { Block block = BuiltInRegistries.BLOCK.get(ResourceLocation.of("minecraft:" + blockData.getBlock().name().toLowerCase(), ':')); blockDisplay.setBlockState(block.defaultBlockState()); } - if (data instanceof DisplayHologramData displayData) { + if (entity instanceof Display display && data instanceof DisplayHologramData displayData) { // billboard data display.setBillboardConstraints(switch (displayData.getBillboard()) { case FIXED -> Display.BillboardConstraints.FIXED; @@ -183,12 +188,12 @@ public boolean show(@NotNull final Player player) { return false; } - if (this.display == null) { + if (this.entity == null) { create(); // try to create it if it doesn't exist every time } - final var display = this.display; - if (display == null) { + final var entity = this.entity; + if (entity == null) { return false; // could not be created, nothing to show } @@ -205,7 +210,7 @@ public boolean show(@NotNull final Player player) { // return false; // } - serverPlayer.connection.send(new ClientboundAddEntityPacket(display)); + serverPlayer.connection.send(new ClientboundAddEntityPacket(entity)); this.viewers.add(player.getUniqueId()); refreshHologram(player); @@ -218,12 +223,12 @@ public boolean hide(@NotNull final Player player) { return false; } - final var display = this.display; - if (display == null) { + final var entity = this.entity; + if (entity == null) { return false; // doesn't exist, nothing to hide } - ((CraftPlayer) player).getHandle().connection.send(new ClientboundRemoveEntitiesPacket(display.getId())); + ((CraftPlayer) player).getHandle().connection.send(new ClientboundRemoveEntitiesPacket(entity.getId())); this.viewers.remove(player.getUniqueId()); return true; @@ -232,8 +237,8 @@ public boolean hide(@NotNull final Player player) { @Override public void refresh(@NotNull final Player player) { - final var display = this.display; - if (display == null) { + final var entity = this.entity; + if (entity == null) { return; // doesn't exist, nothing to refresh } @@ -241,20 +246,19 @@ public void refresh(@NotNull final Player player) { return; } - ((CraftPlayer) player).getHandle().connection.send(new ClientboundTeleportEntityPacket(display)); + ((CraftPlayer) player).getHandle().connection.send(new ClientboundTeleportEntityPacket(entity)); - if (display instanceof TextDisplay textDisplay) { + if (entity instanceof TextDisplay textDisplay) { textDisplay.setText(PaperAdventure.asVanilla(getShownText(player))); } final var values = new ArrayList>(); - //noinspection unchecked - for (final var item : ((SynchedEntityData.DataItem[]) getValue(display.getEntityData(), "itemsById"))) { + for (final var item : ((SynchedEntityData.DataItem[]) getValue(entity.getEntityData(), "itemsById"))) { values.add(item.value()); } - ((CraftPlayer) player).getHandle().connection.send(new ClientboundSetEntityDataPacket(display.getId(), values)); + ((CraftPlayer) player).getHandle().connection.send(new ClientboundSetEntityDataPacket(entity.getId(), values)); } } diff --git a/implementation_1_21/src/main/java/de/oliver/fancyholograms/hologram/version/Hologram1_21.java b/implementation_1_21/src/main/java/de/oliver/fancyholograms/hologram/version/Hologram1_21.java index 5885033f..c39a47cd 100644 --- a/implementation_1_21/src/main/java/de/oliver/fancyholograms/hologram/version/Hologram1_21.java +++ b/implementation_1_21/src/main/java/de/oliver/fancyholograms/hologram/version/Hologram1_21.java @@ -22,7 +22,9 @@ import net.minecraft.util.Brightness; import net.minecraft.world.entity.Display; import net.minecraft.world.entity.Display.TextDisplay; +import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.Block; import org.bukkit.craftbukkit.CraftWorld; @@ -40,15 +42,15 @@ public final class Hologram1_21 extends Hologram { @Nullable - private Display display; + private Entity entity; public Hologram1_21(@NotNull final HologramData data) { super(data); } @Override - public @Nullable org.bukkit.entity.Display getDisplayEntity() { - return display != null ? (org.bukkit.entity.Display) display.getBukkitEntity() : null; + public @Nullable org.bukkit.entity.Entity getEntity() { + return entity != null ? entity.getBukkitEntity() : null; } @Override @@ -61,29 +63,32 @@ public void create() { ServerLevel world = ((CraftWorld) location.getWorld()).getHandle(); switch (data.getType()) { - case TEXT -> this.display = new Display.TextDisplay(EntityType.TEXT_DISPLAY, world); - case BLOCK -> this.display = new Display.BlockDisplay(EntityType.BLOCK_DISPLAY, world); - case ITEM -> this.display = new Display.ItemDisplay(EntityType.ITEM_DISPLAY, world); + case TEXT -> this.entity = new Display.TextDisplay(EntityType.TEXT_DISPLAY, world); + case BLOCK -> this.entity = new Display.BlockDisplay(EntityType.BLOCK_DISPLAY, world); + case ITEM -> this.entity = new Display.ItemDisplay(EntityType.ITEM_DISPLAY, world); + case DROPPED_ITEM -> { + this.entity = new ItemEntity(EntityType.ITEM, world); + this.entity.setNoGravity(true); + } } - final var DATA_TRANSFORMATION_INTERPOLATION_DURATION_ID = ReflectionUtils.getStaticValue(Display.class, MappingKeys1_21.DISPLAY__DATA_TRANSFORMATION_INTERPOLATION_DURATION_ID.getMapping()); - display.getEntityData().set((EntityDataAccessor) DATA_TRANSFORMATION_INTERPOLATION_DURATION_ID, 1); - - final var DATA_TRANSFORMATION_INTERPOLATION_START_DELTA_TICKS_ID = ReflectionUtils.getStaticValue(Display.class, MappingKeys1_21.DISPLAY__DATA_TRANSFORMATION_INTERPOLATION_START_DELTA_TICKS_ID.getMapping()); - display.getEntityData().set((EntityDataAccessor) DATA_TRANSFORMATION_INTERPOLATION_START_DELTA_TICKS_ID, 0); + if (this.entity instanceof Display display) { + display.setTransformationInterpolationDuration(1); + display.setTransformationInterpolationDelay(0); + } update(); } @Override public void delete() { - this.display = null; + this.entity = null; } @Override public void update() { - final var display = this.display; - if (display == null) { + final var entity = this.entity; + if (entity == null) { return; // doesn't exist, nothing to update } @@ -92,26 +97,26 @@ public void update() { if (location.getWorld() == null || !location.isWorldLoaded()) { return; } else { - display.setPosRaw(location.x(), location.y(), location.z()); - display.setYRot(location.getYaw()); - display.setXRot(location.getPitch()); + entity.setPosRaw(location.x(), location.y(), location.z()); + entity.setYRot(location.getYaw()); + entity.setXRot(location.getPitch()); } - if (display instanceof TextDisplay textDisplay && data instanceof TextHologramData textData) { + if (entity instanceof TextDisplay textDisplay && data instanceof TextHologramData textData) { // line width final var DATA_LINE_WIDTH_ID = ReflectionUtils.getStaticValue(TextDisplay.class, MappingKeys1_21.TEXT_DISPLAY__DATA_LINE_WIDTH_ID.getMapping()); - display.getEntityData().set((EntityDataAccessor) DATA_LINE_WIDTH_ID, Hologram.LINE_WIDTH); + entity.getEntityData().set((EntityDataAccessor) DATA_LINE_WIDTH_ID, Hologram.LINE_WIDTH); // background final var DATA_BACKGROUND_COLOR_ID = ReflectionUtils.getStaticValue(TextDisplay.class, MappingKeys1_21.TEXT_DISPLAY__DATA_BACKGROUND_COLOR_ID.getMapping()); final var background = textData.getBackground(); if (background == null) { - display.getEntityData().set((EntityDataAccessor) DATA_BACKGROUND_COLOR_ID, TextDisplay.INITIAL_BACKGROUND); + entity.getEntityData().set((EntityDataAccessor) DATA_BACKGROUND_COLOR_ID, TextDisplay.INITIAL_BACKGROUND); } else if (background == Hologram.TRANSPARENT) { - display.getEntityData().set((EntityDataAccessor) DATA_BACKGROUND_COLOR_ID, 0); + entity.getEntityData().set((EntityDataAccessor) DATA_BACKGROUND_COLOR_ID, 0); } else { - display.getEntityData().set((EntityDataAccessor) DATA_BACKGROUND_COLOR_ID, background.asARGB()); + entity.getEntityData().set((EntityDataAccessor) DATA_BACKGROUND_COLOR_ID, background.asARGB()); } // text shadow @@ -140,17 +145,18 @@ public void update() { } else { textDisplay.setFlags((byte) (textDisplay.getFlags() & ~TextDisplay.FLAG_ALIGN_RIGHT)); } - - } else if (display instanceof Display.ItemDisplay itemDisplay && data instanceof ItemHologramData itemData) { + } else if (entity instanceof Display.ItemDisplay itemDisplay && data instanceof ItemHologramData itemData) { // item itemDisplay.setItemStack(ItemStack.fromBukkitCopy(itemData.getItemStack())); - - } else if (display instanceof Display.BlockDisplay blockDisplay && data instanceof BlockHologramData blockData) { + } else if (entity instanceof Display.BlockDisplay blockDisplay && data instanceof BlockHologramData blockData) { Block block = BuiltInRegistries.BLOCK.get(ResourceLocation.parse(blockData.getBlock().name().toLowerCase())); blockDisplay.setBlockState(block.defaultBlockState()); + } else if (entity instanceof ItemEntity item && data instanceof DroppedItemHologramData itemData) { + // item + item.setItem(ItemStack.fromBukkitCopy(itemData.getItemStack())); } - if (data instanceof DisplayHologramData displayData) { + if (entity instanceof Display display && data instanceof DisplayHologramData displayData) { // billboard data display.setBillboardConstraints(switch (displayData.getBillboard()) { case FIXED -> Display.BillboardConstraints.FIXED; @@ -185,12 +191,12 @@ public boolean show(@NotNull final Player player) { return false; } - if (this.display == null) { + if (this.entity == null) { create(); // try to create it if it doesn't exist every time } - final var display = this.display; - if (display == null) { + final var entity = this.entity; + if (entity == null) { return false; // could not be created, nothing to show } @@ -207,9 +213,9 @@ public boolean show(@NotNull final Player player) { // return false; // } - ServerEntity serverEntity = new ServerEntity(serverPlayer.serverLevel(), display, 0, false, packet -> { + ServerEntity serverEntity = new ServerEntity(serverPlayer.serverLevel(), entity, 0, false, packet -> { }, Set.of()); - serverPlayer.connection.send(new ClientboundAddEntityPacket(display, serverEntity)); + serverPlayer.connection.send(new ClientboundAddEntityPacket(entity, serverEntity)); this.viewers.add(player.getUniqueId()); refreshHologram(player); @@ -222,12 +228,12 @@ public boolean hide(@NotNull final Player player) { return false; } - final var display = this.display; - if (display == null) { + final var entity = this.entity; + if (entity == null) { return false; // doesn't exist, nothing to hide } - ((CraftPlayer) player).getHandle().connection.send(new ClientboundRemoveEntitiesPacket(display.getId())); + ((CraftPlayer) player).getHandle().connection.send(new ClientboundRemoveEntitiesPacket(entity.getId())); this.viewers.remove(player.getUniqueId()); return true; @@ -236,8 +242,8 @@ public boolean hide(@NotNull final Player player) { @Override public void refresh(@NotNull final Player player) { - final var display = this.display; - if (display == null) { + final var entity = this.entity; + if (entity == null) { return; // doesn't exist, nothing to refresh } @@ -245,20 +251,19 @@ public void refresh(@NotNull final Player player) { return; } - ((CraftPlayer) player).getHandle().connection.send(new ClientboundTeleportEntityPacket(display)); + ((CraftPlayer) player).getHandle().connection.send(new ClientboundTeleportEntityPacket(entity)); - if (display instanceof TextDisplay textDisplay) { + if (entity instanceof TextDisplay textDisplay) { textDisplay.setText(PaperAdventure.asVanilla(getShownText(player))); } final var values = new ArrayList>(); - //noinspection unchecked - for (final var item : ((SynchedEntityData.DataItem[]) getValue(display.getEntityData(), "itemsById"))) { + for (final var item : ((SynchedEntityData.DataItem[]) getValue(entity.getEntityData(), "itemsById"))) { values.add(item.value()); } - ((CraftPlayer) player).getHandle().connection.send(new ClientboundSetEntityDataPacket(display.getId(), values)); + ((CraftPlayer) player).getHandle().connection.send(new ClientboundSetEntityDataPacket(entity.getId(), values)); } } diff --git a/src/main/java/de/oliver/fancyholograms/commands/HologramCMD.java b/src/main/java/de/oliver/fancyholograms/commands/HologramCMD.java index d741a6d0..fc5b9953 100644 --- a/src/main/java/de/oliver/fancyholograms/commands/HologramCMD.java +++ b/src/main/java/de/oliver/fancyholograms/commands/HologramCMD.java @@ -123,7 +123,7 @@ public boolean execute(@NotNull CommandSender sender, @NotNull String label, @No // /holo create {tab:type} if (args.length == 2 && args[0].equalsIgnoreCase("create")) { - return Arrays.asList("text", "item", "block"); + return Arrays.asList("text", "item", "block", "dropped_item"); } // /holo [action] {tab:hologram} diff --git a/src/main/java/de/oliver/fancyholograms/commands/hologram/CreateCMD.java b/src/main/java/de/oliver/fancyholograms/commands/hologram/CreateCMD.java index 917ff91e..9bd5a192 100644 --- a/src/main/java/de/oliver/fancyholograms/commands/hologram/CreateCMD.java +++ b/src/main/java/de/oliver/fancyholograms/commands/hologram/CreateCMD.java @@ -53,20 +53,17 @@ public boolean run(@NotNull CommandSender sender, @Nullable Hologram hologram, @ return false; } - DisplayHologramData displayData = null; + HologramData hologramData = null; switch (type) { - case TEXT -> displayData = new TextHologramData(name, player.getLocation()); - case ITEM -> { - displayData = new ItemHologramData(name, player.getLocation()); - displayData.setBillboard(Display.Billboard.FIXED); - } - case BLOCK -> { - displayData = new BlockHologramData(name, player.getLocation()); - displayData.setBillboard(Display.Billboard.FIXED); - } + case TEXT -> hologramData = new TextHologramData(name, player.getLocation()); + case ITEM -> hologramData = new ItemHologramData(name, player.getLocation()) + .setBillboard(Display.Billboard.FIXED); + case BLOCK -> hologramData = new BlockHologramData(name, player.getLocation()) + .setBillboard(Display.Billboard.FIXED); + case DROPPED_ITEM -> hologramData = new DroppedItemHologramData(name, player.getLocation()); } - final var holo = FancyHolograms.get().getHologramsManager().create(displayData); + final var holo = FancyHolograms.get().getHologramsManager().create(hologramData); if (!new HologramCreateEvent(holo, player).callEvent()) { MessageHelper.error(player, "Creating the hologram was cancelled"); return false; diff --git a/src/main/java/de/oliver/fancyholograms/commands/hologram/ItemCMD.java b/src/main/java/de/oliver/fancyholograms/commands/hologram/ItemCMD.java index e836d785..6b744827 100644 --- a/src/main/java/de/oliver/fancyholograms/commands/hologram/ItemCMD.java +++ b/src/main/java/de/oliver/fancyholograms/commands/hologram/ItemCMD.java @@ -1,6 +1,7 @@ package de.oliver.fancyholograms.commands.hologram; import de.oliver.fancyholograms.FancyHolograms; +import de.oliver.fancyholograms.api.data.DroppedItemHologramData; import de.oliver.fancyholograms.api.hologram.Hologram; import de.oliver.fancyholograms.api.data.ItemHologramData; import de.oliver.fancyholograms.api.events.HologramUpdateEvent; @@ -29,39 +30,61 @@ public boolean run(@NotNull CommandSender sender, @Nullable Hologram hologram, @ return false; } - if (!(hologram.getData() instanceof ItemHologramData itemData)) { - MessageHelper.error(player, "This command can only be used on item holograms"); - return false; - } - ItemStack item = player.getInventory().getItemInMainHand(); if (item.getType() == Material.AIR || item.getAmount() < 1) { MessageHelper.error(player, "You need to hold an item in your hand"); return false; } + if (hologram.getData() instanceof ItemHologramData itemData) { + if (item == itemData.getItemStack()) { + MessageHelper.warning(player, "This item is already set"); + return false; + } - if (item == itemData.getItemStack()) { - MessageHelper.warning(player, "This item is already set"); - return false; - } + final var copied = itemData.copy(itemData.getName()); + copied.setItemStack(item); - final var copied = itemData.copy(itemData.getName()); - copied.setItemStack(item); + if (!HologramCMD.callModificationEvent(hologram, player, copied, HologramUpdateEvent.HologramModification.BILLBOARD)) { + return false; + } - if (!HologramCMD.callModificationEvent(hologram, player, copied, HologramUpdateEvent.HologramModification.BILLBOARD)) { - return false; - } + if (copied.getItemStack() == itemData.getItemStack()) { + MessageHelper.warning(player, "This item is already set"); + return false; + } - if (copied.getItemStack() == itemData.getItemStack()) { - MessageHelper.warning(player, "This item is already set"); - return false; - } + itemData.setItemStack(item); + + if (FancyHolograms.get().getHologramConfiguration().isSaveOnChangedEnabled()) { + FancyHolograms.get().getHologramStorage().save(hologram); + } + } else if (hologram.getData() instanceof DroppedItemHologramData itemData) { + if (item == itemData.getItemStack()) { + MessageHelper.warning(player, "This item is already set"); + return false; + } + + final var copied = itemData.copy(itemData.getName()); + copied.setItemStack(item); - itemData.setItemStack(item); + if (!HologramCMD.callModificationEvent(hologram, player, copied, HologramUpdateEvent.HologramModification.BILLBOARD)) { + return false; + } - if (FancyHolograms.get().getHologramConfiguration().isSaveOnChangedEnabled()) { - FancyHolograms.get().getHologramStorage().save(hologram); + if (copied.getItemStack() == itemData.getItemStack()) { + MessageHelper.warning(player, "This item is already set"); + return false; + } + + itemData.setItemStack(item); + + if (FancyHolograms.get().getHologramConfiguration().isSaveOnChangedEnabled()) { + FancyHolograms.get().getHologramStorage().save(hologram); + } + } else { + MessageHelper.error(player, "This command can only be used on item holograms"); + return false; } MessageHelper.success(player, "Set the item to '" + item.getType().name() + "'"); diff --git a/src/main/java/de/oliver/fancyholograms/storage/FlatFileHologramStorage.java b/src/main/java/de/oliver/fancyholograms/storage/FlatFileHologramStorage.java index 14e52653..c7581368 100644 --- a/src/main/java/de/oliver/fancyholograms/storage/FlatFileHologramStorage.java +++ b/src/main/java/de/oliver/fancyholograms/storage/FlatFileHologramStorage.java @@ -155,15 +155,22 @@ private List readHolograms(File configFile) { continue; } - DisplayHologramData displayData = null; + HologramData hologramData; switch (type) { - case TEXT -> displayData = new TextHologramData(name, new Location(null, 0, 0, 0)); - case ITEM -> displayData = new ItemHologramData(name, new Location(null, 0, 0, 0)); - case BLOCK -> displayData = new BlockHologramData(name, new Location(null, 0, 0, 0)); + case TEXT -> hologramData = new TextHologramData(name, new Location(null, 0, 0, 0)); + case ITEM -> hologramData = new ItemHologramData(name, new Location(null, 0, 0, 0)); + case BLOCK -> hologramData = new BlockHologramData(name, new Location(null, 0, 0, 0)); + case DROPPED_ITEM -> hologramData = new DroppedItemHologramData(name, new Location(null, 0, 0, 0)); + default -> hologramData = null; } - displayData.read(holoSection, name); - Hologram hologram = FancyHolograms.get().getHologramManager().create(displayData); + if (hologramData == null) { + continue; + } + + hologramData.read(holoSection, name); + + Hologram hologram = FancyHolograms.get().getHologramManager().create(hologramData); holograms.add(hologram); }