Core/src/eu/univento/core/api/SignInput.java

148 lines
5.0 KiB
Java
Raw Normal View History

2015-12-06 11:04:47 +01:00
package eu.univento.core.api;
2015-12-05 12:26:39 +01:00
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageDecoder;
2016-02-27 09:08:17 +01:00
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;
2015-12-05 12:26:39 +01:00
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;
/**
* @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 {
2015-12-05 12:26:39 +01:00
private final static String VERSION;
2015-12-05 12:26:39 +01:00
static {
String path = Bukkit.getServer().getClass().getPackage().getName();
VERSION = path.substring(path.lastIndexOf(".") + 1, path.length());
}
2015-12-05 12:26:39 +01:00
private final Plugin plugin;
private final Map<UUID, Consumer<String[]>> inputResults;
2015-12-05 12:26:39 +01:00
public SignInput(Plugin plugin) {
this.plugin = plugin;
this.inputResults = new HashMap<UUID, Consumer<String[]>>();
Bukkit.getScheduler().runTaskTimer(this.plugin, this, 0L, 20 * 3L);
2015-12-05 12:26:39 +01:00
}
2015-12-05 12:26:39 +01:00
/**
* 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 });
2015-12-05 12:26:39 +01:00
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;
}
}
2015-12-05 12:26:39 +01:00
/* 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;
}
}