Core/src/de/joethei/core/api/SignInput.java

145 lines
5.1 KiB
Java

package de.joethei.core.api;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.codec.MessageToMessageDecoder;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.function.Consumer;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitScheduler;
public final class SignInput
implements Listener, Runnable
{
private static final String VERSION;
private final Plugin plugin;
private final Map<UUID, Consumer<String[]>> inputResults;
static
{
String path = Bukkit.getServer().getClass().getPackage().getName();
VERSION = path.substring(path.lastIndexOf(".") + 1, path.length());
}
public SignInput(Plugin plugin)
{
this.plugin = plugin;
this.inputResults = new HashMap();
Bukkit.getScheduler().runTaskTimer(this.plugin, this, 0L, 60L);
}
public boolean readInput(Player p, Consumer<String[]> result)
{
this.inputResults.put(p.getUniqueId(), result);
try {
Class packetClass =
Class.forName(getNMSClass("PacketPlayOutOpenSignEditor"));
Class blockPositionClass =
Class.forName(getNMSClass("BlockPosition"));
Constructor blockPosCon = blockPositionClass
.getConstructor(new Class[] { Integer.TYPE, Integer.TYPE,
Integer.TYPE });
Object blockPosition = blockPosCon.newInstance(new Object[] { Integer.valueOf(0), Integer.valueOf(0),
Integer.valueOf(0) });
Constructor packetCon = packetClass
.getConstructor(new Class[] { blockPositionClass });
Object packet = packetCon
.newInstance(new Object[] { blockPosition });
Method getHandle = p.getClass().getMethod("getHandle", new Class[0]);
Object nmsPlayer = getHandle.invoke(p, new Object[0]);
Field pConnectionField = nmsPlayer.getClass().getField(
"playerConnection");
Object pConnection = pConnectionField.get(nmsPlayer);
Method sendMethod = pConnection.getClass().getMethod("sendPacket",
new Class[] { Class.forName(getNMSClass("Packet")) });
sendMethod.invoke(pConnection, new Object[] { packet });
return true;
} catch (Exception ex) {
ex.printStackTrace();
}return false;
}
public void run()
{
for (UUID uuid : this.inputResults.keySet())
if (Bukkit.getPlayer(uuid) == null)
this.inputResults.remove(uuid);
}
@EventHandler
public void onJoin(PlayerJoinEvent e)
{
Player p = e.getPlayer();
getNettyChannel(p).pipeline().addAfter("decoder", "signListener",
new MessageToMessageDecoder() {
protected void decode(ChannelHandlerContext chc, Object packet, List<Object> packetList) throws Exception {
if (SignInput.this.instanceOf(packet,
SignInput.access(SignInput.this, "PacketPlayInUpdateSign"))) {
Method bMethod = packet.getClass().getMethod("b", new Class[0]);
Object chatBaseComponents = bMethod.invoke(packet, new Object[0]);
String[] lines = new String[4];
for (int i = 0; i < 4; i++) {
Object chatComponent = Array.get(
chatBaseComponents, i);
Method getText = chatComponent.getClass()
.getMethod("getText", new Class[0]);
lines[i] =
((String)getText
.invoke(chatComponent, new Object[0]));
}
if (SignInput.this.inputResults.containsKey(p.getUniqueId())) {
((Consumer)SignInput.this.inputResults.get(p.getUniqueId())).accept(lines);
SignInput.this.inputResults.remove(p.getUniqueId());
}
}
packetList.add(packet);
}
});
}
private Channel getNettyChannel(Player p) {
Channel ch = null;
try {
Method getHandle = p.getClass().getMethod("getHandle", new Class[0]);
Object nmsPlayer = getHandle.invoke(p, new Object[0]);
Field pConnectionField = nmsPlayer.getClass().getField(
"playerConnection");
Object pConnection = pConnectionField.get(nmsPlayer);
Field networkManagerField = pConnection.getClass().getField(
"networkManager");
Object networkManager = networkManagerField.get(pConnection);
ch = (Channel)networkManager.getClass().getField("k")
.get(networkManager);
} catch (Exception ex) {
ex.printStackTrace();
}
return ch;
}
private boolean instanceOf(Object o, String className) {
try {
return Class.forName(className).isInstance(o);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return false;
}
private String getNMSClass(String className) {
return "net.minecraft.server." + VERSION + "." + className;
}
}