145 lines
5.1 KiB
Java
145 lines
5.1 KiB
Java
package eu.univento.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;
|
|
}
|
|
} |