mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2025-07-20 19:22:48 +00:00
167 lines
7.0 KiB
Java
167 lines
7.0 KiB
Java
package com.volmit.iris.util;
|
|
|
|
import org.bukkit.Color;
|
|
import org.bukkit.World;
|
|
import org.bukkit.entity.Player;
|
|
import org.bukkit.inventory.ItemStack;
|
|
import org.bukkit.material.MaterialData;
|
|
|
|
import java.lang.reflect.Constructor;
|
|
import java.lang.reflect.Field;
|
|
import java.lang.reflect.Method;
|
|
|
|
/**
|
|
* Legacy particle sender with NMS for 1.7/1.8 servers
|
|
*
|
|
* @author MrMicky
|
|
*/
|
|
@SuppressWarnings("deprecation")
|
|
class ParticleSenderLegacy implements ParticleSender {
|
|
|
|
private static final boolean SERVER_IS_1_8;
|
|
|
|
private static final Constructor<?> PACKET_PARTICLE;
|
|
private static final Class<?> ENUM_PARTICLE;
|
|
|
|
private static final Method WORLD_GET_HANDLE;
|
|
private static final Method WORLD_SEND_PARTICLE;
|
|
|
|
private static final Method PLAYER_GET_HANDLE;
|
|
private static final Field PLAYER_CONNECTION;
|
|
private static final Method SEND_PACKET;
|
|
private static final int[] EMPTY = new int[0];
|
|
|
|
static {
|
|
ENUM_PARTICLE = FastReflection.nmsOptionalClass("EnumParticle").orElse(null);
|
|
SERVER_IS_1_8 = ENUM_PARTICLE != null;
|
|
|
|
try {
|
|
Class<?> packetParticleClass = FastReflection.nmsClass("PacketPlayOutWorldParticles");
|
|
Class<?> playerClass = FastReflection.nmsClass("EntityPlayer");
|
|
Class<?> playerConnectionClass = FastReflection.nmsClass("PlayerConnection");
|
|
Class<?> worldClass = FastReflection.nmsClass("WorldServer");
|
|
Class<?> entityPlayerClass = FastReflection.nmsClass("EntityPlayer");
|
|
|
|
Class<?> craftPlayerClass = FastReflection.obcClass("entity.CraftPlayer");
|
|
Class<?> craftWorldClass = FastReflection.obcClass("CraftWorld");
|
|
|
|
if (SERVER_IS_1_8) {
|
|
PACKET_PARTICLE = packetParticleClass.getConstructor(ENUM_PARTICLE, boolean.class, float.class,
|
|
float.class, float.class, float.class, float.class, float.class, float.class, int.class,
|
|
int[].class);
|
|
WORLD_SEND_PARTICLE = worldClass.getDeclaredMethod("sendParticles", entityPlayerClass, ENUM_PARTICLE,
|
|
boolean.class, double.class, double.class, double.class, int.class, double.class, double.class,
|
|
double.class, double.class, int[].class);
|
|
} else {
|
|
PACKET_PARTICLE = packetParticleClass.getConstructor(String.class, float.class, float.class, float.class,
|
|
float.class, float.class, float.class, float.class, int.class);
|
|
WORLD_SEND_PARTICLE = worldClass.getDeclaredMethod("a", String.class, double.class, double.class,
|
|
double.class, int.class, double.class, double.class, double.class, double.class);
|
|
}
|
|
|
|
WORLD_GET_HANDLE = craftWorldClass.getDeclaredMethod("getHandle");
|
|
PLAYER_GET_HANDLE = craftPlayerClass.getDeclaredMethod("getHandle");
|
|
PLAYER_CONNECTION = playerClass.getField("playerConnection");
|
|
SEND_PACKET = playerConnectionClass.getMethod("sendPacket", FastReflection.nmsClass("Packet"));
|
|
} catch (ReflectiveOperationException e) {
|
|
throw new ExceptionInInitializerError(e);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void spawnParticle(Object receiver, ParticleType particle, double x, double y, double z, int count, double offsetX, double offsetY,
|
|
double offsetZ, double extra, Object data) {
|
|
try {
|
|
int[] datas = toData(particle, data);
|
|
|
|
if (data instanceof Color) {
|
|
if (particle.getDataType() == Color.class) {
|
|
Color color = (Color) data;
|
|
count = 0;
|
|
offsetX = color(color.getRed());
|
|
offsetY = color(color.getGreen());
|
|
offsetZ = color(color.getBlue());
|
|
extra = 1.0;
|
|
}
|
|
}
|
|
|
|
if (receiver instanceof World) {
|
|
Object worldServer = WORLD_GET_HANDLE.invoke(receiver);
|
|
|
|
if (SERVER_IS_1_8) {
|
|
WORLD_SEND_PARTICLE.invoke(worldServer, null, getEnumParticle(particle), true, x, y, z, count, offsetX, offsetY, offsetZ, extra, datas);
|
|
} else {
|
|
String particleName = particle.getLegacyName() + (datas.length != 2 ? "" : "_" + datas[0] + "_" + datas[1]);
|
|
WORLD_SEND_PARTICLE.invoke(worldServer, particleName, x, y, z, count, offsetX, offsetY, offsetZ, extra);
|
|
}
|
|
} else if (receiver instanceof Player) {
|
|
Object packet;
|
|
|
|
if (SERVER_IS_1_8) {
|
|
packet = PACKET_PARTICLE.newInstance(getEnumParticle(particle), true, (float) x, (float) y,
|
|
(float) z, (float) offsetX, (float) offsetY, (float) offsetZ, (float) extra, count, datas);
|
|
} else {
|
|
String particleName = particle.getLegacyName() + (datas.length != 2 ? "" : "_" + datas[0] + "_" + datas[1]);
|
|
packet = PACKET_PARTICLE.newInstance(particleName, (float) x, (float) y, (float) z,
|
|
(float) offsetX, (float) offsetY, (float) offsetZ, (float) extra, count);
|
|
}
|
|
|
|
Object entityPlayer = PLAYER_GET_HANDLE.invoke(receiver);
|
|
Object playerConnection = PLAYER_CONNECTION.get(entityPlayer);
|
|
SEND_PACKET.invoke(playerConnection, packet);
|
|
}
|
|
} catch (ReflectiveOperationException e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean isValidData(Object particle, Object data) {
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public Object getParticle(ParticleType particle) {
|
|
if (!SERVER_IS_1_8) {
|
|
return particle.getLegacyName();
|
|
}
|
|
|
|
try {
|
|
return getEnumParticle(particle);
|
|
} catch (IllegalArgumentException e) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private Object getEnumParticle(ParticleType particleType) {
|
|
return FastReflection.enumValueOf(ENUM_PARTICLE, particleType.toString());
|
|
}
|
|
|
|
private int[] toData(ParticleType particle, Object data) {
|
|
Class<?> dataType = particle.getDataType();
|
|
if (dataType == ItemStack.class) {
|
|
if (!(data instanceof ItemStack)) {
|
|
return SERVER_IS_1_8 ? new int[2] : new int[]{1, 0};
|
|
}
|
|
|
|
ItemStack itemStack = (ItemStack) data;
|
|
return new int[]{itemStack.getType().getId(), itemStack.getDurability()};
|
|
}
|
|
|
|
if (dataType == MaterialData.class) {
|
|
if (!(data instanceof MaterialData)) {
|
|
return SERVER_IS_1_8 ? new int[1] : new int[]{1, 0};
|
|
}
|
|
|
|
MaterialData materialData = (MaterialData) data;
|
|
if (SERVER_IS_1_8) {
|
|
return new int[]{materialData.getItemType().getId() + (materialData.getData() << 12)};
|
|
} else {
|
|
return new int[]{materialData.getItemType().getId(), materialData.getData()};
|
|
}
|
|
}
|
|
|
|
return EMPTY;
|
|
}
|
|
}
|