147 lines
5.0 KiB
Java
147 lines
5.0 KiB
Java
package eu.univento.core.api;
|
|
|
|
import io.netty.channel.Channel;
|
|
import io.netty.channel.ChannelHandlerContext;
|
|
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;
|
|
|
|
|
|
/**
|
|
* @author Janhektor This class in licensed under GPLv3 For more information
|
|
* look at http://www.gnu.org/licenses/gpl-3.0
|
|
*/
|
|
public final class SignInput implements Listener, Runnable {
|
|
|
|
private final static String VERSION;
|
|
|
|
static {
|
|
String path = Bukkit.getServer().getClass().getPackage().getName();
|
|
VERSION = path.substring(path.lastIndexOf(".") + 1, path.length());
|
|
}
|
|
|
|
private final Plugin plugin;
|
|
private final Map<UUID, Consumer<String[]>> inputResults;
|
|
|
|
public SignInput(Plugin plugin) {
|
|
this.plugin = plugin;
|
|
this.inputResults = new HashMap<UUID, Consumer<String[]>>();
|
|
Bukkit.getScheduler().runTaskTimer(this.plugin, this, 0L, 20 * 3L);
|
|
|
|
}
|
|
|
|
/**
|
|
* Use this method to read the SignInput from a player The accept()-method
|
|
* of your consumer will be called, when the player close the sign
|
|
*
|
|
* @return boolean successful
|
|
* @param p
|
|
* - The Player, who have to type an input
|
|
* @param result
|
|
* - The consumer (String[]) for the result; String[] contains
|
|
* strings for 4 lines
|
|
*/
|
|
public boolean readInput(Player p, Consumer<String[]> result) {
|
|
inputResults.put(p.getUniqueId(), result);
|
|
try {
|
|
Class<?> packetClass = Class.forName(getNMSClass("PacketPlayOutOpenSignEditor"));
|
|
Class<?> blockPositionClass = Class.forName(getNMSClass("BlockPosition"));
|
|
Constructor<?> blockPosCon = blockPositionClass
|
|
.getConstructor(new Class[] { int.class, int.class, int.class });
|
|
Object blockPosition = blockPosCon.newInstance(new Object[] { 0, 0, 0 });
|
|
Constructor<?> packetCon = packetClass.getConstructor(new Class[] { blockPositionClass });
|
|
Object packet = packetCon.newInstance(new Object[] { blockPosition });
|
|
|
|
Method getHandle = p.getClass().getMethod("getHandle");
|
|
Object nmsPlayer = getHandle.invoke(p);
|
|
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;
|
|
}
|
|
}
|
|
|
|
/* Garbage Collection */
|
|
@Override
|
|
public void run() {
|
|
for (UUID uuid : inputResults.keySet()) {
|
|
if (Bukkit.getPlayer(uuid) == null)
|
|
inputResults.remove(uuid);
|
|
}
|
|
}
|
|
|
|
/* Events */
|
|
@EventHandler
|
|
public void onJoin(PlayerJoinEvent e) {
|
|
Player p = e.getPlayer();
|
|
getNettyChannel(p).pipeline().addAfter("decoder", "signListener", new MessageToMessageDecoder<Object>() {
|
|
@Override
|
|
protected void decode(ChannelHandlerContext chc, Object packet, List<Object> packetList) throws Exception {
|
|
if (instanceOf(packet, getNMSClass("PacketPlayInUpdateSign"))) {
|
|
Method bMethod = packet.getClass().getMethod("b");
|
|
Object chatBaseComponents = bMethod.invoke(packet);
|
|
String[] lines = new String[4];
|
|
for (int i = 0; i < 4; i++) {
|
|
Object chatComponent = Array.get(chatBaseComponents, i);
|
|
Method getText = chatComponent.getClass().getMethod("getText");
|
|
lines[i] = (String) getText.invoke(chatComponent);
|
|
}
|
|
if (inputResults.containsKey(p.getUniqueId())) {
|
|
inputResults.get(p.getUniqueId()).accept(lines);
|
|
inputResults.remove(p.getUniqueId());
|
|
}
|
|
}
|
|
packetList.add(packet);
|
|
}
|
|
});
|
|
}
|
|
|
|
/* Util Methods */
|
|
private Channel getNettyChannel(Player p) {
|
|
Channel ch = null;
|
|
try {
|
|
Method getHandle = p.getClass().getMethod("getHandle");
|
|
Object nmsPlayer = getHandle.invoke(p);
|
|
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;
|
|
}
|
|
}
|