mirror of
https://github.com/EpicEricEE/ShopChest.git
synced 2024-11-25 03:55:22 +01:00
Add NMS hologram line implementations
This commit is contained in:
parent
2d832e587a
commit
30de267f1e
@ -12,7 +12,7 @@
|
||||
<modules>
|
||||
<module>interfaces</module>
|
||||
<module>v8r1</module>
|
||||
<!-- <module>v8r2</module>
|
||||
<module>v8r2</module>
|
||||
<module>v8r3</module>
|
||||
<module>v9r1</module>
|
||||
<module>v9r2</module>
|
||||
@ -21,7 +21,7 @@
|
||||
<module>v12r1</module>
|
||||
<module>v13r1</module>
|
||||
<module>v13r2</module>
|
||||
<module>v14r1</module> -->
|
||||
<module>v14r1</module>
|
||||
<module>v15r1</module>
|
||||
</modules>
|
||||
|
||||
|
34
nms/v10r1/pom.xml
Normal file
34
nms/v10r1/pom.xml
Normal file
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>de.epiceric.shopchest</groupId>
|
||||
<artifactId>shopchest-nms-v10r1</artifactId>
|
||||
<version>1.13-SNAPSHOT</version>
|
||||
|
||||
<name>ShopChest NMS v1.10-R1</name>
|
||||
|
||||
<parent>
|
||||
<groupId>de.epiceric.shopchest</groupId>
|
||||
<artifactId>shopchest-nms</artifactId>
|
||||
<version>1.13-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>de.epiceric.shopchest</groupId>
|
||||
<artifactId>shopchest-nms-interfaces</artifactId>
|
||||
<version>1.13-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>craftbukkit</artifactId>
|
||||
<version>1.10-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@ -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<Boolean> nameVisible;
|
||||
private DataWatcherObject<Optional<IChatBaseComponent>> 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<Boolean>) fNameVisible.get(null);
|
||||
customName = (DataWatcherObject<Optional<IChatBaseComponent>>) fCustomName.get(null);
|
||||
DataWatcherObject<Byte> entityFlags = (DataWatcherObject<Byte>) fEntityFlags.get(null);
|
||||
DataWatcherObject<Integer> airTicks = (DataWatcherObject<Integer>) fAirTicks.get(null);
|
||||
DataWatcherObject<Boolean> noGravity = (DataWatcherObject<Boolean>) fNoGravity.get(null);
|
||||
DataWatcherObject<Byte> 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));
|
||||
}
|
||||
}
|
34
nms/v11r1/pom.xml
Normal file
34
nms/v11r1/pom.xml
Normal file
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>de.epiceric.shopchest</groupId>
|
||||
<artifactId>shopchest-nms-v11r1</artifactId>
|
||||
<version>1.13-SNAPSHOT</version>
|
||||
|
||||
<name>ShopChest NMS v1.11-R1</name>
|
||||
|
||||
<parent>
|
||||
<groupId>de.epiceric.shopchest</groupId>
|
||||
<artifactId>shopchest-nms</artifactId>
|
||||
<version>1.13-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>de.epiceric.shopchest</groupId>
|
||||
<artifactId>shopchest-nms-interfaces</artifactId>
|
||||
<version>1.13-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>craftbukkit</artifactId>
|
||||
<version>1.11.2-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@ -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<Boolean> nameVisible;
|
||||
private DataWatcherObject<Optional<IChatBaseComponent>> 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<Boolean>) fNameVisible.get(null);
|
||||
customName = (DataWatcherObject<Optional<IChatBaseComponent>>) fCustomName.get(null);
|
||||
DataWatcherObject<Byte> entityFlags = (DataWatcherObject<Byte>) fEntityFlags.get(null);
|
||||
DataWatcherObject<Integer> airTicks = (DataWatcherObject<Integer>) fAirTicks.get(null);
|
||||
DataWatcherObject<Boolean> noGravity = (DataWatcherObject<Boolean>) fNoGravity.get(null);
|
||||
DataWatcherObject<Byte> 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));
|
||||
}
|
||||
}
|
34
nms/v12r1/pom.xml
Normal file
34
nms/v12r1/pom.xml
Normal file
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>de.epiceric.shopchest</groupId>
|
||||
<artifactId>shopchest-nms-v12r1</artifactId>
|
||||
<version>1.13-SNAPSHOT</version>
|
||||
|
||||
<name>ShopChest NMS v1.12-R1</name>
|
||||
|
||||
<parent>
|
||||
<groupId>de.epiceric.shopchest</groupId>
|
||||
<artifactId>shopchest-nms</artifactId>
|
||||
<version>1.13-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>de.epiceric.shopchest</groupId>
|
||||
<artifactId>shopchest-nms-interfaces</artifactId>
|
||||
<version>1.13-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>craftbukkit</artifactId>
|
||||
<version>1.12.2-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@ -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<Boolean> nameVisible;
|
||||
private DataWatcherObject<Optional<IChatBaseComponent>> 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<Boolean>) fNameVisible.get(null);
|
||||
customName = (DataWatcherObject<Optional<IChatBaseComponent>>) fCustomName.get(null);
|
||||
DataWatcherObject<Byte> entityFlags = (DataWatcherObject<Byte>) fEntityFlags.get(null);
|
||||
DataWatcherObject<Integer> airTicks = (DataWatcherObject<Integer>) fAirTicks.get(null);
|
||||
DataWatcherObject<Boolean> noGravity = (DataWatcherObject<Boolean>) fNoGravity.get(null);
|
||||
DataWatcherObject<Byte> 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));
|
||||
}
|
||||
}
|
34
nms/v13r1/pom.xml
Normal file
34
nms/v13r1/pom.xml
Normal file
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>de.epiceric.shopchest</groupId>
|
||||
<artifactId>shopchest-nms-v13r1</artifactId>
|
||||
<version>1.13-SNAPSHOT</version>
|
||||
|
||||
<name>ShopChest NMS v1.13-R1</name>
|
||||
|
||||
<parent>
|
||||
<groupId>de.epiceric.shopchest</groupId>
|
||||
<artifactId>shopchest-nms</artifactId>
|
||||
<version>1.13-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>de.epiceric.shopchest</groupId>
|
||||
<artifactId>shopchest-nms-interfaces</artifactId>
|
||||
<version>1.13-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>craftbukkit</artifactId>
|
||||
<version>1.13-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@ -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<Boolean> nameVisible;
|
||||
private DataWatcherObject<Optional<IChatBaseComponent>> 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<Boolean>) fNameVisible.get(null);
|
||||
customName = (DataWatcherObject<Optional<IChatBaseComponent>>) fCustomName.get(null);
|
||||
DataWatcherObject<Byte> entityFlags = (DataWatcherObject<Byte>) fEntityFlags.get(null);
|
||||
DataWatcherObject<Integer> airTicks = (DataWatcherObject<Integer>) fAirTicks.get(null);
|
||||
DataWatcherObject<Boolean> noGravity = (DataWatcherObject<Boolean>) fNoGravity.get(null);
|
||||
DataWatcherObject<Byte> 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));
|
||||
}
|
||||
}
|
34
nms/v13r2/pom.xml
Normal file
34
nms/v13r2/pom.xml
Normal file
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>de.epiceric.shopchest</groupId>
|
||||
<artifactId>shopchest-nms-v13r2</artifactId>
|
||||
<version>1.13-SNAPSHOT</version>
|
||||
|
||||
<name>ShopChest NMS v1.13-R2</name>
|
||||
|
||||
<parent>
|
||||
<groupId>de.epiceric.shopchest</groupId>
|
||||
<artifactId>shopchest-nms</artifactId>
|
||||
<version>1.13-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>de.epiceric.shopchest</groupId>
|
||||
<artifactId>shopchest-nms-interfaces</artifactId>
|
||||
<version>1.13-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>craftbukkit</artifactId>
|
||||
<version>1.13.2-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@ -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<Boolean> nameVisible;
|
||||
private DataWatcherObject<Optional<IChatBaseComponent>> 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<Boolean>) fNameVisible.get(null);
|
||||
customName = (DataWatcherObject<Optional<IChatBaseComponent>>) fCustomName.get(null);
|
||||
DataWatcherObject<Byte> entityFlags = (DataWatcherObject<Byte>) fEntityFlags.get(null);
|
||||
DataWatcherObject<Integer> airTicks = (DataWatcherObject<Integer>) fAirTicks.get(null);
|
||||
DataWatcherObject<Boolean> noGravity = (DataWatcherObject<Boolean>) fNoGravity.get(null);
|
||||
DataWatcherObject<Byte> 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));
|
||||
}
|
||||
}
|
34
nms/v14r1/pom.xml
Normal file
34
nms/v14r1/pom.xml
Normal file
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>de.epiceric.shopchest</groupId>
|
||||
<artifactId>shopchest-nms-v14r1</artifactId>
|
||||
<version>1.13-SNAPSHOT</version>
|
||||
|
||||
<name>ShopChest NMS v1.14-R1</name>
|
||||
|
||||
<parent>
|
||||
<groupId>de.epiceric.shopchest</groupId>
|
||||
<artifactId>shopchest-nms</artifactId>
|
||||
<version>1.13-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>de.epiceric.shopchest</groupId>
|
||||
<artifactId>shopchest-nms-interfaces</artifactId>
|
||||
<version>1.13-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>craftbukkit</artifactId>
|
||||
<version>1.14.3-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@ -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<Boolean> nameVisible;
|
||||
private DataWatcherObject<Optional<IChatBaseComponent>> 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<Boolean>) fNameVisible.get(null);
|
||||
customName = (DataWatcherObject<Optional<IChatBaseComponent>>) fCustomName.get(null);
|
||||
DataWatcherObject<Byte> entityFlags = (DataWatcherObject<Byte>) fEntityFlags.get(null);
|
||||
DataWatcherObject<Integer> airTicks = (DataWatcherObject<Integer>) fAirTicks.get(null);
|
||||
DataWatcherObject<Boolean> noGravity = (DataWatcherObject<Boolean>) fNoGravity.get(null);
|
||||
DataWatcherObject<Byte> 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));
|
||||
}
|
||||
}
|
@ -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<Boolean> 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));
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
34
nms/v8r2/pom.xml
Normal file
34
nms/v8r2/pom.xml
Normal file
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>de.epiceric.shopchest</groupId>
|
||||
<artifactId>shopchest-nms-v8r2</artifactId>
|
||||
<version>1.13-SNAPSHOT</version>
|
||||
|
||||
<name>ShopChest NMS v1.8-R2</name>
|
||||
|
||||
<parent>
|
||||
<groupId>de.epiceric.shopchest</groupId>
|
||||
<artifactId>shopchest-nms</artifactId>
|
||||
<version>1.13-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>de.epiceric.shopchest</groupId>
|
||||
<artifactId>shopchest-nms-interfaces</artifactId>
|
||||
<version>1.13-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>craftbukkit</artifactId>
|
||||
<version>1.8.3-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@ -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;
|
||||
}
|
||||
}
|
34
nms/v8r3/pom.xml
Normal file
34
nms/v8r3/pom.xml
Normal file
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>de.epiceric.shopchest</groupId>
|
||||
<artifactId>shopchest-nms-v8r3</artifactId>
|
||||
<version>1.13-SNAPSHOT</version>
|
||||
|
||||
<name>ShopChest NMS v1.8-R3</name>
|
||||
|
||||
<parent>
|
||||
<groupId>de.epiceric.shopchest</groupId>
|
||||
<artifactId>shopchest-nms</artifactId>
|
||||
<version>1.13-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>de.epiceric.shopchest</groupId>
|
||||
<artifactId>shopchest-nms-interfaces</artifactId>
|
||||
<version>1.13-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>craftbukkit</artifactId>
|
||||
<version>1.8.8-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@ -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;
|
||||
}
|
||||
}
|
34
nms/v9r1/pom.xml
Normal file
34
nms/v9r1/pom.xml
Normal file
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>de.epiceric.shopchest</groupId>
|
||||
<artifactId>shopchest-nms-v9r1</artifactId>
|
||||
<version>1.13-SNAPSHOT</version>
|
||||
|
||||
<name>ShopChest NMS v1.9-R1</name>
|
||||
|
||||
<parent>
|
||||
<groupId>de.epiceric.shopchest</groupId>
|
||||
<artifactId>shopchest-nms</artifactId>
|
||||
<version>1.13-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>de.epiceric.shopchest</groupId>
|
||||
<artifactId>shopchest-nms-interfaces</artifactId>
|
||||
<version>1.13-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>craftbukkit</artifactId>
|
||||
<version>1.9.2-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@ -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<Boolean> nameVisible;
|
||||
private DataWatcherObject<Optional<IChatBaseComponent>> 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<Boolean>) fNameVisible.get(null);
|
||||
customName = (DataWatcherObject<Optional<IChatBaseComponent>>) fCustomName.get(null);
|
||||
DataWatcherObject<Byte> entityFlags = (DataWatcherObject<Byte>) fEntityFlags.get(null);
|
||||
DataWatcherObject<Integer> airTicks = (DataWatcherObject<Integer>) fAirTicks.get(null);
|
||||
DataWatcherObject<Byte> 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));
|
||||
}
|
||||
}
|
34
nms/v9r2/pom.xml
Normal file
34
nms/v9r2/pom.xml
Normal file
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>de.epiceric.shopchest</groupId>
|
||||
<artifactId>shopchest-nms-v9r2</artifactId>
|
||||
<version>1.13-SNAPSHOT</version>
|
||||
|
||||
<name>ShopChest NMS v1.9-R2</name>
|
||||
|
||||
<parent>
|
||||
<groupId>de.epiceric.shopchest</groupId>
|
||||
<artifactId>shopchest-nms</artifactId>
|
||||
<version>1.13-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>de.epiceric.shopchest</groupId>
|
||||
<artifactId>shopchest-nms-interfaces</artifactId>
|
||||
<version>1.13-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>craftbukkit</artifactId>
|
||||
<version>1.9.4-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@ -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<Boolean> nameVisible;
|
||||
private DataWatcherObject<Optional<IChatBaseComponent>> 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<Boolean>) fNameVisible.get(null);
|
||||
customName = (DataWatcherObject<Optional<IChatBaseComponent>>) fCustomName.get(null);
|
||||
DataWatcherObject<Byte> entityFlags = (DataWatcherObject<Byte>) fEntityFlags.get(null);
|
||||
DataWatcherObject<Integer> airTicks = (DataWatcherObject<Integer>) fAirTicks.get(null);
|
||||
DataWatcherObject<Byte> 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));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user