Fix armor stands spawn in nether and end + Reflection

This commit is contained in:
MrMicky
2018-04-25 14:41:24 +02:00
parent 2d3f6e46a3
commit 41821c8783
@@ -6,6 +6,7 @@ package net.jitse.npclib.nms.holograms;
import com.comphenix.tinyprotocol.Reflection; import com.comphenix.tinyprotocol.Reflection;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.util.ArrayList; import java.util.ArrayList;
@@ -25,49 +26,49 @@ public class Hologram {
private Set<Object> destroyPackets = new HashSet<>(); private Set<Object> destroyPackets = new HashSet<>();
// Classes: // Classes:
private final Class<?> entityArmorStandClazz = Reflection.getMinecraftClass("EntityArmorStand"); private static final Class<?> ENTITY_ARMOR_STAND_CLAZZ = Reflection.getMinecraftClass("EntityArmorStand");
private final Class<?> entityLivingClazz = Reflection.getMinecraftClass("EntityLiving"); private static final Class<?> ENTITY_LIVING_CLAZZ = Reflection.getMinecraftClass("EntityLiving");
private final Class<?> entityClazz = Reflection.getMinecraftClass("Entity"); private static final Class<?> ENTITY_CLAZZ = Reflection.getMinecraftClass("Entity");
private final Class<?> craftWorldClazz = Reflection.getCraftBukkitClass("CraftWorld"); private static final Class<?> CRAFT_BUKKIT_CLASS = Reflection.getCraftBukkitClass("CraftWorld");
private final Class<?> craftPlayerClazz = Reflection.getCraftBukkitClass("entity.CraftPlayer"); private static final Class<?> CRAFT_PLAYER_CLAZZ = Reflection.getCraftBukkitClass("entity.CraftPlayer");
private final Class<?> packetPlayOutSpawnEntityLivingClazz = Reflection.getMinecraftClass( private static final Class<?> PACKET_PLAY_OUT_SPAWN_ENTITY_LIVING_CLAZZ = Reflection.getMinecraftClass(
"PacketPlayOutSpawnEntityLiving"); "PacketPlayOutSpawnEntityLiving");
private final Class<?> packetPlayOutEntityDestroyClazz = Reflection.getMinecraftClass( private static final Class<?> PACKET_PLAY_OUT_ENTITY_DESTROY_CLAZZ = Reflection.getMinecraftClass(
"PacketPlayOutEntityDestroy"); "PacketPlayOutEntityDestroy");
private final Class<?> entityPlayerClazz = Reflection.getMinecraftClass("EntityPlayer"); private static final Class<?> ENTITY_PLAYER_CLAZZ = Reflection.getMinecraftClass("EntityPlayer");
private final Class<?> playerConnectionClazz = Reflection.getMinecraftClass("PlayerConnection"); private static final Class<?> PLAYER_CONNECTION_CLAZZ = Reflection.getMinecraftClass("PlayerConnection");
private final Class<?> packetClazz = Reflection.getMinecraftClass("Packet"); private static final Class<?> PACKET_CLAZZ = Reflection.getMinecraftClass("Packet");
// Constructors: // Constructors:
private final Reflection.ConstructorInvoker packetPlayOutSpawnEntityLivingConstructor = Reflection private static final Reflection.ConstructorInvoker PACKET_PLAY_OUT_SPAWN_ENTITY_LIVING_CONSTRUCTOR = Reflection
.getConstructor(packetPlayOutSpawnEntityLivingClazz, entityLivingClazz); .getConstructor(PACKET_PLAY_OUT_SPAWN_ENTITY_LIVING_CLAZZ, ENTITY_LIVING_CLAZZ);
private final Reflection.ConstructorInvoker packetPlayOutEntityDestroyConstructor = Reflection private static final Reflection.ConstructorInvoker PACKET_PLAY_OUT_ENTITY_DESTROY_CONSTRUCTOR = Reflection
.getConstructor(packetPlayOutEntityDestroyClazz, int[].class); .getConstructor(PACKET_PLAY_OUT_ENTITY_DESTROY_CLAZZ, int[].class);
// Fields: // Fields:
private final Reflection.FieldAccessor playerConnectionField = Reflection.getField(entityPlayerClazz, private static final Reflection.FieldAccessor playerConnectionField = Reflection.getField(ENTITY_PLAYER_CLAZZ,
"playerConnection", playerConnectionClazz); "playerConnection", PLAYER_CONNECTION_CLAZZ);
// Methods: // Methods:
private final Reflection.MethodInvoker setLocationMethod = Reflection.getMethod(entityArmorStandClazz, private static final Reflection.MethodInvoker SET_LOCATION_METHOD = Reflection.getMethod(ENTITY_ARMOR_STAND_CLAZZ,
"setLocation", double.class, double.class, double.class, float.class, float.class); "setLocation", double.class, double.class, double.class, float.class, float.class);
private final Reflection.MethodInvoker setCustomNameMethod = Reflection.getMethod(entityArmorStandClazz, private static final Reflection.MethodInvoker SET_CUSTOM_NAME_METHOD = Reflection.getMethod(ENTITY_ARMOR_STAND_CLAZZ,
"setCustomName", String.class); "setCustomName", String.class);
private final Reflection.MethodInvoker setCustomNameVisibleMethod = Reflection.getMethod(entityArmorStandClazz, private static final Reflection.MethodInvoker SET_CUSTOM_NAME_VISIBLE_METHOD = Reflection.getMethod(ENTITY_ARMOR_STAND_CLAZZ,
"setCustomNameVisible", boolean.class); "setCustomNameVisible", boolean.class);
private final Reflection.MethodInvoker setSmallMethod = Reflection.getMethod(entityArmorStandClazz, private static final Reflection.MethodInvoker SET_SMALL_METHOD = Reflection.getMethod(ENTITY_ARMOR_STAND_CLAZZ,
"setSmall", boolean.class); "setSmall", boolean.class);
private final Reflection.MethodInvoker setInvisibleMethod = Reflection.getMethod(entityArmorStandClazz, private static final Reflection.MethodInvoker SET_INVISIBLE_METHOD = Reflection.getMethod(ENTITY_ARMOR_STAND_CLAZZ,
"setInvisible", boolean.class); "setInvisible", boolean.class);
private final Reflection.MethodInvoker setBasePlateMethod = Reflection.getMethod(entityArmorStandClazz, private static final Reflection.MethodInvoker SET_BASE_PLATE_METHOD = Reflection.getMethod(ENTITY_ARMOR_STAND_CLAZZ,
"setBasePlate", boolean.class); "setBasePlate", boolean.class);
private final Reflection.MethodInvoker setArmsMethod = Reflection.getMethod(entityArmorStandClazz, private static final Reflection.MethodInvoker SET_ARMS_METHOD = Reflection.getMethod(ENTITY_ARMOR_STAND_CLAZZ,
"setArms", boolean.class); "setArms", boolean.class);
private final Reflection.MethodInvoker playerGetHandleMethod = Reflection.getMethod(craftPlayerClazz, private static final Reflection.MethodInvoker PLAYER_GET_HANDLE_METHOD = Reflection.getMethod(CRAFT_PLAYER_CLAZZ,
"getHandle"); "getHandle");
private final Reflection.MethodInvoker sendPacketMethod = Reflection.getMethod(playerConnectionClazz, private static final Reflection.MethodInvoker SEND_PACKET_METHOD = Reflection.getMethod(PLAYER_CONNECTION_CLAZZ,
"sendPacket", packetClazz); "sendPacket", PACKET_CLAZZ);
private final Reflection.MethodInvoker getIdMethod = Reflection.getMethod(entityArmorStandClazz, private static final Reflection.MethodInvoker GET_ID_METHOD = Reflection.getMethod(ENTITY_ARMOR_STAND_CLAZZ,
"getId"); "getId");
private final Location start; private final Location start;
@@ -78,32 +79,37 @@ public class Hologram {
this.start = location; this.start = location;
this.lines = lines; this.lines = lines;
this.worldServer = Reflection.getMethod(craftWorldClazz, "getHandle") this.worldServer = Reflection.getMethod(CRAFT_BUKKIT_CLASS, "getHandle")
.invoke(craftWorldClazz.cast(location.getWorld())); .invoke(CRAFT_BUKKIT_CLASS.cast(location.getWorld()));
} }
public void generatePackets(boolean above1_9_r2) { public void generatePackets(boolean above1_9_r2) {
Reflection.MethodInvoker gravityMethod = (above1_9_r2 ? Reflection.getMethod(entityClazz, Reflection.MethodInvoker gravityMethod = (above1_9_r2 ? Reflection.getMethod(ENTITY_CLAZZ,
"setNoGravity", boolean.class) : Reflection.getMethod(entityArmorStandClazz, "setNoGravity", boolean.class) : Reflection.getMethod(ENTITY_ARMOR_STAND_CLAZZ,
"setGravity", boolean.class)); "setGravity", boolean.class));
Location location = start.clone().add(0, delta * lines.size(), 0); Location location = start.clone().add(0, delta * lines.size(), 0);
Class<?> worldClass = worldServer.getClass().getSuperclass();
if (start.getWorld().getEnvironment() != World.Environment.NORMAL) {
worldClass = worldClass.getSuperclass();
}
Reflection.ConstructorInvoker entityArmorStandConstructor = Reflection Reflection.ConstructorInvoker entityArmorStandConstructor = Reflection
.getConstructor(entityArmorStandClazz, worldServer.getClass().getSuperclass()); .getConstructor(ENTITY_ARMOR_STAND_CLAZZ, worldClass);
for (String line : lines) { for (String line : lines) {
Object entityArmorStand = entityArmorStandConstructor.invoke(worldServer); Object entityArmorStand = entityArmorStandConstructor.invoke(worldServer);
setLocationMethod.invoke(entityArmorStand, location.getX(), location.getY(), location.getZ(), 0, 0); SET_LOCATION_METHOD.invoke(entityArmorStand, location.getX(), location.getY(), location.getZ(), 0, 0);
setCustomNameMethod.invoke(entityArmorStand, line); SET_CUSTOM_NAME_METHOD.invoke(entityArmorStand, line);
setCustomNameVisibleMethod.invoke(entityArmorStand, true); SET_CUSTOM_NAME_VISIBLE_METHOD.invoke(entityArmorStand, true);
gravityMethod.invoke(entityArmorStand, (above1_9_r2 ? true : false)); gravityMethod.invoke(entityArmorStand, above1_9_r2);
setSmallMethod.invoke(entityArmorStand, true); SET_SMALL_METHOD.invoke(entityArmorStand, true);
setInvisibleMethod.invoke(entityArmorStand, true); SET_INVISIBLE_METHOD.invoke(entityArmorStand, true);
setBasePlateMethod.invoke(entityArmorStand, false); SET_BASE_PLATE_METHOD.invoke(entityArmorStand, false);
setArmsMethod.invoke(entityArmorStand, false); SET_ARMS_METHOD.invoke(entityArmorStand, false);
location.subtract(0, delta, 0); location.subtract(0, delta, 0);
@@ -113,30 +119,30 @@ public class Hologram {
armorStands.add(entityArmorStand); armorStands.add(entityArmorStand);
Object spawnPacket = packetPlayOutSpawnEntityLivingConstructor.invoke(entityArmorStand); Object spawnPacket = PACKET_PLAY_OUT_SPAWN_ENTITY_LIVING_CONSTRUCTOR.invoke(entityArmorStand);
spawnPackets.add(spawnPacket); spawnPackets.add(spawnPacket);
Object destroyPacket = packetPlayOutEntityDestroyConstructor Object destroyPacket = PACKET_PLAY_OUT_ENTITY_DESTROY_CONSTRUCTOR
.invoke(new int[]{(int) getIdMethod.invoke(entityArmorStand)}); .invoke(new int[]{(int) GET_ID_METHOD.invoke(entityArmorStand)});
destroyPackets.add(destroyPacket); destroyPackets.add(destroyPacket);
} }
} }
public void spawn(Player player) { public void spawn(Player player) {
Object playerConnection = playerConnectionField.get(playerGetHandleMethod Object playerConnection = playerConnectionField.get(PLAYER_GET_HANDLE_METHOD
.invoke(craftPlayerClazz.cast(player))); .invoke(CRAFT_PLAYER_CLAZZ.cast(player)));
for (Object packet : spawnPackets) { for (Object packet : spawnPackets) {
sendPacketMethod.invoke(playerConnection, packet); SEND_PACKET_METHOD.invoke(playerConnection, packet);
} }
} }
public void destroy(Player player) { public void destroy(Player player) {
Object playerConnection = playerConnectionField.get(playerGetHandleMethod Object playerConnection = playerConnectionField.get(PLAYER_GET_HANDLE_METHOD
.invoke(craftPlayerClazz.cast(player))); .invoke(CRAFT_PLAYER_CLAZZ.cast(player)));
for (Object packet : destroyPackets) { for (Object packet : destroyPackets) {
sendPacketMethod.invoke(playerConnection, packet); SEND_PACKET_METHOD.invoke(playerConnection, packet);
} }
} }
} }