From 30de267f1e1bca7e5846c7b6969507a21b1d4ca7 Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 19 Mar 2020 13:24:29 +0100 Subject: [PATCH] Add NMS hologram line implementations --- nms/pom.xml | 4 +- nms/v10r1/pom.xml | 34 ++++ .../shopchest/shop/hologram/HologramLine.java | 182 +++++++++++++++++ nms/v11r1/pom.xml | 34 ++++ .../shopchest/shop/hologram/HologramLine.java | 182 +++++++++++++++++ nms/v12r1/pom.xml | 34 ++++ .../shopchest/shop/hologram/HologramLine.java | 182 +++++++++++++++++ nms/v13r1/pom.xml | 34 ++++ .../shopchest/shop/hologram/HologramLine.java | 183 +++++++++++++++++ nms/v13r2/pom.xml | 34 ++++ .../shopchest/shop/hologram/HologramLine.java | 183 +++++++++++++++++ nms/v14r1/pom.xml | 34 ++++ .../shopchest/shop/hologram/HologramLine.java | 185 ++++++++++++++++++ .../shopchest/shop/hologram/HologramLine.java | 43 +++- .../shopchest/shop/hologram/HologramLine.java | 18 +- nms/v8r2/pom.xml | 34 ++++ .../shopchest/shop/hologram/HologramLine.java | 121 ++++++++++++ nms/v8r3/pom.xml | 34 ++++ .../shopchest/shop/hologram/HologramLine.java | 121 ++++++++++++ nms/v9r1/pom.xml | 34 ++++ .../shopchest/shop/hologram/HologramLine.java | 179 +++++++++++++++++ nms/v9r2/pom.xml | 34 ++++ .../shopchest/shop/hologram/HologramLine.java | 179 +++++++++++++++++ 23 files changed, 2081 insertions(+), 21 deletions(-) create mode 100644 nms/v10r1/pom.xml create mode 100644 nms/v10r1/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java create mode 100644 nms/v11r1/pom.xml create mode 100644 nms/v11r1/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java create mode 100644 nms/v12r1/pom.xml create mode 100644 nms/v12r1/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java create mode 100644 nms/v13r1/pom.xml create mode 100644 nms/v13r1/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java create mode 100644 nms/v13r2/pom.xml create mode 100644 nms/v13r2/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java create mode 100644 nms/v14r1/pom.xml create mode 100644 nms/v14r1/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java create mode 100644 nms/v8r2/pom.xml create mode 100644 nms/v8r2/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java create mode 100644 nms/v8r3/pom.xml create mode 100644 nms/v8r3/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java create mode 100644 nms/v9r1/pom.xml create mode 100644 nms/v9r1/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java create mode 100644 nms/v9r2/pom.xml create mode 100644 nms/v9r2/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java diff --git a/nms/pom.xml b/nms/pom.xml index 2ff285b..8e34d13 100644 --- a/nms/pom.xml +++ b/nms/pom.xml @@ -12,7 +12,7 @@ interfaces v8r1 - + v14r1 v15r1 diff --git a/nms/v10r1/pom.xml b/nms/v10r1/pom.xml new file mode 100644 index 0000000..0fb2a02 --- /dev/null +++ b/nms/v10r1/pom.xml @@ -0,0 +1,34 @@ + + + 4.0.0 + + de.epiceric.shopchest + shopchest-nms-v10r1 + 1.13-SNAPSHOT + + ShopChest NMS v1.10-R1 + + + de.epiceric.shopchest + shopchest-nms + 1.13-SNAPSHOT + + + + + de.epiceric.shopchest + shopchest-nms-interfaces + 1.13-SNAPSHOT + provided + + + + org.bukkit + craftbukkit + 1.10-R0.1-SNAPSHOT + provided + + + diff --git a/nms/v10r1/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java b/nms/v10r1/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java new file mode 100644 index 0000000..f3ee1fe --- /dev/null +++ b/nms/v10r1/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java @@ -0,0 +1,182 @@ +package de.epiceric.shopchest.shop.hologram; + +import java.io.IOException; +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.Optional; +import java.util.UUID; + +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_10_R1.entity.CraftPlayer; +import org.bukkit.entity.Player; + +import io.netty.buffer.Unpooled; +import net.minecraft.server.v1_10_R1.DataWatcher; +import net.minecraft.server.v1_10_R1.DataWatcherObject; +import net.minecraft.server.v1_10_R1.Entity; +import net.minecraft.server.v1_10_R1.EntityArmorStand; +import net.minecraft.server.v1_10_R1.IChatBaseComponent; +import net.minecraft.server.v1_10_R1.Packet; +import net.minecraft.server.v1_10_R1.PacketDataSerializer; +import net.minecraft.server.v1_10_R1.PacketPlayOutEntityDestroy; +import net.minecraft.server.v1_10_R1.PacketPlayOutEntityMetadata; +import net.minecraft.server.v1_10_R1.PacketPlayOutEntityTeleport; +import net.minecraft.server.v1_10_R1.PacketPlayOutSpawnEntity; +import net.minecraft.server.v1_10_R1.PlayerConnection; + +public class HologramLine implements IHologramLine { + private PacketPlayOutSpawnEntity spawnPacket; + private DataWatcher dataWatcher; + + private DataWatcherObject nameVisible; + private DataWatcherObject> customName; + + private int id; + private Location location; + private String text; + + public HologramLine(Location location, String text) { + this.id = 5; + this.location = location.clone(); + this.text = text; + + this.spawnPacket = new PacketPlayOutSpawnEntity(); + this.dataWatcher = createDataWatcher(); + + updatePacket(); + } + + @Override + public void setLocation(Location location) { + this.location = location.clone(); + updatePacket(); + + PacketPlayOutEntityTeleport packet = createTeleportPacket(); + location.getWorld().getPlayers().forEach(player -> sendPackets(player, packet)); + } + + @Override + public void setText(String text) { + this.text = text; + + dataWatcher.register(nameVisible, !text.isEmpty()); + dataWatcher.register(customName, text); + + Packet metadataPacket = new PacketPlayOutEntityMetadata(id, dataWatcher, true); + location.getWorld().getPlayers().forEach(player -> sendPackets(player, metadataPacket)); + } + + @Override + public void showPlayer(Player player) { + if (player == null || !player.isOnline()) { + return; + } + + sendPackets(player, spawnPacket, new PacketPlayOutEntityMetadata(id, dataWatcher, true)); + } + + @Override + public void hidePlayer(Player player) { + if (player == null || !player.isOnline()) { + return; + } + + sendPackets(player, new PacketPlayOutEntityDestroy(id)); + } + + @Override + public void destroy() { + location.getWorld().getPlayers().forEach(player -> hidePlayer(player)); + } + + private void sendPackets(Player player, Packet... packets) { + PlayerConnection con = ((CraftPlayer) player).getHandle().playerConnection; + Arrays.stream(packets).forEach(packet -> con.sendPacket(packet)); + } + + private PacketPlayOutEntityTeleport createTeleportPacket() { + PacketDataSerializer s = new PacketDataSerializer(Unpooled.buffer()); + s.d(id); // id + s.writeDouble(location.getX()); // x + s.writeDouble(location.getY() + 1.975); // y + s.writeDouble(location.getZ()); // z + s.writeByte(0); // yaw + s.writeByte(0); // pitch + s.writeBoolean(true); // on ground + + try { + PacketPlayOutEntityTeleport packet = new PacketPlayOutEntityTeleport(); + packet.a(s); + return packet; + } catch (IOException e) { + e.printStackTrace(); + } finally { + s.release(); + } + + return null; + } + + private void updatePacket() { + PacketDataSerializer s = new PacketDataSerializer(Unpooled.buffer()); + s.d(id); // id + s.a(UUID.randomUUID()); // uuid + s.writeByte(78); // type + s.writeDouble(location.getX()); // x + s.writeDouble(location.getY() + 1.975); // y + s.writeDouble(location.getZ()); // z + s.writeByte(0); // pitch + s.writeByte(0); // yaw + s.writeInt(0); // ? + s.writeShort(0); // mot x + s.writeShort(0); // mot y + s.writeShort(0); // mot z + + try { + spawnPacket.a(s); + } catch (IOException e) { + e.printStackTrace(); + } finally { + s.release(); + } + } + + @SuppressWarnings("unchecked") + private DataWatcher createDataWatcher() { + try { + Field fEntityFlags = Entity.class.getDeclaredField("aa"); + Field fAirTicks = Entity.class.getDeclaredField("az"); + Field fNameVisible = Entity.class.getDeclaredField("aB"); + Field fCustomName = Entity.class.getDeclaredField("aA"); + Field fNoGravity = Entity.class.getDeclaredField("aD"); + + setAccessible(fEntityFlags, fAirTicks, fNameVisible, fCustomName, fNoGravity); + + nameVisible = (DataWatcherObject) fNameVisible.get(null); + customName = (DataWatcherObject>) fCustomName.get(null); + DataWatcherObject entityFlags = (DataWatcherObject) fEntityFlags.get(null); + DataWatcherObject airTicks = (DataWatcherObject) fAirTicks.get(null); + DataWatcherObject noGravity = (DataWatcherObject) fNoGravity.get(null); + DataWatcherObject armorStandFlags = EntityArmorStand.a; + + DataWatcher dataWatcher = new DataWatcher(null); + dataWatcher.register(entityFlags, (byte) 0b100000); + dataWatcher.register(airTicks, 300); + dataWatcher.register(nameVisible, !text.isEmpty()); + dataWatcher.register(customName, text); + dataWatcher.register(noGravity, true); + dataWatcher.register(armorStandFlags, (byte) 0b10000); + + return dataWatcher; + } catch (ReflectiveOperationException e) { + e.printStackTrace(); + } + + return null; + } + + private void setAccessible(AccessibleObject... args) { + Arrays.stream(args).forEach(arg -> arg.setAccessible(true)); + } +} \ No newline at end of file diff --git a/nms/v11r1/pom.xml b/nms/v11r1/pom.xml new file mode 100644 index 0000000..a7f81e6 --- /dev/null +++ b/nms/v11r1/pom.xml @@ -0,0 +1,34 @@ + + + 4.0.0 + + de.epiceric.shopchest + shopchest-nms-v11r1 + 1.13-SNAPSHOT + + ShopChest NMS v1.11-R1 + + + de.epiceric.shopchest + shopchest-nms + 1.13-SNAPSHOT + + + + + de.epiceric.shopchest + shopchest-nms-interfaces + 1.13-SNAPSHOT + provided + + + + org.bukkit + craftbukkit + 1.11.2-R0.1-SNAPSHOT + provided + + + diff --git a/nms/v11r1/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java b/nms/v11r1/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java new file mode 100644 index 0000000..e51b159 --- /dev/null +++ b/nms/v11r1/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java @@ -0,0 +1,182 @@ +package de.epiceric.shopchest.shop.hologram; + +import java.io.IOException; +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.Optional; +import java.util.UUID; + +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_11_R1.entity.CraftPlayer; +import org.bukkit.entity.Player; + +import io.netty.buffer.Unpooled; +import net.minecraft.server.v1_11_R1.DataWatcher; +import net.minecraft.server.v1_11_R1.DataWatcherObject; +import net.minecraft.server.v1_11_R1.Entity; +import net.minecraft.server.v1_11_R1.EntityArmorStand; +import net.minecraft.server.v1_11_R1.IChatBaseComponent; +import net.minecraft.server.v1_11_R1.Packet; +import net.minecraft.server.v1_11_R1.PacketDataSerializer; +import net.minecraft.server.v1_11_R1.PacketPlayOutEntityDestroy; +import net.minecraft.server.v1_11_R1.PacketPlayOutEntityMetadata; +import net.minecraft.server.v1_11_R1.PacketPlayOutEntityTeleport; +import net.minecraft.server.v1_11_R1.PacketPlayOutSpawnEntity; +import net.minecraft.server.v1_11_R1.PlayerConnection; + +public class HologramLine implements IHologramLine { + private PacketPlayOutSpawnEntity spawnPacket; + private DataWatcher dataWatcher; + + private DataWatcherObject nameVisible; + private DataWatcherObject> customName; + + private int id; + private Location location; + private String text; + + public HologramLine(Location location, String text) { + this.id = 5; + this.location = location.clone(); + this.text = text; + + this.spawnPacket = new PacketPlayOutSpawnEntity(); + this.dataWatcher = createDataWatcher(); + + updatePacket(); + } + + @Override + public void setLocation(Location location) { + this.location = location.clone(); + updatePacket(); + + PacketPlayOutEntityTeleport packet = createTeleportPacket(); + location.getWorld().getPlayers().forEach(player -> sendPackets(player, packet)); + } + + @Override + public void setText(String text) { + this.text = text; + + dataWatcher.register(nameVisible, !text.isEmpty()); + dataWatcher.register(customName, text); + + Packet metadataPacket = new PacketPlayOutEntityMetadata(id, dataWatcher, true); + location.getWorld().getPlayers().forEach(player -> sendPackets(player, metadataPacket)); + } + + @Override + public void showPlayer(Player player) { + if (player == null || !player.isOnline()) { + return; + } + + sendPackets(player, spawnPacket, new PacketPlayOutEntityMetadata(id, dataWatcher, true)); + } + + @Override + public void hidePlayer(Player player) { + if (player == null || !player.isOnline()) { + return; + } + + sendPackets(player, new PacketPlayOutEntityDestroy(id)); + } + + @Override + public void destroy() { + location.getWorld().getPlayers().forEach(player -> hidePlayer(player)); + } + + private void sendPackets(Player player, Packet... packets) { + PlayerConnection con = ((CraftPlayer) player).getHandle().playerConnection; + Arrays.stream(packets).forEach(packet -> con.sendPacket(packet)); + } + + private PacketPlayOutEntityTeleport createTeleportPacket() { + PacketDataSerializer s = new PacketDataSerializer(Unpooled.buffer()); + s.d(id); // id + s.writeDouble(location.getX()); // x + s.writeDouble(location.getY() + 1.975); // y + s.writeDouble(location.getZ()); // z + s.writeByte(0); // yaw + s.writeByte(0); // pitch + s.writeBoolean(true); // on ground + + try { + PacketPlayOutEntityTeleport packet = new PacketPlayOutEntityTeleport(); + packet.a(s); + return packet; + } catch (IOException e) { + e.printStackTrace(); + } finally { + s.release(); + } + + return null; + } + + private void updatePacket() { + PacketDataSerializer s = new PacketDataSerializer(Unpooled.buffer()); + s.d(id); // id + s.a(UUID.randomUUID()); // uuid + s.writeByte(78); // type + s.writeDouble(location.getX()); // x + s.writeDouble(location.getY() + 1.975); // y + s.writeDouble(location.getZ()); // z + s.writeByte(0); // pitch + s.writeByte(0); // yaw + s.writeInt(0); // ? + s.writeShort(0); // mot x + s.writeShort(0); // mot y + s.writeShort(0); // mot z + + try { + spawnPacket.a(s); + } catch (IOException e) { + e.printStackTrace(); + } finally { + s.release(); + } + } + + @SuppressWarnings("unchecked") + private DataWatcher createDataWatcher() { + try { + Field fEntityFlags = Entity.class.getDeclaredField("Z"); + Field fAirTicks = Entity.class.getDeclaredField("az"); + Field fNameVisible = Entity.class.getDeclaredField("aB"); + Field fCustomName = Entity.class.getDeclaredField("aA"); + Field fNoGravity = Entity.class.getDeclaredField("aD"); + + setAccessible(fEntityFlags, fAirTicks, fNameVisible, fCustomName, fNoGravity); + + nameVisible = (DataWatcherObject) fNameVisible.get(null); + customName = (DataWatcherObject>) fCustomName.get(null); + DataWatcherObject entityFlags = (DataWatcherObject) fEntityFlags.get(null); + DataWatcherObject airTicks = (DataWatcherObject) fAirTicks.get(null); + DataWatcherObject noGravity = (DataWatcherObject) fNoGravity.get(null); + DataWatcherObject armorStandFlags = EntityArmorStand.a; + + DataWatcher dataWatcher = new DataWatcher(null); + dataWatcher.register(entityFlags, (byte) 0b100000); + dataWatcher.register(airTicks, 300); + dataWatcher.register(nameVisible, !text.isEmpty()); + dataWatcher.register(customName, text); + dataWatcher.register(noGravity, true); + dataWatcher.register(armorStandFlags, (byte) 0b10000); + + return dataWatcher; + } catch (ReflectiveOperationException e) { + e.printStackTrace(); + } + + return null; + } + + private void setAccessible(AccessibleObject... args) { + Arrays.stream(args).forEach(arg -> arg.setAccessible(true)); + } +} \ No newline at end of file diff --git a/nms/v12r1/pom.xml b/nms/v12r1/pom.xml new file mode 100644 index 0000000..d75be83 --- /dev/null +++ b/nms/v12r1/pom.xml @@ -0,0 +1,34 @@ + + + 4.0.0 + + de.epiceric.shopchest + shopchest-nms-v12r1 + 1.13-SNAPSHOT + + ShopChest NMS v1.12-R1 + + + de.epiceric.shopchest + shopchest-nms + 1.13-SNAPSHOT + + + + + de.epiceric.shopchest + shopchest-nms-interfaces + 1.13-SNAPSHOT + provided + + + + org.bukkit + craftbukkit + 1.12.2-R0.1-SNAPSHOT + provided + + + diff --git a/nms/v12r1/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java b/nms/v12r1/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java new file mode 100644 index 0000000..81ae113 --- /dev/null +++ b/nms/v12r1/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java @@ -0,0 +1,182 @@ +package de.epiceric.shopchest.shop.hologram; + +import java.io.IOException; +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.Optional; +import java.util.UUID; + +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer; +import org.bukkit.entity.Player; + +import io.netty.buffer.Unpooled; +import net.minecraft.server.v1_12_R1.DataWatcher; +import net.minecraft.server.v1_12_R1.DataWatcherObject; +import net.minecraft.server.v1_12_R1.Entity; +import net.minecraft.server.v1_12_R1.EntityArmorStand; +import net.minecraft.server.v1_12_R1.IChatBaseComponent; +import net.minecraft.server.v1_12_R1.Packet; +import net.minecraft.server.v1_12_R1.PacketDataSerializer; +import net.minecraft.server.v1_12_R1.PacketPlayOutEntityDestroy; +import net.minecraft.server.v1_12_R1.PacketPlayOutEntityMetadata; +import net.minecraft.server.v1_12_R1.PacketPlayOutEntityTeleport; +import net.minecraft.server.v1_12_R1.PacketPlayOutSpawnEntity; +import net.minecraft.server.v1_12_R1.PlayerConnection; + +public class HologramLine implements IHologramLine { + private PacketPlayOutSpawnEntity spawnPacket; + private DataWatcher dataWatcher; + + private DataWatcherObject nameVisible; + private DataWatcherObject> customName; + + private int id; + private Location location; + private String text; + + public HologramLine(Location location, String text) { + this.id = 5; + this.location = location.clone(); + this.text = text; + + this.spawnPacket = new PacketPlayOutSpawnEntity(); + this.dataWatcher = createDataWatcher(); + + updatePacket(); + } + + @Override + public void setLocation(Location location) { + this.location = location.clone(); + updatePacket(); + + PacketPlayOutEntityTeleport packet = createTeleportPacket(); + location.getWorld().getPlayers().forEach(player -> sendPackets(player, packet)); + } + + @Override + public void setText(String text) { + this.text = text; + + dataWatcher.register(nameVisible, !text.isEmpty()); + dataWatcher.register(customName, text); + + Packet metadataPacket = new PacketPlayOutEntityMetadata(id, dataWatcher, true); + location.getWorld().getPlayers().forEach(player -> sendPackets(player, metadataPacket)); + } + + @Override + public void showPlayer(Player player) { + if (player == null || !player.isOnline()) { + return; + } + + sendPackets(player, spawnPacket, new PacketPlayOutEntityMetadata(id, dataWatcher, true)); + } + + @Override + public void hidePlayer(Player player) { + if (player == null || !player.isOnline()) { + return; + } + + sendPackets(player, new PacketPlayOutEntityDestroy(id)); + } + + @Override + public void destroy() { + location.getWorld().getPlayers().forEach(player -> hidePlayer(player)); + } + + private void sendPackets(Player player, Packet... packets) { + PlayerConnection con = ((CraftPlayer) player).getHandle().playerConnection; + Arrays.stream(packets).forEach(packet -> con.sendPacket(packet)); + } + + private PacketPlayOutEntityTeleport createTeleportPacket() { + PacketDataSerializer s = new PacketDataSerializer(Unpooled.buffer()); + s.d(id); // id + s.writeDouble(location.getX()); // x + s.writeDouble(location.getY() + 1.975); // y + s.writeDouble(location.getZ()); // z + s.writeByte(0); // yaw + s.writeByte(0); // pitch + s.writeBoolean(true); // on ground + + try { + PacketPlayOutEntityTeleport packet = new PacketPlayOutEntityTeleport(); + packet.a(s); + return packet; + } catch (IOException e) { + e.printStackTrace(); + } finally { + s.release(); + } + + return null; + } + + private void updatePacket() { + PacketDataSerializer s = new PacketDataSerializer(Unpooled.buffer()); + s.d(id); // id + s.a(UUID.randomUUID()); // uuid + s.writeByte(78); // type + s.writeDouble(location.getX()); // x + s.writeDouble(location.getY() + 1.975); // y + s.writeDouble(location.getZ()); // z + s.writeByte(0); // pitch + s.writeByte(0); // yaw + s.writeInt(0); // ? + s.writeShort(0); // mot x + s.writeShort(0); // mot y + s.writeShort(0); // mot z + + try { + spawnPacket.a(s); + } catch (IOException e) { + e.printStackTrace(); + } finally { + s.release(); + } + } + + @SuppressWarnings("unchecked") + private DataWatcher createDataWatcher() { + try { + Field fEntityFlags = Entity.class.getDeclaredField("Z"); + Field fAirTicks = Entity.class.getDeclaredField("aA"); + Field fNameVisible = Entity.class.getDeclaredField("aC"); + Field fCustomName = Entity.class.getDeclaredField("aB"); + Field fNoGravity = Entity.class.getDeclaredField("aE"); + + setAccessible(fEntityFlags, fAirTicks, fNameVisible, fCustomName, fNoGravity); + + nameVisible = (DataWatcherObject) fNameVisible.get(null); + customName = (DataWatcherObject>) fCustomName.get(null); + DataWatcherObject entityFlags = (DataWatcherObject) fEntityFlags.get(null); + DataWatcherObject airTicks = (DataWatcherObject) fAirTicks.get(null); + DataWatcherObject noGravity = (DataWatcherObject) fNoGravity.get(null); + DataWatcherObject armorStandFlags = EntityArmorStand.a; + + DataWatcher dataWatcher = new DataWatcher(null); + dataWatcher.register(entityFlags, (byte) 0b100000); + dataWatcher.register(airTicks, 300); + dataWatcher.register(nameVisible, !text.isEmpty()); + dataWatcher.register(customName, text); + dataWatcher.register(noGravity, true); + dataWatcher.register(armorStandFlags, (byte) 0b10000); + + return dataWatcher; + } catch (ReflectiveOperationException e) { + e.printStackTrace(); + } + + return null; + } + + private void setAccessible(AccessibleObject... args) { + Arrays.stream(args).forEach(arg -> arg.setAccessible(true)); + } +} \ No newline at end of file diff --git a/nms/v13r1/pom.xml b/nms/v13r1/pom.xml new file mode 100644 index 0000000..ddbd71f --- /dev/null +++ b/nms/v13r1/pom.xml @@ -0,0 +1,34 @@ + + + 4.0.0 + + de.epiceric.shopchest + shopchest-nms-v13r1 + 1.13-SNAPSHOT + + ShopChest NMS v1.13-R1 + + + de.epiceric.shopchest + shopchest-nms + 1.13-SNAPSHOT + + + + + de.epiceric.shopchest + shopchest-nms-interfaces + 1.13-SNAPSHOT + provided + + + + org.bukkit + craftbukkit + 1.13-R0.1-SNAPSHOT + provided + + + diff --git a/nms/v13r1/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java b/nms/v13r1/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java new file mode 100644 index 0000000..270c971 --- /dev/null +++ b/nms/v13r1/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java @@ -0,0 +1,183 @@ +package de.epiceric.shopchest.shop.hologram; + +import java.io.IOException; +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.Optional; +import java.util.UUID; + +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_13_R1.entity.CraftPlayer; +import org.bukkit.entity.Player; + +import io.netty.buffer.Unpooled; +import net.minecraft.server.v1_13_R1.DataWatcher; +import net.minecraft.server.v1_13_R1.DataWatcherObject; +import net.minecraft.server.v1_13_R1.Entity; +import net.minecraft.server.v1_13_R1.EntityArmorStand; +import net.minecraft.server.v1_13_R1.IChatBaseComponent; +import net.minecraft.server.v1_13_R1.Packet; +import net.minecraft.server.v1_13_R1.PacketDataSerializer; +import net.minecraft.server.v1_13_R1.PacketPlayOutEntityDestroy; +import net.minecraft.server.v1_13_R1.PacketPlayOutEntityMetadata; +import net.minecraft.server.v1_13_R1.PacketPlayOutEntityTeleport; +import net.minecraft.server.v1_13_R1.PacketPlayOutSpawnEntity; +import net.minecraft.server.v1_13_R1.PlayerConnection; +import net.minecraft.server.v1_13_R1.IChatBaseComponent.ChatSerializer; + +public class HologramLine implements IHologramLine { + private PacketPlayOutSpawnEntity spawnPacket; + private DataWatcher dataWatcher; + + private DataWatcherObject nameVisible; + private DataWatcherObject> customName; + + private int id; + private Location location; + private String text; + + public HologramLine(Location location, String text) { + this.id = 5; + this.location = location.clone(); + this.text = text; + + this.spawnPacket = new PacketPlayOutSpawnEntity(); + this.dataWatcher = createDataWatcher(); + + updatePacket(); + } + + @Override + public void setLocation(Location location) { + this.location = location.clone(); + updatePacket(); + + PacketPlayOutEntityTeleport packet = createTeleportPacket(); + location.getWorld().getPlayers().forEach(player -> sendPackets(player, packet)); + } + + @Override + public void setText(String text) { + this.text = text; + + dataWatcher.register(nameVisible, !text.isEmpty()); + dataWatcher.register(customName, Optional.ofNullable(ChatSerializer.b(text))); + + Packet metadataPacket = new PacketPlayOutEntityMetadata(id, dataWatcher, true); + location.getWorld().getPlayers().forEach(player -> sendPackets(player, metadataPacket)); + } + + @Override + public void showPlayer(Player player) { + if (player == null || !player.isOnline()) { + return; + } + + sendPackets(player, spawnPacket, new PacketPlayOutEntityMetadata(id, dataWatcher, true)); + } + + @Override + public void hidePlayer(Player player) { + if (player == null || !player.isOnline()) { + return; + } + + sendPackets(player, new PacketPlayOutEntityDestroy(id)); + } + + @Override + public void destroy() { + location.getWorld().getPlayers().forEach(player -> hidePlayer(player)); + } + + private void sendPackets(Player player, Packet... packets) { + PlayerConnection con = ((CraftPlayer) player).getHandle().playerConnection; + Arrays.stream(packets).forEach(packet -> con.sendPacket(packet)); + } + + private PacketPlayOutEntityTeleport createTeleportPacket() { + PacketDataSerializer s = new PacketDataSerializer(Unpooled.buffer()); + s.d(id); // id + s.writeDouble(location.getX()); // x + s.writeDouble(location.getY() + 1.975); // y + s.writeDouble(location.getZ()); // z + s.writeByte(0); // yaw + s.writeByte(0); // pitch + s.writeBoolean(true); // on ground + + try { + PacketPlayOutEntityTeleport packet = new PacketPlayOutEntityTeleport(); + packet.a(s); + return packet; + } catch (IOException e) { + e.printStackTrace(); + } finally { + s.release(); + } + + return null; + } + + private void updatePacket() { + PacketDataSerializer s = new PacketDataSerializer(Unpooled.buffer()); + s.d(id); // id + s.a(UUID.randomUUID()); // uuid + s.writeByte(78); // type + s.writeDouble(location.getX()); // x + s.writeDouble(location.getY() + 1.975); // y + s.writeDouble(location.getZ()); // z + s.writeByte(0); // pitch + s.writeByte(0); // yaw + s.writeInt(0); // ? + s.writeShort(0); // mot x + s.writeShort(0); // mot y + s.writeShort(0); // mot z + + try { + spawnPacket.a(s); + } catch (IOException e) { + e.printStackTrace(); + } finally { + s.release(); + } + } + + @SuppressWarnings("unchecked") + private DataWatcher createDataWatcher() { + try { + Field fEntityFlags = Entity.class.getDeclaredField("ac"); + Field fAirTicks = Entity.class.getDeclaredField("aD"); + Field fNameVisible = Entity.class.getDeclaredField("aF"); + Field fCustomName = Entity.class.getDeclaredField("aE"); + Field fNoGravity = Entity.class.getDeclaredField("aH"); + + setAccessible(fEntityFlags, fAirTicks, fNameVisible, fCustomName, fNoGravity); + + nameVisible = (DataWatcherObject) fNameVisible.get(null); + customName = (DataWatcherObject>) fCustomName.get(null); + DataWatcherObject entityFlags = (DataWatcherObject) fEntityFlags.get(null); + DataWatcherObject airTicks = (DataWatcherObject) fAirTicks.get(null); + DataWatcherObject noGravity = (DataWatcherObject) fNoGravity.get(null); + DataWatcherObject armorStandFlags = EntityArmorStand.a; + + DataWatcher dataWatcher = new DataWatcher(null); + dataWatcher.register(entityFlags, (byte) 0b100000); + dataWatcher.register(airTicks, 300); + dataWatcher.register(nameVisible, !text.isEmpty()); + dataWatcher.register(customName, Optional.ofNullable(ChatSerializer.b(text))); // TODO: Json + dataWatcher.register(noGravity, true); + dataWatcher.register(armorStandFlags, (byte) 0b10000); + + return dataWatcher; + } catch (ReflectiveOperationException e) { + e.printStackTrace(); + } + + return null; + } + + private void setAccessible(AccessibleObject... args) { + Arrays.stream(args).forEach(arg -> arg.setAccessible(true)); + } +} \ No newline at end of file diff --git a/nms/v13r2/pom.xml b/nms/v13r2/pom.xml new file mode 100644 index 0000000..4f260f5 --- /dev/null +++ b/nms/v13r2/pom.xml @@ -0,0 +1,34 @@ + + + 4.0.0 + + de.epiceric.shopchest + shopchest-nms-v13r2 + 1.13-SNAPSHOT + + ShopChest NMS v1.13-R2 + + + de.epiceric.shopchest + shopchest-nms + 1.13-SNAPSHOT + + + + + de.epiceric.shopchest + shopchest-nms-interfaces + 1.13-SNAPSHOT + provided + + + + org.bukkit + craftbukkit + 1.13.2-R0.1-SNAPSHOT + provided + + + diff --git a/nms/v13r2/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java b/nms/v13r2/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java new file mode 100644 index 0000000..0304769 --- /dev/null +++ b/nms/v13r2/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java @@ -0,0 +1,183 @@ +package de.epiceric.shopchest.shop.hologram; + +import java.io.IOException; +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.Optional; +import java.util.UUID; + +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_13_R2.entity.CraftPlayer; +import org.bukkit.entity.Player; + +import io.netty.buffer.Unpooled; +import net.minecraft.server.v1_13_R2.DataWatcher; +import net.minecraft.server.v1_13_R2.DataWatcherObject; +import net.minecraft.server.v1_13_R2.Entity; +import net.minecraft.server.v1_13_R2.EntityArmorStand; +import net.minecraft.server.v1_13_R2.IChatBaseComponent; +import net.minecraft.server.v1_13_R2.Packet; +import net.minecraft.server.v1_13_R2.PacketDataSerializer; +import net.minecraft.server.v1_13_R2.PacketPlayOutEntityDestroy; +import net.minecraft.server.v1_13_R2.PacketPlayOutEntityMetadata; +import net.minecraft.server.v1_13_R2.PacketPlayOutEntityTeleport; +import net.minecraft.server.v1_13_R2.PacketPlayOutSpawnEntity; +import net.minecraft.server.v1_13_R2.PlayerConnection; +import net.minecraft.server.v1_13_R2.IChatBaseComponent.ChatSerializer; + +public class HologramLine implements IHologramLine { + private PacketPlayOutSpawnEntity spawnPacket; + private DataWatcher dataWatcher; + + private DataWatcherObject nameVisible; + private DataWatcherObject> customName; + + private int id; + private Location location; + private String text; + + public HologramLine(Location location, String text) { + this.id = 5; + this.location = location.clone(); + this.text = text; + + this.spawnPacket = new PacketPlayOutSpawnEntity(); + this.dataWatcher = createDataWatcher(); + + updatePacket(); + } + + @Override + public void setLocation(Location location) { + this.location = location.clone(); + updatePacket(); + + PacketPlayOutEntityTeleport packet = createTeleportPacket(); + location.getWorld().getPlayers().forEach(player -> sendPackets(player, packet)); + } + + @Override + public void setText(String text) { + this.text = text; + + dataWatcher.register(nameVisible, !text.isEmpty()); + dataWatcher.register(customName, Optional.ofNullable(ChatSerializer.b(text))); + + Packet metadataPacket = new PacketPlayOutEntityMetadata(id, dataWatcher, true); + location.getWorld().getPlayers().forEach(player -> sendPackets(player, metadataPacket)); + } + + @Override + public void showPlayer(Player player) { + if (player == null || !player.isOnline()) { + return; + } + + sendPackets(player, spawnPacket, new PacketPlayOutEntityMetadata(id, dataWatcher, true)); + } + + @Override + public void hidePlayer(Player player) { + if (player == null || !player.isOnline()) { + return; + } + + sendPackets(player, new PacketPlayOutEntityDestroy(id)); + } + + @Override + public void destroy() { + location.getWorld().getPlayers().forEach(player -> hidePlayer(player)); + } + + private void sendPackets(Player player, Packet... packets) { + PlayerConnection con = ((CraftPlayer) player).getHandle().playerConnection; + Arrays.stream(packets).forEach(packet -> con.sendPacket(packet)); + } + + private PacketPlayOutEntityTeleport createTeleportPacket() { + PacketDataSerializer s = new PacketDataSerializer(Unpooled.buffer()); + s.d(id); // id + s.writeDouble(location.getX()); // x + s.writeDouble(location.getY() + 1.975); // y + s.writeDouble(location.getZ()); // z + s.writeByte(0); // yaw + s.writeByte(0); // pitch + s.writeBoolean(true); // on ground + + try { + PacketPlayOutEntityTeleport packet = new PacketPlayOutEntityTeleport(); + packet.a(s); + return packet; + } catch (IOException e) { + e.printStackTrace(); + } finally { + s.release(); + } + + return null; + } + + private void updatePacket() { + PacketDataSerializer s = new PacketDataSerializer(Unpooled.buffer()); + s.d(id); // id + s.a(UUID.randomUUID()); // uuid + s.writeByte(78); // type + s.writeDouble(location.getX()); // x + s.writeDouble(location.getY() + 1.975); // y + s.writeDouble(location.getZ()); // z + s.writeByte(0); // pitch + s.writeByte(0); // yaw + s.writeInt(0); // ? + s.writeShort(0); // mot x + s.writeShort(0); // mot y + s.writeShort(0); // mot z + + try { + spawnPacket.a(s); + } catch (IOException e) { + e.printStackTrace(); + } finally { + s.release(); + } + } + + @SuppressWarnings("unchecked") + private DataWatcher createDataWatcher() { + try { + Field fEntityFlags = Entity.class.getDeclaredField("ac"); + Field fAirTicks = Entity.class.getDeclaredField("aD"); + Field fNameVisible = Entity.class.getDeclaredField("aF"); + Field fCustomName = Entity.class.getDeclaredField("aE"); + Field fNoGravity = Entity.class.getDeclaredField("aH"); + + setAccessible(fEntityFlags, fAirTicks, fNameVisible, fCustomName, fNoGravity); + + nameVisible = (DataWatcherObject) fNameVisible.get(null); + customName = (DataWatcherObject>) fCustomName.get(null); + DataWatcherObject entityFlags = (DataWatcherObject) fEntityFlags.get(null); + DataWatcherObject airTicks = (DataWatcherObject) fAirTicks.get(null); + DataWatcherObject noGravity = (DataWatcherObject) fNoGravity.get(null); + DataWatcherObject armorStandFlags = EntityArmorStand.a; + + DataWatcher dataWatcher = new DataWatcher(null); + dataWatcher.register(entityFlags, (byte) 0b100000); + dataWatcher.register(airTicks, 300); + dataWatcher.register(nameVisible, !text.isEmpty()); + dataWatcher.register(customName, Optional.ofNullable(ChatSerializer.b(text))); // TODO: Json + dataWatcher.register(noGravity, true); + dataWatcher.register(armorStandFlags, (byte) 0b10000); + + return dataWatcher; + } catch (ReflectiveOperationException e) { + e.printStackTrace(); + } + + return null; + } + + private void setAccessible(AccessibleObject... args) { + Arrays.stream(args).forEach(arg -> arg.setAccessible(true)); + } +} \ No newline at end of file diff --git a/nms/v14r1/pom.xml b/nms/v14r1/pom.xml new file mode 100644 index 0000000..3870b84 --- /dev/null +++ b/nms/v14r1/pom.xml @@ -0,0 +1,34 @@ + + + 4.0.0 + + de.epiceric.shopchest + shopchest-nms-v14r1 + 1.13-SNAPSHOT + + ShopChest NMS v1.14-R1 + + + de.epiceric.shopchest + shopchest-nms + 1.13-SNAPSHOT + + + + + de.epiceric.shopchest + shopchest-nms-interfaces + 1.13-SNAPSHOT + provided + + + + org.bukkit + craftbukkit + 1.14.3-R0.1-SNAPSHOT + provided + + + diff --git a/nms/v14r1/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java b/nms/v14r1/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java new file mode 100644 index 0000000..966bce2 --- /dev/null +++ b/nms/v14r1/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java @@ -0,0 +1,185 @@ +package de.epiceric.shopchest.shop.hologram; + +import java.io.IOException; +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.Optional; +import java.util.UUID; + +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_14_R1.entity.CraftPlayer; +import org.bukkit.entity.Player; + +import io.netty.buffer.Unpooled; +import net.minecraft.server.v1_14_R1.DataWatcher; +import net.minecraft.server.v1_14_R1.DataWatcherObject; +import net.minecraft.server.v1_14_R1.Entity; +import net.minecraft.server.v1_14_R1.EntityArmorStand; +import net.minecraft.server.v1_14_R1.EntityTypes; +import net.minecraft.server.v1_14_R1.IChatBaseComponent; +import net.minecraft.server.v1_14_R1.IRegistry; +import net.minecraft.server.v1_14_R1.Packet; +import net.minecraft.server.v1_14_R1.PacketDataSerializer; +import net.minecraft.server.v1_14_R1.PacketPlayOutEntityDestroy; +import net.minecraft.server.v1_14_R1.PacketPlayOutEntityMetadata; +import net.minecraft.server.v1_14_R1.PacketPlayOutEntityTeleport; +import net.minecraft.server.v1_14_R1.PacketPlayOutSpawnEntity; +import net.minecraft.server.v1_14_R1.PlayerConnection; +import net.minecraft.server.v1_14_R1.IChatBaseComponent.ChatSerializer; + +public class HologramLine implements IHologramLine { + private PacketPlayOutSpawnEntity spawnPacket; + private DataWatcher dataWatcher; + + private DataWatcherObject nameVisible; + private DataWatcherObject> customName; + + private int id; + private Location location; + private String text; + + public HologramLine(Location location, String text) { + this.id = 5; + this.location = location.clone(); + this.text = text; + + this.spawnPacket = new PacketPlayOutSpawnEntity(); + this.dataWatcher = createDataWatcher(); + + updatePacket(); + } + + @Override + public void setLocation(Location location) { + this.location = location.clone(); + updatePacket(); + + PacketPlayOutEntityTeleport packet = createTeleportPacket(); + location.getWorld().getPlayers().forEach(player -> sendPackets(player, packet)); + } + + @Override + public void setText(String text) { + this.text = text; + + dataWatcher.register(nameVisible, !text.isEmpty()); + dataWatcher.register(customName, Optional.ofNullable(ChatSerializer.b(text))); + + Packet metadataPacket = new PacketPlayOutEntityMetadata(id, dataWatcher, true); + location.getWorld().getPlayers().forEach(player -> sendPackets(player, metadataPacket)); + } + + @Override + public void showPlayer(Player player) { + if (player == null || !player.isOnline()) { + return; + } + + sendPackets(player, spawnPacket, new PacketPlayOutEntityMetadata(id, dataWatcher, true)); + } + + @Override + public void hidePlayer(Player player) { + if (player == null || !player.isOnline()) { + return; + } + + sendPackets(player, new PacketPlayOutEntityDestroy(id)); + } + + @Override + public void destroy() { + location.getWorld().getPlayers().forEach(player -> hidePlayer(player)); + } + + private void sendPackets(Player player, Packet... packets) { + PlayerConnection con = ((CraftPlayer) player).getHandle().playerConnection; + Arrays.stream(packets).forEach(packet -> con.sendPacket(packet)); + } + + private PacketPlayOutEntityTeleport createTeleportPacket() { + PacketDataSerializer s = new PacketDataSerializer(Unpooled.buffer()); + s.d(id); // id + s.writeDouble(location.getX()); // x + s.writeDouble(location.getY() + 1.975); // y + s.writeDouble(location.getZ()); // z + s.writeByte(0); // yaw + s.writeByte(0); // pitch + s.writeBoolean(true); // on ground + + try { + PacketPlayOutEntityTeleport packet = new PacketPlayOutEntityTeleport(); + packet.a(s); + return packet; + } catch (IOException e) { + e.printStackTrace(); + } finally { + s.release(); + } + + return null; + } + + private void updatePacket() { + PacketDataSerializer s = new PacketDataSerializer(Unpooled.buffer()); + s.d(id); // id + s.a(UUID.randomUUID()); // uuid + s.d(IRegistry.ENTITY_TYPE.a(EntityTypes.ARMOR_STAND)); // type + s.writeDouble(location.getX()); // x + s.writeDouble(location.getY()); // y + s.writeDouble(location.getZ()); // z + s.writeByte(0); // pitch + s.writeByte(0); // yaw + s.writeInt(0); // ? + s.writeShort(0); // mot x + s.writeShort(0); // mot y + s.writeShort(0); // mot z + + try { + spawnPacket.a(s); + } catch (IOException e) { + e.printStackTrace(); + } finally { + s.release(); + } + } + + @SuppressWarnings("unchecked") + private DataWatcher createDataWatcher() { + try { + Field fEntityFlags = Entity.class.getDeclaredField("W"); + Field fAirTicks = Entity.class.getDeclaredField("AIR_TICKS"); + Field fNameVisible = Entity.class.getDeclaredField("aA"); + Field fCustomName = Entity.class.getDeclaredField("az"); + Field fNoGravity = Entity.class.getDeclaredField("aC"); + + setAccessible(fEntityFlags, fAirTicks, fNameVisible, fCustomName, fNoGravity); + + nameVisible = (DataWatcherObject) fNameVisible.get(null); + customName = (DataWatcherObject>) fCustomName.get(null); + DataWatcherObject entityFlags = (DataWatcherObject) fEntityFlags.get(null); + DataWatcherObject airTicks = (DataWatcherObject) fAirTicks.get(null); + DataWatcherObject noGravity = (DataWatcherObject) fNoGravity.get(null); + DataWatcherObject armorStandFlags = EntityArmorStand.b; + + DataWatcher dataWatcher = new DataWatcher(null); + dataWatcher.register(entityFlags, (byte) 0b100000); + dataWatcher.register(airTicks, 300); + dataWatcher.register(nameVisible, !text.isEmpty()); + dataWatcher.register(customName, Optional.ofNullable(ChatSerializer.b(text))); + dataWatcher.register(noGravity, true); + dataWatcher.register(armorStandFlags, (byte) 0b10000); + + return dataWatcher; + } catch (ReflectiveOperationException e) { + e.printStackTrace(); + } + + return null; + } + + private void setAccessible(AccessibleObject... args) { + Arrays.stream(args).forEach(arg -> arg.setAccessible(true)); + } +} \ No newline at end of file diff --git a/nms/v15r1/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java b/nms/v15r1/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java index 702d07e..c09573d 100644 --- a/nms/v15r1/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java +++ b/nms/v15r1/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java @@ -29,7 +29,7 @@ import net.minecraft.server.v1_15_R1.PlayerConnection; import net.minecraft.server.v1_15_R1.IChatBaseComponent.ChatSerializer; public class HologramLine implements IHologramLine { - private PacketPlayOutSpawnEntity packet; + private PacketPlayOutSpawnEntity spawnPacket; private DataWatcher dataWatcher; private DataWatcherObject nameVisible; @@ -44,7 +44,7 @@ public class HologramLine implements IHologramLine { this.location = location.clone(); this.text = text; - this.packet = new PacketPlayOutSpawnEntity(); + this.spawnPacket = new PacketPlayOutSpawnEntity(); this.dataWatcher = createDataWatcher(); updatePacket(); @@ -55,7 +55,7 @@ public class HologramLine implements IHologramLine { this.location = location.clone(); updatePacket(); - PacketPlayOutEntityTeleport packet = new PacketPlayOutEntityTeleport(); + PacketPlayOutEntityTeleport packet = createTeleportPacket(); location.getWorld().getPlayers().forEach(player -> sendPackets(player, packet)); } @@ -66,8 +66,8 @@ public class HologramLine implements IHologramLine { dataWatcher.register(nameVisible, !text.isEmpty()); dataWatcher.register(customName, Optional.ofNullable(ChatSerializer.b(text))); - location.getWorld().getPlayers() - .forEach(player -> sendPackets(player, new PacketPlayOutEntityMetadata(id, dataWatcher, true))); + Packet metadataPacket = new PacketPlayOutEntityMetadata(id, dataWatcher, true); + location.getWorld().getPlayers().forEach(player -> sendPackets(player, metadataPacket)); } @Override @@ -76,7 +76,7 @@ public class HologramLine implements IHologramLine { return; } - sendPackets(player, packet, new PacketPlayOutEntityMetadata(id, dataWatcher, true)); + sendPackets(player, spawnPacket, new PacketPlayOutEntityMetadata(id, dataWatcher, true)); } @Override @@ -98,7 +98,30 @@ public class HologramLine implements IHologramLine { Arrays.stream(packets).forEach(packet -> con.sendPacket(packet)); } - public void updatePacket() { + private PacketPlayOutEntityTeleport createTeleportPacket() { + PacketDataSerializer s = new PacketDataSerializer(Unpooled.buffer()); + s.d(id); // id + s.writeDouble(location.getX()); // x + s.writeDouble(location.getY() + 1.975); // y + s.writeDouble(location.getZ()); // z + s.writeByte(0); // yaw + s.writeByte(0); // pitch + s.writeBoolean(true); // on ground + + try { + PacketPlayOutEntityTeleport packet = new PacketPlayOutEntityTeleport(); + packet.a(s); + return packet; + } catch (IOException e) { + e.printStackTrace(); + } finally { + s.release(); + } + + return null; + } + + private void updatePacket() { PacketDataSerializer s = new PacketDataSerializer(Unpooled.buffer()); s.d(id); // id s.a(UUID.randomUUID()); // uuid @@ -114,7 +137,7 @@ public class HologramLine implements IHologramLine { s.writeShort(0); // mot z try { - packet.a(s); + spawnPacket.a(s); } catch (IOException e) { e.printStackTrace(); } finally { @@ -123,7 +146,7 @@ public class HologramLine implements IHologramLine { } @SuppressWarnings("unchecked") - public DataWatcher createDataWatcher() { + private DataWatcher createDataWatcher() { try { Field fEntityFlags = Entity.class.getDeclaredField("T"); Field fAirTicks = Entity.class.getDeclaredField("AIR_TICKS"); @@ -156,7 +179,7 @@ public class HologramLine implements IHologramLine { return null; } - void setAccessible(AccessibleObject... args) { + private void setAccessible(AccessibleObject... args) { Arrays.stream(args).forEach(arg -> arg.setAccessible(true)); } } \ No newline at end of file diff --git a/nms/v8r1/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java b/nms/v8r1/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java index eeeea0d..ff00767 100644 --- a/nms/v8r1/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java +++ b/nms/v8r1/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java @@ -18,7 +18,7 @@ import net.minecraft.server.v1_8_R1.PacketPlayOutSpawnEntity; import net.minecraft.server.v1_8_R1.PlayerConnection; public class HologramLine implements IHologramLine { - private PacketPlayOutSpawnEntity packet; + private PacketPlayOutSpawnEntity spawnPacket; private DataWatcher dataWatcher; private int id; @@ -30,7 +30,7 @@ public class HologramLine implements IHologramLine { this.location = location.clone(); this.text = text == null ? "" : text; - this.packet = new PacketPlayOutSpawnEntity(); + this.spawnPacket = new PacketPlayOutSpawnEntity(); this.dataWatcher = createDataWatcher(); updatePacket(); @@ -45,8 +45,8 @@ public class HologramLine implements IHologramLine { int y = MathHelper.floor(location.getY() * 32d); int z = MathHelper.floor(location.getZ() * 32d); - Packet packet = new PacketPlayOutEntityTeleport(id, x, y, z, (byte) 0, (byte) 0, true); - location.getWorld().getPlayers().forEach(player -> sendPackets(player, packet)); + Packet teleportPacket = new PacketPlayOutEntityTeleport(id, x, y, z, (byte) 0, (byte) 0, true); + location.getWorld().getPlayers().forEach(player -> sendPackets(player, teleportPacket)); } @Override @@ -56,8 +56,8 @@ public class HologramLine implements IHologramLine { dataWatcher.a(2, this.text); // custom name dataWatcher.a(3, (byte) (this.text.isEmpty() ? 0 : 1)); // name visible - location.getWorld().getPlayers() - .forEach(player -> sendPackets(player, new PacketPlayOutEntityMetadata(id, dataWatcher, true))); + Packet metadataPacket = new PacketPlayOutEntityMetadata(id, dataWatcher, true); + location.getWorld().getPlayers().forEach(player -> sendPackets(player, metadataPacket)); } @Override @@ -66,7 +66,7 @@ public class HologramLine implements IHologramLine { return; } - sendPackets(player, packet, new PacketPlayOutEntityMetadata(id, dataWatcher, true)); + sendPackets(player, spawnPacket, new PacketPlayOutEntityMetadata(id, dataWatcher, true)); } @Override @@ -98,7 +98,7 @@ public class HologramLine implements IHologramLine { serializer.writeByte(0); // pitch serializer.writeByte(0); // yaw serializer.writeInt(0); // has motion (?) - this.packet.a(serializer); + this.spawnPacket.a(serializer); serializer.release(); } @@ -108,7 +108,7 @@ public class HologramLine implements IHologramLine { dataWatcher.a(1, (short) 300); // air ticks dataWatcher.a(2, text); // custom name dataWatcher.a(3, (byte) (text.isEmpty() ? 0 : 1)); // name visible - dataWatcher.a(10, (byte) 0b1100); // armor stand flags + dataWatcher.a(10, (byte) 0); // armor stand flags return dataWatcher; } } \ No newline at end of file diff --git a/nms/v8r2/pom.xml b/nms/v8r2/pom.xml new file mode 100644 index 0000000..f43319c --- /dev/null +++ b/nms/v8r2/pom.xml @@ -0,0 +1,34 @@ + + + 4.0.0 + + de.epiceric.shopchest + shopchest-nms-v8r2 + 1.13-SNAPSHOT + + ShopChest NMS v1.8-R2 + + + de.epiceric.shopchest + shopchest-nms + 1.13-SNAPSHOT + + + + + de.epiceric.shopchest + shopchest-nms-interfaces + 1.13-SNAPSHOT + provided + + + + org.bukkit + craftbukkit + 1.8.3-R0.1-SNAPSHOT + provided + + + diff --git a/nms/v8r2/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java b/nms/v8r2/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java new file mode 100644 index 0000000..4849291 --- /dev/null +++ b/nms/v8r2/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java @@ -0,0 +1,121 @@ +package de.epiceric.shopchest.shop.hologram; + +import java.io.IOException; +import java.util.Arrays; + +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_8_R2.entity.CraftPlayer; +import org.bukkit.entity.Player; + +import io.netty.buffer.Unpooled; +import net.minecraft.server.v1_8_R2.DataWatcher; +import net.minecraft.server.v1_8_R2.MathHelper; +import net.minecraft.server.v1_8_R2.Packet; +import net.minecraft.server.v1_8_R2.PacketDataSerializer; +import net.minecraft.server.v1_8_R2.PacketPlayOutEntityDestroy; +import net.minecraft.server.v1_8_R2.PacketPlayOutEntityMetadata; +import net.minecraft.server.v1_8_R2.PacketPlayOutEntityTeleport; +import net.minecraft.server.v1_8_R2.PacketPlayOutSpawnEntity; +import net.minecraft.server.v1_8_R2.PlayerConnection; + +public class HologramLine implements IHologramLine { + private PacketPlayOutSpawnEntity spawnPacket; + private DataWatcher dataWatcher; + + private int id; + private Location location; + private String text; + + public HologramLine(Location location, String text) { + this.id = 5; + this.location = location.clone(); + this.text = text == null ? "" : text; + + this.spawnPacket = new PacketPlayOutSpawnEntity(); + this.dataWatcher = createDataWatcher(); + + updatePacket(); + } + + @Override + public void setLocation(Location location) { + this.location = location.clone(); + updatePacket(); + + int x = MathHelper.floor(location.getX() * 32d); + int y = MathHelper.floor((location.getY() + 1.975) * 32d); + int z = MathHelper.floor(location.getZ() * 32d); + + Packet teleportPacket = new PacketPlayOutEntityTeleport(id, x, y, z, (byte) 0, (byte) 0, true); + location.getWorld().getPlayers().forEach(player -> sendPackets(player, teleportPacket)); + } + + @Override + public void setText(String text) { + this.text = text == null ? "" : text; + + dataWatcher.a(2, this.text); // custom name + dataWatcher.a(3, (byte) (this.text.isEmpty() ? 0 : 1)); // name visible + + Packet metadataPacket = new PacketPlayOutEntityMetadata(id, dataWatcher, true); + location.getWorld().getPlayers().forEach(player -> sendPackets(player, metadataPacket)); + } + + @Override + public void showPlayer(Player player) { + if (player == null || !player.isOnline()) { + return; + } + + sendPackets(player, spawnPacket, new PacketPlayOutEntityMetadata(id, dataWatcher, true)); + } + + @Override + public void hidePlayer(Player player) { + if (player == null || !player.isOnline()) { + return; + } + + sendPackets(player, new PacketPlayOutEntityDestroy(id)); + } + + @Override + public void destroy() { + location.getWorld().getPlayers().forEach(player -> hidePlayer(player)); + } + + private void sendPackets(Player player, Packet... packets) { + PlayerConnection con = ((CraftPlayer) player).getHandle().playerConnection; + Arrays.stream(packets).forEach(packet -> con.sendPacket(packet)); + } + + private void updatePacket() { + PacketDataSerializer s = new PacketDataSerializer(Unpooled.buffer()); + s.b(id); // id + s.writeByte(78); // entity type + s.writeInt(MathHelper.floor(location.getX() * 32d)); // x + s.writeInt(MathHelper.floor((location.getY() + 1.975) * 32d)); // y + s.writeInt(MathHelper.floor(location.getZ() * 32d)); // z + s.writeByte(0); // pitch + s.writeByte(0); // yaw + s.writeInt(0); // has motion (?) + + try { + spawnPacket.a(s); + } catch (IOException e) { + e.printStackTrace(); + } finally { + s.release(); + } + } + + private DataWatcher createDataWatcher() { + DataWatcher dataWatcher = new DataWatcher(null); + dataWatcher.a(0, 0b100000); // entity flags + dataWatcher.a(1, (short) 300); // air ticks + dataWatcher.a(2, text); // custom name + dataWatcher.a(3, (byte) (text.isEmpty() ? 0 : 1)); // name visible + dataWatcher.a(10, (byte) 0b10000); // armor stand flags + return dataWatcher; + } +} \ No newline at end of file diff --git a/nms/v8r3/pom.xml b/nms/v8r3/pom.xml new file mode 100644 index 0000000..f64ab5a --- /dev/null +++ b/nms/v8r3/pom.xml @@ -0,0 +1,34 @@ + + + 4.0.0 + + de.epiceric.shopchest + shopchest-nms-v8r3 + 1.13-SNAPSHOT + + ShopChest NMS v1.8-R3 + + + de.epiceric.shopchest + shopchest-nms + 1.13-SNAPSHOT + + + + + de.epiceric.shopchest + shopchest-nms-interfaces + 1.13-SNAPSHOT + provided + + + + org.bukkit + craftbukkit + 1.8.8-R0.1-SNAPSHOT + provided + + + diff --git a/nms/v8r3/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java b/nms/v8r3/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java new file mode 100644 index 0000000..e360754 --- /dev/null +++ b/nms/v8r3/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java @@ -0,0 +1,121 @@ +package de.epiceric.shopchest.shop.hologram; + +import java.io.IOException; +import java.util.Arrays; + +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; +import org.bukkit.entity.Player; + +import io.netty.buffer.Unpooled; +import net.minecraft.server.v1_8_R3.DataWatcher; +import net.minecraft.server.v1_8_R3.MathHelper; +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketDataSerializer; +import net.minecraft.server.v1_8_R3.PacketPlayOutEntityDestroy; +import net.minecraft.server.v1_8_R3.PacketPlayOutEntityMetadata; +import net.minecraft.server.v1_8_R3.PacketPlayOutEntityTeleport; +import net.minecraft.server.v1_8_R3.PacketPlayOutSpawnEntity; +import net.minecraft.server.v1_8_R3.PlayerConnection; + +public class HologramLine implements IHologramLine { + private PacketPlayOutSpawnEntity spawnPacket; + private DataWatcher dataWatcher; + + private int id; + private Location location; + private String text; + + public HologramLine(Location location, String text) { + this.id = 5; + this.location = location.clone(); + this.text = text == null ? "" : text; + + this.spawnPacket = new PacketPlayOutSpawnEntity(); + this.dataWatcher = createDataWatcher(); + + updatePacket(); + } + + @Override + public void setLocation(Location location) { + this.location = location.clone(); + updatePacket(); + + int x = MathHelper.floor(location.getX() * 32d); + int y = MathHelper.floor((location.getY() + 1.975) * 32d); + int z = MathHelper.floor(location.getZ() * 32d); + + Packet teleportPacket = new PacketPlayOutEntityTeleport(id, x, y, z, (byte) 0, (byte) 0, true); + location.getWorld().getPlayers().forEach(player -> sendPackets(player, teleportPacket)); + } + + @Override + public void setText(String text) { + this.text = text == null ? "" : text; + + dataWatcher.a(2, this.text); // custom name + dataWatcher.a(3, (byte) (this.text.isEmpty() ? 0 : 1)); // name visible + + Packet metadataPacket = new PacketPlayOutEntityMetadata(id, dataWatcher, true); + location.getWorld().getPlayers().forEach(player -> sendPackets(player, metadataPacket)); + } + + @Override + public void showPlayer(Player player) { + if (player == null || !player.isOnline()) { + return; + } + + sendPackets(player, spawnPacket, new PacketPlayOutEntityMetadata(id, dataWatcher, true)); + } + + @Override + public void hidePlayer(Player player) { + if (player == null || !player.isOnline()) { + return; + } + + sendPackets(player, new PacketPlayOutEntityDestroy(id)); + } + + @Override + public void destroy() { + location.getWorld().getPlayers().forEach(player -> hidePlayer(player)); + } + + private void sendPackets(Player player, Packet... packets) { + PlayerConnection con = ((CraftPlayer) player).getHandle().playerConnection; + Arrays.stream(packets).forEach(packet -> con.sendPacket(packet)); + } + + private void updatePacket() { + PacketDataSerializer s = new PacketDataSerializer(Unpooled.buffer()); + s.b(id); // id + s.writeByte(78); // entity type + s.writeInt(MathHelper.floor(location.getX() * 32d)); // x + s.writeInt(MathHelper.floor((location.getY() + 1.975) * 32d)); // y + s.writeInt(MathHelper.floor(location.getZ() * 32d)); // z + s.writeByte(0); // pitch + s.writeByte(0); // yaw + s.writeInt(0); // has motion (?) + + try { + spawnPacket.a(s); + } catch (IOException e) { + e.printStackTrace(); + } finally { + s.release(); + } + } + + private DataWatcher createDataWatcher() { + DataWatcher dataWatcher = new DataWatcher(null); + dataWatcher.a(0, 0b100000); // entity flags + dataWatcher.a(1, (short) 300); // air ticks + dataWatcher.a(2, text); // custom name + dataWatcher.a(3, (byte) (text.isEmpty() ? 0 : 1)); // name visible + dataWatcher.a(10, (byte) 0b10000); // armor stand flags + return dataWatcher; + } +} \ No newline at end of file diff --git a/nms/v9r1/pom.xml b/nms/v9r1/pom.xml new file mode 100644 index 0000000..af0e24d --- /dev/null +++ b/nms/v9r1/pom.xml @@ -0,0 +1,34 @@ + + + 4.0.0 + + de.epiceric.shopchest + shopchest-nms-v9r1 + 1.13-SNAPSHOT + + ShopChest NMS v1.9-R1 + + + de.epiceric.shopchest + shopchest-nms + 1.13-SNAPSHOT + + + + + de.epiceric.shopchest + shopchest-nms-interfaces + 1.13-SNAPSHOT + provided + + + + org.bukkit + craftbukkit + 1.9.2-R0.1-SNAPSHOT + provided + + + diff --git a/nms/v9r1/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java b/nms/v9r1/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java new file mode 100644 index 0000000..f1c788c --- /dev/null +++ b/nms/v9r1/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java @@ -0,0 +1,179 @@ +package de.epiceric.shopchest.shop.hologram; + +import java.io.IOException; +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.Optional; +import java.util.UUID; + +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_9_R1.entity.CraftPlayer; +import org.bukkit.entity.Player; + +import io.netty.buffer.Unpooled; +import net.minecraft.server.v1_9_R1.DataWatcher; +import net.minecraft.server.v1_9_R1.DataWatcherObject; +import net.minecraft.server.v1_9_R1.Entity; +import net.minecraft.server.v1_9_R1.EntityArmorStand; +import net.minecraft.server.v1_9_R1.IChatBaseComponent; +import net.minecraft.server.v1_9_R1.Packet; +import net.minecraft.server.v1_9_R1.PacketDataSerializer; +import net.minecraft.server.v1_9_R1.PacketPlayOutEntityDestroy; +import net.minecraft.server.v1_9_R1.PacketPlayOutEntityMetadata; +import net.minecraft.server.v1_9_R1.PacketPlayOutEntityTeleport; +import net.minecraft.server.v1_9_R1.PacketPlayOutSpawnEntity; +import net.minecraft.server.v1_9_R1.PlayerConnection; + +public class HologramLine implements IHologramLine { + private PacketPlayOutSpawnEntity spawnPacket; + private DataWatcher dataWatcher; + + private DataWatcherObject nameVisible; + private DataWatcherObject> customName; + + private int id; + private Location location; + private String text; + + public HologramLine(Location location, String text) { + this.id = 5; + this.location = location.clone(); + this.text = text; + + this.spawnPacket = new PacketPlayOutSpawnEntity(); + this.dataWatcher = createDataWatcher(); + + updatePacket(); + } + + @Override + public void setLocation(Location location) { + this.location = location.clone(); + updatePacket(); + + PacketPlayOutEntityTeleport packet = createTeleportPacket(); + location.getWorld().getPlayers().forEach(player -> sendPackets(player, packet)); + } + + @Override + public void setText(String text) { + this.text = text; + + dataWatcher.register(nameVisible, !text.isEmpty()); + dataWatcher.register(customName, text); + + Packet metadataPacket = new PacketPlayOutEntityMetadata(id, dataWatcher, true); + location.getWorld().getPlayers().forEach(player -> sendPackets(player, metadataPacket)); + } + + @Override + public void showPlayer(Player player) { + if (player == null || !player.isOnline()) { + return; + } + + sendPackets(player, spawnPacket, new PacketPlayOutEntityMetadata(id, dataWatcher, true)); + } + + @Override + public void hidePlayer(Player player) { + if (player == null || !player.isOnline()) { + return; + } + + sendPackets(player, new PacketPlayOutEntityDestroy(id)); + } + + @Override + public void destroy() { + location.getWorld().getPlayers().forEach(player -> hidePlayer(player)); + } + + private void sendPackets(Player player, Packet... packets) { + PlayerConnection con = ((CraftPlayer) player).getHandle().playerConnection; + Arrays.stream(packets).forEach(packet -> con.sendPacket(packet)); + } + + private PacketPlayOutEntityTeleport createTeleportPacket() { + PacketDataSerializer s = new PacketDataSerializer(Unpooled.buffer()); + s.d(id); // id + s.writeDouble(location.getX()); // x + s.writeDouble(location.getY() + 1.975); // y + s.writeDouble(location.getZ()); // z + s.writeByte(0); // yaw + s.writeByte(0); // pitch + s.writeBoolean(true); // on ground + + try { + PacketPlayOutEntityTeleport packet = new PacketPlayOutEntityTeleport(); + packet.a(s); + return packet; + } catch (IOException e) { + e.printStackTrace(); + } finally { + s.release(); + } + + return null; + } + + private void updatePacket() { + PacketDataSerializer s = new PacketDataSerializer(Unpooled.buffer()); + s.d(id); // id + s.a(UUID.randomUUID()); // uuid + s.writeByte(78); // type + s.writeDouble(location.getX()); // x + s.writeDouble(location.getY() + 1.975); // y + s.writeDouble(location.getZ()); // z + s.writeByte(0); // pitch + s.writeByte(0); // yaw + s.writeInt(0); // ? + s.writeShort(0); // mot x + s.writeShort(0); // mot y + s.writeShort(0); // mot z + + try { + spawnPacket.a(s); + } catch (IOException e) { + e.printStackTrace(); + } finally { + s.release(); + } + } + + @SuppressWarnings("unchecked") + private DataWatcher createDataWatcher() { + try { + Field fEntityFlags = Entity.class.getDeclaredField("ax"); + Field fAirTicks = Entity.class.getDeclaredField("ay"); + Field fNameVisible = Entity.class.getDeclaredField("aA"); + Field fCustomName = Entity.class.getDeclaredField("az"); + + setAccessible(fEntityFlags, fAirTicks, fNameVisible, fCustomName); + + nameVisible = (DataWatcherObject) fNameVisible.get(null); + customName = (DataWatcherObject>) fCustomName.get(null); + DataWatcherObject entityFlags = (DataWatcherObject) fEntityFlags.get(null); + DataWatcherObject airTicks = (DataWatcherObject) fAirTicks.get(null); + DataWatcherObject armorStandFlags = EntityArmorStand.a; + + DataWatcher dataWatcher = new DataWatcher(null); + dataWatcher.register(entityFlags, (byte) 0b100000); + dataWatcher.register(airTicks, 300); + dataWatcher.register(nameVisible, !text.isEmpty()); + dataWatcher.register(customName, text); + dataWatcher.register(armorStandFlags, (byte) 0b10000); + + return dataWatcher; + } catch (ReflectiveOperationException e) { + e.printStackTrace(); + } + + return null; + } + + private void setAccessible(AccessibleObject... args) { + Arrays.stream(args).forEach(arg -> arg.setAccessible(true)); + } +} \ No newline at end of file diff --git a/nms/v9r2/pom.xml b/nms/v9r2/pom.xml new file mode 100644 index 0000000..8a8640d --- /dev/null +++ b/nms/v9r2/pom.xml @@ -0,0 +1,34 @@ + + + 4.0.0 + + de.epiceric.shopchest + shopchest-nms-v9r2 + 1.13-SNAPSHOT + + ShopChest NMS v1.9-R2 + + + de.epiceric.shopchest + shopchest-nms + 1.13-SNAPSHOT + + + + + de.epiceric.shopchest + shopchest-nms-interfaces + 1.13-SNAPSHOT + provided + + + + org.bukkit + craftbukkit + 1.9.4-R0.1-SNAPSHOT + provided + + + diff --git a/nms/v9r2/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java b/nms/v9r2/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java new file mode 100644 index 0000000..aa7c310 --- /dev/null +++ b/nms/v9r2/src/main/java/de/epiceric/shopchest/shop/hologram/HologramLine.java @@ -0,0 +1,179 @@ +package de.epiceric.shopchest.shop.hologram; + +import java.io.IOException; +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.Optional; +import java.util.UUID; + +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_9_R2.entity.CraftPlayer; +import org.bukkit.entity.Player; + +import io.netty.buffer.Unpooled; +import net.minecraft.server.v1_9_R2.DataWatcher; +import net.minecraft.server.v1_9_R2.DataWatcherObject; +import net.minecraft.server.v1_9_R2.Entity; +import net.minecraft.server.v1_9_R2.EntityArmorStand; +import net.minecraft.server.v1_9_R2.IChatBaseComponent; +import net.minecraft.server.v1_9_R2.Packet; +import net.minecraft.server.v1_9_R2.PacketDataSerializer; +import net.minecraft.server.v1_9_R2.PacketPlayOutEntityDestroy; +import net.minecraft.server.v1_9_R2.PacketPlayOutEntityMetadata; +import net.minecraft.server.v1_9_R2.PacketPlayOutEntityTeleport; +import net.minecraft.server.v1_9_R2.PacketPlayOutSpawnEntity; +import net.minecraft.server.v1_9_R2.PlayerConnection; + +public class HologramLine implements IHologramLine { + private PacketPlayOutSpawnEntity spawnPacket; + private DataWatcher dataWatcher; + + private DataWatcherObject nameVisible; + private DataWatcherObject> customName; + + private int id; + private Location location; + private String text; + + public HologramLine(Location location, String text) { + this.id = 5; + this.location = location.clone(); + this.text = text; + + this.spawnPacket = new PacketPlayOutSpawnEntity(); + this.dataWatcher = createDataWatcher(); + + updatePacket(); + } + + @Override + public void setLocation(Location location) { + this.location = location.clone(); + updatePacket(); + + PacketPlayOutEntityTeleport packet = createTeleportPacket(); + location.getWorld().getPlayers().forEach(player -> sendPackets(player, packet)); + } + + @Override + public void setText(String text) { + this.text = text; + + dataWatcher.register(nameVisible, !text.isEmpty()); + dataWatcher.register(customName, text); + + Packet metadataPacket = new PacketPlayOutEntityMetadata(id, dataWatcher, true); + location.getWorld().getPlayers().forEach(player -> sendPackets(player, metadataPacket)); + } + + @Override + public void showPlayer(Player player) { + if (player == null || !player.isOnline()) { + return; + } + + sendPackets(player, spawnPacket, new PacketPlayOutEntityMetadata(id, dataWatcher, true)); + } + + @Override + public void hidePlayer(Player player) { + if (player == null || !player.isOnline()) { + return; + } + + sendPackets(player, new PacketPlayOutEntityDestroy(id)); + } + + @Override + public void destroy() { + location.getWorld().getPlayers().forEach(player -> hidePlayer(player)); + } + + private void sendPackets(Player player, Packet... packets) { + PlayerConnection con = ((CraftPlayer) player).getHandle().playerConnection; + Arrays.stream(packets).forEach(packet -> con.sendPacket(packet)); + } + + private PacketPlayOutEntityTeleport createTeleportPacket() { + PacketDataSerializer s = new PacketDataSerializer(Unpooled.buffer()); + s.d(id); // id + s.writeDouble(location.getX()); // x + s.writeDouble(location.getY() + 1.975); // y + s.writeDouble(location.getZ()); // z + s.writeByte(0); // yaw + s.writeByte(0); // pitch + s.writeBoolean(true); // on ground + + try { + PacketPlayOutEntityTeleport packet = new PacketPlayOutEntityTeleport(); + packet.a(s); + return packet; + } catch (IOException e) { + e.printStackTrace(); + } finally { + s.release(); + } + + return null; + } + + private void updatePacket() { + PacketDataSerializer s = new PacketDataSerializer(Unpooled.buffer()); + s.d(id); // id + s.a(UUID.randomUUID()); // uuid + s.writeByte(78); // type + s.writeDouble(location.getX()); // x + s.writeDouble(location.getY() + 1.975); // y + s.writeDouble(location.getZ()); // z + s.writeByte(0); // pitch + s.writeByte(0); // yaw + s.writeInt(0); // ? + s.writeShort(0); // mot x + s.writeShort(0); // mot y + s.writeShort(0); // mot z + + try { + spawnPacket.a(s); + } catch (IOException e) { + e.printStackTrace(); + } finally { + s.release(); + } + } + + @SuppressWarnings("unchecked") + private DataWatcher createDataWatcher() { + try { + Field fEntityFlags = Entity.class.getDeclaredField("ay"); + Field fAirTicks = Entity.class.getDeclaredField("az"); + Field fNameVisible = Entity.class.getDeclaredField("aB"); + Field fCustomName = Entity.class.getDeclaredField("aA"); + + setAccessible(fEntityFlags, fAirTicks, fNameVisible, fCustomName); + + nameVisible = (DataWatcherObject) fNameVisible.get(null); + customName = (DataWatcherObject>) fCustomName.get(null); + DataWatcherObject entityFlags = (DataWatcherObject) fEntityFlags.get(null); + DataWatcherObject airTicks = (DataWatcherObject) fAirTicks.get(null); + DataWatcherObject armorStandFlags = EntityArmorStand.a; + + DataWatcher dataWatcher = new DataWatcher(null); + dataWatcher.register(entityFlags, (byte) 0b100000); + dataWatcher.register(airTicks, 300); + dataWatcher.register(nameVisible, !text.isEmpty()); + dataWatcher.register(customName, text); + dataWatcher.register(armorStandFlags, (byte) 0b10000); + + return dataWatcher; + } catch (ReflectiveOperationException e) { + e.printStackTrace(); + } + + return null; + } + + private void setAccessible(AccessibleObject... args) { + Arrays.stream(args).forEach(arg -> arg.setAccessible(true)); + } +} \ No newline at end of file