diff --git a/api/src/main/java/net/jitse/npclib/hologram/HologramBase.java b/api/src/main/java/net/jitse/npclib/hologram/HologramBase.java index 9830668..0863dbf 100644 --- a/api/src/main/java/net/jitse/npclib/hologram/HologramBase.java +++ b/api/src/main/java/net/jitse/npclib/hologram/HologramBase.java @@ -1,6 +1,5 @@ package net.jitse.npclib.hologram; -import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.entity.Player; @@ -56,31 +55,4 @@ public abstract class HologramBase implements Hologram, HologramPacketHandler { this.shown.remove(uuid); } - - @Override - public void updateText(List text) { - if (this.text.size() != text.size()) - throw new IllegalArgumentException("When updating the text, the old and new text should have the same amount of lines"); - - for (int i = 0; i < text.size(); i++) { - String oldLine = this.text.get(i); - String newLine = text.get(i); - - if (oldLine.equals(newLine)) - continue; // No need to update. - - // Perhaps this should return an object so we can send all immediately to the shown players. - createTextUpdatePacket(oldLine, newLine); - } - - for (UUID uuid : shown) { - Player player = Bukkit.getPlayer(uuid); - if (player == null || !player.isOnline()) { - throw new IllegalStateException("Tried to update hologram for offline player"); - } - -// sendTextUpdatePackets(player, ); - } - this.text = text; - } } diff --git a/api/src/main/java/net/jitse/npclib/hologram/HologramPacketHandler.java b/api/src/main/java/net/jitse/npclib/hologram/HologramPacketHandler.java index b7d149a..5ec3216 100644 --- a/api/src/main/java/net/jitse/npclib/hologram/HologramPacketHandler.java +++ b/api/src/main/java/net/jitse/npclib/hologram/HologramPacketHandler.java @@ -9,8 +9,4 @@ public interface HologramPacketHandler { void sendShowPackets(Player player); void sendHidePackets(Player player); - - void createTextUpdatePacket(String oldLine, String newLine); - - void sendTextUpdatePackets(Player player); } diff --git a/api/src/main/java/net/jitse/npclib/internal/NPCBase.java b/api/src/main/java/net/jitse/npclib/internal/NPCBase.java index c4c79ab..1511e02 100644 --- a/api/src/main/java/net/jitse/npclib/internal/NPCBase.java +++ b/api/src/main/java/net/jitse/npclib/internal/NPCBase.java @@ -13,6 +13,7 @@ import net.jitse.npclib.api.events.NPCShowEvent; import net.jitse.npclib.api.skin.Skin; import net.jitse.npclib.api.state.NPCSlot; import net.jitse.npclib.api.state.NPCState; +import net.jitse.npclib.hologram.Hologram; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.World; @@ -39,6 +40,7 @@ public abstract class NPCBase implements NPC, NPCPacketHandler { protected List text; protected Location location; protected Skin skin; + protected Hologram hologram; // offHand support in 1.9 R1 and later. protected ItemStack helmet, chestplate, leggings, boots, inHand, offHand; @@ -304,7 +306,7 @@ public abstract class NPCBase implements NPC, NPCPacketHandler { for (UUID shownUuid : shown) { Player player = Bukkit.getPlayer(shownUuid); if (player != null && isShown(player)) { - sendTextUpdatePackets(this.text, text, player); + hologram.updateText(text); } } this.text = text; diff --git a/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/NPC_v1_8_R1.java b/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/NPC_v1_8_R1.java index a3da078..eb552a2 100755 --- a/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/NPC_v1_8_R1.java +++ b/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/NPC_v1_8_R1.java @@ -6,7 +6,6 @@ package net.jitse.npclib.nms.v1_8_R1; import net.jitse.npclib.NPCLib; import net.jitse.npclib.api.state.NPCSlot; -import net.jitse.npclib.hologram.Hologram; import net.jitse.npclib.internal.NPCBase; import net.jitse.npclib.nms.v1_8_R1.hologram.Hologram_v1_8_R1; import net.jitse.npclib.nms.v1_8_R1.packets.*; @@ -27,7 +26,6 @@ import java.util.UUID; */ public class NPC_v1_8_R1 extends NPCBase { - private Hologram hologram; private PacketPlayOutNamedEntitySpawn packetPlayOutNamedEntitySpawn; private PacketPlayOutScoreboardTeam packetPlayOutScoreboardTeamRegister; private PacketPlayOutPlayerInfo packetPlayOutPlayerInfoAdd, packetPlayOutPlayerInfoRemove; diff --git a/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/hologram/Hologram_v1_8_R1.java b/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/hologram/Hologram_v1_8_R1.java index 8758314..f05387c 100644 --- a/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/hologram/Hologram_v1_8_R1.java +++ b/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/hologram/Hologram_v1_8_R1.java @@ -1,21 +1,23 @@ package net.jitse.npclib.nms.v1_8_R1.hologram; import net.jitse.npclib.hologram.HologramBase; -import net.minecraft.server.v1_8_R1.EntityArmorStand; -import net.minecraft.server.v1_8_R1.PacketPlayOutEntityDestroy; -import net.minecraft.server.v1_8_R1.PacketPlayOutSpawnEntityLiving; +import net.minecraft.server.v1_8_R1.*; +import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.craftbukkit.v1_8_R1.CraftWorld; +import org.bukkit.craftbukkit.v1_8_R1.entity.CraftPlayer; import org.bukkit.entity.Player; +import java.util.ArrayList; import java.util.List; +import java.util.UUID; public class Hologram_v1_8_R1 extends HologramBase { - // Perhaps all logic methods should be placed in the base class instead then - // use a similar approach to the NPCBase class, with a HologramPacketHandler class... - // That way I can't mess up logic on different version whilst implementing new features. - // *cough cough* hologram text updates. I can already see this go wrong. + private List nmsArmorStands; + private List showPackets; + private List hidePackets; + public Hologram_v1_8_R1(Location start, List text) { super(start, text); } @@ -24,15 +26,14 @@ public class Hologram_v1_8_R1 extends HologramBase { public void createPackets() { Location top = start.clone().add(0, DELTA * text.size(), 0); - for (String line : text) { - if (line.isEmpty()) { - top.subtract(0, DELTA, 0); - continue; - } + List nmsArmorStands = new ArrayList<>(); + List showPackets = new ArrayList<>(); + List hidePackets = new ArrayList<>(); + for (String line : text) { EntityArmorStand armorStand = new EntityArmorStand(((CraftWorld) top.getWorld()).getHandle()); armorStand.setLocation(top.getX(), top.getY(), top.getZ(), 0, 0); - armorStand.setCustomName(line); // Does this method update? Or should teams be used? + armorStand.setCustomName(line); armorStand.setCustomNameVisible(true); armorStand.setGravity(false); armorStand.setSmall(true); @@ -40,43 +41,82 @@ public class Hologram_v1_8_R1 extends HologramBase { armorStand.setBasePlate(false); armorStand.setArms(false); + nmsArmorStands.add(armorStand); + PacketPlayOutSpawnEntityLiving lineShowPacket = new PacketPlayOutSpawnEntityLiving(armorStand); PacketPlayOutEntityDestroy lineHidePacket = new PacketPlayOutEntityDestroy(armorStand.getId()); - // TODO: Add packets and ArmorStand object to some sort of manager. + + showPackets.add(lineShowPacket); + hidePackets.add(lineHidePacket); top.subtract(0, DELTA, 0); } + + this.nmsArmorStands = nmsArmorStands; + this.showPackets = showPackets; + this.hidePackets = hidePackets; } @Override public void sendShowPackets(Player player) { - + PlayerConnection connection = ((CraftPlayer) player).getHandle().playerConnection; + for (int i = 0; i < text.size(); i++) { + if (text.get(i).isEmpty()) continue; // No need to spawn the line. + connection.sendPacket(showPackets.get(i)); + } } @Override public void sendHidePackets(Player player) { - + PlayerConnection connection = ((CraftPlayer) player).getHandle().playerConnection; + for (int i = 0; i < text.size(); i++) { + if (text.get(i).isEmpty()) continue; // No need to hide the line (as it was never spawned). + connection.sendPacket(hidePackets.get(i)); + } } @Override - public void createTextUpdatePacket(String oldLine, String newLine) { + public void updateText(List text) { + List toSend = new ArrayList<>(); - } + if (this.text.size() != text.size()) + throw new IllegalArgumentException("When updating the text, the old and new text should have the same amount of lines"); - @Override - public void sendTextUpdatePackets(Player player) { + for (int i = 0; i < text.size(); i++) { + EntityArmorStand armorStand = nmsArmorStands.get(i); + String oldLine = this.text.get(i); + String newLine = text.get(i); - } + armorStand.getDataWatcher().watch(2, newLine); // Update the DataWatcher object. - @Override - public void sendTextUpdatePackets(Player player, int index, String newLine) { - if (newLine.isEmpty()) { - // Check if line was empty before, if not, remove the hologram line. - } else { - // Check if line was empty before, if it was, create the hologram line. - // If the line was not empty before and it isn't now, update its text. + if (oldLine.equals(newLine)) { + continue; // No need to update. + } else if (newLine.isEmpty() && !oldLine.isEmpty()) { + // Check if line was empty before, if not, remove the hologram line. + toSend.add(hidePackets.get(i)); + } else if (!newLine.isEmpty() && oldLine.isEmpty()) { + // Check if line was empty before, if it was, create the hologram line. + PacketPlayOutSpawnEntityLiving lineShowPacket = new PacketPlayOutSpawnEntityLiving(armorStand); + toSend.add(lineShowPacket); + } else { + // If the line was not empty before and it isn't now, update its text. + PacketPlayOutEntityMetadata metadataPacket = new PacketPlayOutEntityMetadata(armorStand.getId(), armorStand.getDataWatcher(), true); + toSend.add(metadataPacket); + } } - // Send the packets to all players that can see the hologram (i.e. shown set). + for (UUID uuid : shown) { + Player player = Bukkit.getPlayer(uuid); + if (player == null || !player.isOnline()) { + throw new IllegalStateException("Tried to update hologram for offline player"); + } + + PlayerConnection connection = ((CraftPlayer) player).getHandle().playerConnection; + for (Packet packet : toSend) { + connection.sendPacket(packet); + } + } + + this.text = text; // At last, update the text in this hologram object. } }