forked from stefatorus/LagAssist
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
580 lines
16 KiB
580 lines
16 KiB
package com.entryrise.lagassist.packets;
|
|
|
|
import java.lang.reflect.Array;
|
|
import java.lang.reflect.Constructor;
|
|
import java.lang.reflect.Field;
|
|
import java.lang.reflect.Method;
|
|
import java.util.Collection;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
|
|
import org.bukkit.Bukkit;
|
|
import org.bukkit.Location;
|
|
import org.bukkit.World;
|
|
import org.bukkit.block.Block;
|
|
import org.bukkit.command.CommandMap;
|
|
import org.bukkit.command.PluginCommand;
|
|
import org.bukkit.configuration.file.YamlConfiguration;
|
|
import org.bukkit.entity.Entity;
|
|
import org.bukkit.entity.Player;
|
|
import org.bukkit.inventory.ItemStack;
|
|
import org.bukkit.inventory.meta.MapMeta;
|
|
import org.bukkit.map.MapView;
|
|
import org.bukkit.plugin.Plugin;
|
|
import org.bukkit.plugin.SimplePluginManager;
|
|
import org.bukkit.scoreboard.Scoreboard;
|
|
import org.json.simple.JSONObject;
|
|
|
|
import com.entryrise.lagassist.Main;
|
|
import com.entryrise.lagassist.utils.V1_8;
|
|
import com.entryrise.lagassist.utils.VersionMgr;
|
|
|
|
import net.md_5.bungee.api.ChatMessageType;
|
|
import net.md_5.bungee.api.chat.ComponentBuilder;
|
|
|
|
public class Reflection {
|
|
|
|
private static Map<Class<?>, Field[]> cached = new HashMap<Class<?>, Field[]>();
|
|
private static String version = ServerPackage.getServerVersion();
|
|
|
|
public static enum Classes {
|
|
|
|
CraftWorld(), CraftBlock(), CraftPlayer(), Material(), MapMeta(), WorldServer(), ChunkProviderServer(),
|
|
PacketPlayOutTitle(), IChatBaseComponent(), World(), MinecraftServer();
|
|
|
|
private Class<?> type;
|
|
|
|
public Class<?> getType() {
|
|
return type;
|
|
}
|
|
}
|
|
|
|
public static enum Methods {
|
|
|
|
setMapId(), getMapId(), getPlayerHandle(), getBlockType(), getChunkProviderServer(), chunkExists(),
|
|
getIChatBaseComponent(), setViewDistance(), getServer();
|
|
|
|
private Method mthd;
|
|
|
|
public Method getMethod() {
|
|
return mthd;
|
|
}
|
|
}
|
|
|
|
public static void Enabler() {
|
|
|
|
// PUTTING CLASSES IN ENUM.
|
|
Classes.CraftWorld.type = getClass("{cb}.CraftWorld");
|
|
Classes.World.type = getClass("{b}.World");
|
|
Classes.CraftBlock.type = getClass("{cb}.block.CraftBlock");
|
|
Classes.CraftPlayer.type = getClass("{cb}.entity.CraftPlayer");
|
|
Classes.Material.type = getClass("{b}.Material");
|
|
Classes.MapMeta.type = getClass("{b}.inventory.meta.MapMeta");
|
|
Classes.WorldServer.type = getClass(VersionMgr.isV_17Plus() ? "{nms}.level.WorldServer" : "{nms}.WorldServer");
|
|
Classes.MinecraftServer.type = getClass("{nms}.MinecraftServer");
|
|
Classes.ChunkProviderServer.type = getClass(VersionMgr.isV_17Plus() ? "{nms}.level.ChunkProviderServer" : "{nms}.ChunkProviderServer");
|
|
Classes.IChatBaseComponent.type = getClass(VersionMgr.isV_17Plus() ? "{nm}.network.chat.IChatBaseComponent" : "{nms}.IChatBaseComponent");
|
|
// Classes.PacketPlayOutTitle.type = getClass(VersionMgr.isV_17Plus()? "{nm}.network.protocol.game.PacketPlayOutTitle" : "{nms}.PacketPlayOutTitle");
|
|
|
|
// PUTTING METHODS IN ENUM.
|
|
Methods.setMapId.mthd = getMethod(Classes.MapMeta.getType(), "setMapId", int.class);
|
|
Methods.getMapId.mthd = getMethod(Classes.MapMeta.getType(), "getMapId");
|
|
Methods.getPlayerHandle.mthd = getMethod(Classes.CraftPlayer.getType(), "getHandle");
|
|
Methods.getBlockType.mthd = getMethod(Classes.CraftBlock.getType(), "getType");
|
|
Methods.getChunkProviderServer.mthd = getMethod(Classes.WorldServer.getType(), "getChunkProviderServer");
|
|
Methods.getIChatBaseComponent.mthd = getMethod(Classes.IChatBaseComponent.getType(), "a", String.class);
|
|
Methods.chunkExists.mthd = getMethod(Classes.ChunkProviderServer.getType(), VersionMgr.ChunkExistsName(),
|
|
int.class, int.class);
|
|
Methods.setViewDistance.mthd = getMethod(Classes.World.getType(), "setViewDistance", int.class);
|
|
Methods.getServer.mthd = getMethod(Classes.MinecraftServer.getType(), "getServer");
|
|
}
|
|
|
|
@SuppressWarnings("deprecation")
|
|
public static void sendAction(Player player, String s) {
|
|
if (Bukkit.getVersion().contains("1.8")) {
|
|
V1_8.sendActionbar(player, s);
|
|
} else {
|
|
player.spigot().sendMessage(ChatMessageType.ACTION_BAR, new ComponentBuilder(s).create());
|
|
}
|
|
}
|
|
|
|
// public void sendTitle(Player p, int fadein, int stay, int fadeout, String title, String subtitle) {
|
|
// try {
|
|
// Object enumTitle = Classes.PacketPlayOutTitle.getType().getDeclaredClasses()[0].getField("TITLE").get(null);
|
|
// Object enumSubtitle = Classes.PacketPlayOutTitle.getType().getDeclaredClasses()[0].getField("SUBTITLE")
|
|
// .get(null);
|
|
//
|
|
// Object titlebase = runMethod(null, Methods.getIChatBaseComponent.getMethod(),
|
|
// "{\"text\": \"" + title + "\"}");
|
|
// Object subtitlebase = runMethod(null, Methods.getIChatBaseComponent.getMethod(),
|
|
// "{\"text\": \"" + subtitle + "\"}");
|
|
//
|
|
// Class<?> packetcls = Classes.PacketPlayOutTitle.getType();
|
|
// Constructor<?> constr = packetcls.getConstructor(
|
|
// Classes.PacketPlayOutTitle.getType().getDeclaredClasses()[0], Classes.IChatBaseComponent.getType(),
|
|
// int.class, int.class, int.class);
|
|
//
|
|
// Object packetTitle = constr.newInstance(enumTitle, titlebase, fadein, stay, fadeout);
|
|
// Object packetSubtitle = constr.newInstance(enumSubtitle, subtitlebase, fadein, stay, fadeout);
|
|
//
|
|
// sendPlayerPacket(p, packetTitle);
|
|
// sendPlayerPacket(p, packetSubtitle);
|
|
// }
|
|
//
|
|
// catch (Exception e) {
|
|
// e.printStackTrace();
|
|
// }
|
|
// }
|
|
|
|
public static MapView getMapView(int i) {
|
|
Class<?> buk = Bukkit.class;
|
|
|
|
try {
|
|
Method getMap = buk.getDeclaredMethod("getMap", VersionMgr.isNewMaterials() ? int.class : short.class);
|
|
return (MapView) (VersionMgr.isNewMaterials() ? getMap.invoke(null, i) : getMap.invoke(null, (short) i));
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
return null;
|
|
}
|
|
|
|
}
|
|
|
|
private static Object minecraftserver = null;
|
|
public static double getTPS(int number) {
|
|
try {
|
|
if (minecraftserver == null) {
|
|
minecraftserver = Methods.getServer.mthd.invoke(null);
|
|
}
|
|
|
|
Field f = Reflection.getField(Classes.MinecraftServer.type, "recentTps");
|
|
f.setAccessible(true);
|
|
|
|
return ((double[])f.get(minecraftserver))[number];
|
|
} catch(Exception e) {
|
|
e.printStackTrace();
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
public static int getId(MapView view) {
|
|
if (view == null) {
|
|
return 0;
|
|
}
|
|
|
|
Class<?> mv = MapView.class;
|
|
|
|
try {
|
|
Method getMap = mv.getDeclaredMethod("getId");
|
|
Object obj = getMap.invoke(view);
|
|
if (obj instanceof Short) {
|
|
return (short) obj;
|
|
} else if (obj instanceof Integer) {
|
|
return (int) obj;
|
|
}
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
@SuppressWarnings("unchecked")
|
|
static JSONObject convert(String text) {
|
|
JSONObject json = new JSONObject();
|
|
json.put("text", text);
|
|
return json;
|
|
}
|
|
|
|
public static Class<?> getClass(String classname) {
|
|
try {
|
|
|
|
String path = classname.replace("{nms}", "net.minecraft.server" + (VersionMgr.isV_17Plus() ? "" : "." + version))
|
|
.replace("{nm}", "net.minecraft" + (VersionMgr.isV_17Plus() ? "" : "." + version)).replace("{cb}", "org.bukkit.craftbukkit." + version)
|
|
.replace("{b}", "org.bukkit");
|
|
return Class.forName(path);
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public static Object getCraftWorld(World w) {
|
|
Class<?> crwclass = Classes.CraftWorld.getType();
|
|
System.out.println(crwclass.getName());
|
|
Object craftworld = crwclass.cast(w);
|
|
return craftworld;
|
|
}
|
|
|
|
public static Object getWorldServer(Object craftWorld) {
|
|
try {
|
|
return getFieldValue(craftWorld, "world");
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public static Object getChunkProvider(Object worldServer) {
|
|
try {
|
|
return runMethod(worldServer, Methods.getChunkProviderServer.getMethod());
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public static boolean isChunkExistent(Object chunkProvider, int x, int z) {
|
|
try {
|
|
return (boolean) runMethod(chunkProvider, Methods.chunkExists.getMethod(), x, z);
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
// NOTE: ASSUMING TRUE IN ORDER TO IGNORE IF EXCEPTION POPS UP.
|
|
return true;
|
|
}
|
|
|
|
public static boolean isTile(Block b) {
|
|
return !b.getState().getClass().getSimpleName().toLowerCase().contains("craftblockstate");
|
|
}
|
|
|
|
public static Entity getEntity(Location l) {
|
|
try {
|
|
|
|
Collection<Entity> ents = l.getWorld().getNearbyEntities(l, 1, 1, 1);
|
|
for (Entity ent : ents) {
|
|
return ent;
|
|
}
|
|
} catch (Exception e) {
|
|
return null;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public static void setmapId(ItemStack s, int id) {
|
|
MapMeta mapm = (MapMeta) s.getItemMeta();
|
|
try {
|
|
runMethod(mapm, Methods.setMapId.getMethod(), id);
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
s.setItemMeta(mapm);
|
|
}
|
|
|
|
public static int getMapId(ItemStack s) {
|
|
MapMeta mapm = (MapMeta) s.getItemMeta();
|
|
try {
|
|
return (int) runMethod(mapm, Methods.getMapId.getMethod());
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
public static Object getNmsPlayer(Player p) {
|
|
if (p == null) {
|
|
return null;
|
|
}
|
|
Method getHandle;
|
|
try {
|
|
getHandle = p.getClass().getMethod("getHandle");
|
|
return getHandle.invoke(p);
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public static Object getNmsScoreboard(Scoreboard s) throws Exception {
|
|
Method getHandle = s.getClass().getMethod("getHandle");
|
|
return getHandle.invoke(s);
|
|
}
|
|
|
|
public static String getObjectSerialized(Object obj) {
|
|
YamlConfiguration conf = new YamlConfiguration();
|
|
Class<?> cls = obj.getClass();
|
|
String loc = cls.getSimpleName();
|
|
|
|
createObjectSerialized(conf, loc, obj, 0);
|
|
|
|
return conf.saveToString();
|
|
}
|
|
|
|
public static void createObjectSerialized(YamlConfiguration conf, String loc, Object obj, int recursiveness) {
|
|
|
|
Class<?> cls = obj.getClass();
|
|
|
|
if (!cached.containsKey(cls)) {
|
|
cached.put(cls, cls.getDeclaredFields());
|
|
}
|
|
|
|
for (Field fl : cached.get(cls)) {
|
|
fl.setAccessible(true);
|
|
|
|
Object newobj = getFieldValue(fl, obj);
|
|
|
|
if (newobj == null) {
|
|
continue;
|
|
}
|
|
|
|
String name = fl.getName();
|
|
String type = newobj.getClass().getSimpleName();
|
|
|
|
String newloc = loc + "." + type + "." + name;
|
|
|
|
if (isSimple(newobj) || recursiveness > 1) {
|
|
conf.set(newloc, convertToString(newobj));
|
|
continue;
|
|
}
|
|
|
|
createObjectSerialized(conf, newloc, newobj, recursiveness + 1);
|
|
|
|
}
|
|
}
|
|
|
|
// public static long getObjectSize(Object obj, int recursiveness) {
|
|
// if (obj == null) {
|
|
// return 0;
|
|
// }
|
|
//
|
|
//
|
|
// if (obj instanceof Serializable) {
|
|
// return getSerializedSize((Serializable) obj);
|
|
// }
|
|
//
|
|
// Class<?> cls = obj.getClass();
|
|
//
|
|
// long size = 0;
|
|
//
|
|
// if (!cached.containsKey(cls)) {
|
|
// cached.put(cls, cls.getDeclaredFields());
|
|
// }
|
|
//
|
|
// for (Field fl : cached.get(cls)) {
|
|
// fl.setAccessible(true);
|
|
// Object nobj = getFieldValue(fl, obj);
|
|
// size+=getObjectSize(nobj, recursiveness+1);
|
|
// }
|
|
//
|
|
// return size;
|
|
// }
|
|
//
|
|
// private static long getSerializedSize(Serializable obj) {
|
|
//
|
|
// try {
|
|
// ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
|
// ObjectOutputStream oos = new ObjectOutputStream(bos);
|
|
// oos.writeObject(obj);
|
|
// oos.flush();
|
|
// byte[] data = bos.toByteArray();
|
|
//
|
|
// return data.length;
|
|
// } catch (Exception e) {
|
|
// return 0;
|
|
// }
|
|
// }
|
|
|
|
public static Object getFieldValue(Object instance, String fieldName) throws Exception {
|
|
Field field = instance.getClass().getDeclaredField(fieldName);
|
|
field.setAccessible(true);
|
|
return field.get(instance);
|
|
}
|
|
|
|
@SuppressWarnings("unchecked")
|
|
public static <T> T getFieldValue(Field field, Object obj) {
|
|
try {
|
|
return (T) field.get(obj);
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public static Field getField(Class<?> clazz, String fieldName) throws Exception {
|
|
Field field = clazz.getDeclaredField(fieldName);
|
|
field.setAccessible(true);
|
|
return field;
|
|
}
|
|
|
|
public static Method getMethod(Class<?> clazz, String methodName, Class<?>... resl) {
|
|
Method method;
|
|
try {
|
|
method = clazz.getDeclaredMethod(methodName, resl);
|
|
method.setAccessible(true);
|
|
return method;
|
|
} catch (Exception e) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public static Object runMethod(Object obj, Method m, Object... resl) throws Exception {
|
|
return m.invoke(obj, resl);
|
|
}
|
|
|
|
public static Object runMethod(Object obj, String name, Object... resl) throws Exception {
|
|
Class<?>[] classes = new Class<?>[resl.length];
|
|
for (int i = 0; i < resl.length; i++) {
|
|
classes[i] = resl[i].getClass();
|
|
}
|
|
return getMethod(obj.getClass(), name, classes).invoke(obj, resl);
|
|
}
|
|
|
|
public static void setValue(Object instance, String field, Object value) {
|
|
try {
|
|
Field f = instance.getClass().getDeclaredField(field);
|
|
f.setAccessible(true);
|
|
f.set(instance, value);
|
|
} catch (Throwable t) {
|
|
t.printStackTrace();
|
|
}
|
|
}
|
|
|
|
public static void sendAllPacket(Object packet) throws Exception {
|
|
for (Player p : Bukkit.getOnlinePlayers()) {
|
|
Object nmsPlayer = getNmsPlayer(p);
|
|
Object connection = nmsPlayer.getClass().getField("playerConnection").get(nmsPlayer);
|
|
connection.getClass().getMethod("sendPacket", getClass("{nms}.Packet")).invoke(connection, packet);
|
|
}
|
|
}
|
|
|
|
public static int getPing(Player p) {
|
|
try {
|
|
Object entityPlayer = Methods.getPlayerHandle.getMethod().invoke(p);
|
|
return (int) getFieldValue(entityPlayer, "ping");
|
|
} catch (Exception e) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
public static void sendListPacket(List<String> players, Object packet) {
|
|
try {
|
|
for (String name : players) {
|
|
Object nmsPlayer = getNmsPlayer(Bukkit.getPlayer(name));
|
|
Object connection = nmsPlayer.getClass().getField("playerConnection").get(nmsPlayer);
|
|
connection.getClass().getMethod("sendPacket", getClass("{nms}.Packet")).invoke(connection, packet);
|
|
}
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
public static void sendPlayerPacket(Player p, Object packet) throws Exception {
|
|
Object nmsPlayer = getNmsPlayer(p);
|
|
Object connection = nmsPlayer.getClass().getField("playerConnection").get(nmsPlayer);
|
|
connection.getClass().getMethod("sendPacket", getClass("{nms}.Packet")).invoke(connection, packet);
|
|
}
|
|
|
|
public static PluginCommand getCommand(String name, Plugin plugin) {
|
|
PluginCommand command = null;
|
|
|
|
try {
|
|
Constructor<PluginCommand> c = PluginCommand.class.getDeclaredConstructor(String.class, Plugin.class);
|
|
c.setAccessible(true);
|
|
|
|
command = c.newInstance(name, plugin);
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
|
|
return command;
|
|
}
|
|
|
|
public static CommandMap getCommandMap() {
|
|
CommandMap commandMap = null;
|
|
|
|
try {
|
|
if (Bukkit.getPluginManager() instanceof SimplePluginManager) {
|
|
Field f = SimplePluginManager.class.getDeclaredField("commandMap");
|
|
f.setAccessible(true);
|
|
|
|
commandMap = (CommandMap) f.get(Bukkit.getPluginManager());
|
|
}
|
|
} catch (NoSuchFieldException e) {
|
|
e.printStackTrace();
|
|
} catch (SecurityException e) {
|
|
e.printStackTrace();
|
|
} catch (IllegalArgumentException e) {
|
|
e.printStackTrace();
|
|
} catch (IllegalAccessException e) {
|
|
e.printStackTrace();
|
|
}
|
|
|
|
return commandMap;
|
|
}
|
|
|
|
private static String convertToString(Object obj) {
|
|
Class<?> cls = obj.getClass();
|
|
|
|
if (cls.isArray()) {
|
|
String stg = "";
|
|
int length = Array.getLength(obj);
|
|
for (int i = 0; i < length; i++) {
|
|
stg += convertToString(Array.get(obj, i));
|
|
}
|
|
return stg;
|
|
|
|
}
|
|
|
|
return obj.toString();
|
|
}
|
|
|
|
private static boolean isSimple(Object obj) {
|
|
Class<?> cls = obj.getClass();
|
|
|
|
if (cls.isPrimitive()) {
|
|
return true;
|
|
}
|
|
|
|
if (cls.isEnum()) {
|
|
return true;
|
|
}
|
|
|
|
if (cls == Integer.class) {
|
|
return true;
|
|
}
|
|
|
|
if (cls == Boolean.class) {
|
|
return true;
|
|
}
|
|
|
|
if (cls == String.class) {
|
|
return true;
|
|
}
|
|
|
|
if (cls == Character.class) {
|
|
return true;
|
|
}
|
|
|
|
if (cls == Byte.class) {
|
|
return true;
|
|
}
|
|
|
|
if (cls == Short.class) {
|
|
return true;
|
|
}
|
|
|
|
if (cls == Float.class) {
|
|
return true;
|
|
}
|
|
|
|
if (cls == Double.class) {
|
|
return true;
|
|
}
|
|
|
|
if (cls == Long.class) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public static void setViewDistance(World w, int amount) {
|
|
try {
|
|
runMethod(w, Methods.setViewDistance.mthd, amount);
|
|
Main.sendDebug("Succesfully set view distance at " + amount + " in world " + w.getName(), 1);
|
|
} catch (Exception e) {
|
|
Main.sendDebug("Exception at setViewDistance (" + w.getName() + ", " + amount + ")", 1);
|
|
}
|
|
|
|
|
|
}
|
|
}
|