【Minecraft Spigot】パケットの送受信処理に介入する

0pt   2018-08-10 18:00
IT技術情報局

環境:Spigot 1.12.2
PacketHandler.classのwriteで送信処理に、channelReadで受信処理に介入します。
パケット名はnet.minecraft.server.1_12_R1.PacketPlay…より。
自由にご活用下さい(:3 ∠ )_。

Main.class import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.plugin.java.JavaPlugin; public class Main extends JavaPlugin implements Listener{ private static PacketInjector injector; @Override public void onEnable(){ injector = new PacketInjector(); getServer().getPluginManager().registerEvents(this, this); } @Override public void onDisable(){ } @EventHandler public void onPlayerJoinEvent(PlayerJoinEvent e){ injector.addPlayer(e.getPlayer()); } } PacketHandler.class import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; public class PacketHandler extends ChannelDuplexHandler{ private Player p; public PacketHandler(final Player p) { this.p = p; } @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { System.out.println(msg.getClass().getPackage().getName() + "." + msg.getClass().getSimpleName()); super.write(ctx, msg, promise); } @Override public void channelRead(ChannelHandlerContext c, Object m) throws Exception { if(m.getClass().getSimpleName().equalsIgnoreCase("PacketPlayInChat")){ String text = Reflection.getFieldValue(m, "a").toString(); } super.channelRead(c, m); } } PacketInjector.class private Field EntityPlayer_playerConnection; private Class<?> PlayerConnection; private Field PlayerConnection_networkManager; private Class<?> NetworkManager; private Field k; private Field m; public PacketInjector() { try{ EntityPlayer_playerConnection = Reflection.getField(Reflection.getClass("{nms}.EntityPlayer"), "playerConnection"); PlayerConnection = Reflection.getClass("{nms}.PlayerConnection"); PlayerConnection_networkManager = Reflection.getField(PlayerConnection, "networkManager"); NetworkManager = Reflection.getClass("{nms}.NetworkManager"); k = Reflection.getField(NetworkManager, "channel"); m = Reflection.getField(NetworkManager, "m"); }catch(Throwable t) { t.printStackTrace(); } } public void addPlayer(Player p) { try{ Channel ch = getChannel(getNetworkManager(Reflection.getNmsPlayer(p))); if(ch.pipeline().get("PacketInjector") == null) { PacketHandler h = new PacketHandler(p); ch.pipeline().addBefore("packet_handler", "PacketInjector", h); } }catch(Throwable t) { t.printStackTrace(); } } public void removePlayer(Player p) { try{ Channel ch = getChannel(getNetworkManager(Reflection.getNmsPlayer(p))); if(ch.pipeline().get("PacketInjector") != null) { ch.pipeline().remove("PacketInjector"); } }catch(Throwable t) { t.printStackTrace(); } } private Object getNetworkManager(Object ep) throws Exception { return Reflection.getFieldValueT(PlayerConnection_networkManager, Reflection.getFieldValueT(EntityPlayer_playerConnection, ep)); } private Channel getChannel(Object networkManager) { Channel ch = null; try{ ch = Reflection.getFieldValueT(k, networkManager); }catch(Exception e) { ch = Reflection.getFieldValueT(m, networkManager); } return ch; } } Reflection.class import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.List; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.scoreboard.Scoreboard; public class Reflection { public static Class<?> getClass(String classname) { try{ String version = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3]; String path = classname.replace("{nms}", "net.minecraft.server."+version).replace("{nm}", "net.minecraft."+version).replace("{cb}", "org.bukkit.craftbukkit.."+version); return Class.forName(path); }catch(Throwable t){ t.printStackTrace(); return null; } } public static Object getNmsPlayer(Player p) throws Exception { Method getHandle = p.getClass().getMethod("getHandle"); return getHandle.invoke(p); } public static Object getNmsScoreboard(Scoreboard s) throws Exception { Method getHandle = s.getClass().getMethod("getHandle"); return getHandle.invoke(s); } 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 getFieldValueT(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 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", Reflection.getClass("{nms}.Packet")).invoke(connection, packet); } } 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", Reflection.getClass("{nms}.Packet")).invoke(connection, packet); } }catch(Throwable t) { t.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", Reflection.getClass("{nms}.Packet")).invoke(connection, packet); } }

Source: java tag

   ITアンテナトップページへ
情報処理/ITの話題が沢山。