TellRaw/src/main/java/cn/citycraft/TellRaw/internal/FancyMessageInternal.java

224 lines
9.7 KiB
Java

package cn.citycraft.TellRaw.internal;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.bukkit.Achievement;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.Statistic;
import org.bukkit.Statistic.Type;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import cn.citycraft.TellRaw.FancyMessage;
import cn.citycraft.TellRaw.common.Reflection;
import cn.citycraft.TellRaw.common.TextualComponent;
/**
* Represents a formattable message. Such messages can use elements such as
* colors, formatting codes, hover and click data, and other features provided
* by the vanilla Minecraft <a
* href="http://minecraft.gamepedia.com/Tellraw#Raw_JSON_Text">JSON message
* formatter</a>.
* This class allows plugins to emulate the functionality of the vanilla
* Minecraft <a href="http://minecraft.gamepedia.com/Commands#tellraw">tellraw
* command</a>.
* <p>
* This class follows the builder pattern, allowing for method chaining. It is
* set up such that invocations of property-setting methods will affect the
* current editing component, and a call to {@link #then()} or
* {@link #then(Object)} will append a new editing component to the end of the
* message, optionally initializing it with text. Further property-setting
* method calls will affect that editing component.
* </p>
*/
public class FancyMessageInternal extends FancyMessage {
/**
* 新建自动序列化类
*/
public FancyMessageInternal() {
this("");
}
/**
* 新建自动序列化类
*
* @param firstPartText
* 第一个文本串
*/
public FancyMessageInternal(final String firstPartText) {
super(TextualComponent.rawText(firstPartText));
}
@Override
public FancyMessage achievementTooltip(final Achievement which) {
try {
final Object achievement = getNMSAchievementMethod.invoke(null, which);
return achievementTooltip((String) nmsAchievement_NameField.get(achievement));
} catch (final IllegalAccessException e) {
Bukkit.getLogger().log(Level.WARNING, "Could not access method.", e);
return this;
} catch (final IllegalArgumentException e) {
Bukkit.getLogger().log(Level.WARNING, "Argument could not be passed.", e);
return this;
} catch (final InvocationTargetException e) {
Bukkit.getLogger().log(Level.WARNING, "A error has occured durring invoking of method.", e);
return this;
}
}
@Override
public FancyMessage itemTooltip(final ItemStack itemStack) {
try {
final Object nmsItem = getOBCasNMSCopyMethod.invoke(null, itemStack);
return itemTooltip(getNMSSaveNBTMethod.invoke(nmsItem, nmsNBTTagCompound.newInstance()).toString());
} catch (final Exception e) {
e.printStackTrace();
return this;
}
}
@Override
public void send(final CommandSender sender, final String jsonString) {
if (!(sender instanceof Player)) {
sender.sendMessage(toOldMessageFormat());
return;
}
final Player player = (Player) sender;
try {
final Object handle = Reflection.getHandle(player);
if (nmsPlayerConnectionField == null) {
try {
nmsPlayerConnectionField = Reflection.getField(handle.getClass(), "playerConnection");
} catch (final Exception e) {
for (final Field field : handle.getClass().getDeclaredFields()) {
if (field.getType().getSimpleName().contains("NetHandlerPlayServer")) {
nmsPlayerConnectionField = field;
break;
}
}
}
}
final Object connection = nmsPlayerConnectionField.get(handle);
if (nmsSendPacketMethod == null) {
try {
nmsSendPacketMethod = Reflection.getMethod(connection.getClass(), "sendPacket", nmsPacketClass);
} catch (final Exception e) {
nmsSendPacketMethod = Reflection.getMethodByParamsAndType(connection.getClass(), Void.TYPE, nmsPacketClass).get(0);
}
}
if (nmsSendPacketMethod == null) {
throw new RuntimeException("could find field: sendPacket in EntityPlayer class");
}
nmsSendPacketMethod.invoke(connection, createChatPacket(jsonString));
} catch (final IllegalArgumentException e) {
Bukkit.getLogger().log(Level.WARNING, "Argument could not be passed.", e);
} catch (final IllegalAccessException e) {
Bukkit.getLogger().log(Level.WARNING, "Could not access method.", e);
} catch (final InstantiationException e) {
Bukkit.getLogger().log(Level.WARNING, "Underlying class is abstract.", e);
} catch (final InvocationTargetException e) {
Bukkit.getLogger().log(Level.WARNING, "A error has occured durring invoking of method.", e);
} catch (final NoSuchMethodException e) {
Bukkit.getLogger().log(Level.WARNING, "Could not find method.", e);
} catch (final ClassNotFoundException e) {
Bukkit.getLogger().log(Level.WARNING, "Could not find class.", e);
} catch (final SecurityException ex) {
Logger.getLogger(FancyMessageInternal.class.getName()).log(Level.SEVERE, null, ex);
}
}
@Override
public FancyMessage statisticTooltip(final Statistic which) {
final Type type = which.getType();
if (type != Type.UNTYPED) {
throw new IllegalArgumentException("That statistic requires an additional " + type + " parameter!");
}
try {
final Object statistic = getNMSStatisticMethod.invoke(null, which);
return achievementTooltip((String) nmsStatistic_NameField.get(statistic));
} catch (final IllegalAccessException e) {
Bukkit.getLogger().log(Level.WARNING, "Could not access method.", e);
return this;
} catch (final IllegalArgumentException e) {
Bukkit.getLogger().log(Level.WARNING, "Argument could not be passed.", e);
return this;
} catch (final InvocationTargetException e) {
Bukkit.getLogger().log(Level.WARNING, "A error has occured durring invoking of method.", e);
return this;
}
}
@Override
public FancyMessage statisticTooltip(final Statistic which, final EntityType entity) {
final Type type = which.getType();
if (type == Type.UNTYPED) {
throw new IllegalArgumentException("That statistic needs no additional parameter!");
}
if (type != Type.ENTITY) {
throw new IllegalArgumentException("Wrong parameter type for that statistic - needs " + type + "!");
}
try {
final Object statistic = getNMSEntityStatisticMethod.invoke(null, which, entity);
return achievementTooltip((String) nmsStatistic_NameField.get(statistic));
} catch (final IllegalAccessException e) {
Bukkit.getLogger().log(Level.WARNING, "Could not access method.", e);
return this;
} catch (final IllegalArgumentException e) {
Bukkit.getLogger().log(Level.WARNING, "Argument could not be passed.", e);
return this;
} catch (final InvocationTargetException e) {
Bukkit.getLogger().log(Level.WARNING, "A error has occured durring invoking of method.", e);
return this;
}
}
@Override
public FancyMessage statisticTooltip(final Statistic which, final Material item) {
final Type type = which.getType();
if (type == Type.UNTYPED) {
throw new IllegalArgumentException("That statistic needs no additional parameter!");
}
if ((type == Type.BLOCK && item.isBlock()) || type == Type.ENTITY) {
throw new IllegalArgumentException("Wrong parameter type for that statistic - needs " + type + "!");
}
try {
final Object statistic = getNMSMaterialStatisticMethod.invoke(null, which, item);
return achievementTooltip((String) nmsStatistic_NameField.get(statistic));
} catch (final IllegalAccessException e) {
Bukkit.getLogger().log(Level.WARNING, "Could not access method.", e);
return this;
} catch (final IllegalArgumentException e) {
Bukkit.getLogger().log(Level.WARNING, "Argument could not be passed.", e);
return this;
} catch (final InvocationTargetException e) {
Bukkit.getLogger().log(Level.WARNING, "A error has occured durring invoking of method.", e);
return this;
}
}
/**
* 创建Chat数据包
*
* @param json
* 需要创建的数据包
* @return 创建发包对象
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws InstantiationException
* @throws InvocationTargetException
* @throws NoSuchMethodException
* @throws ClassNotFoundException
*/
private Object createChatPacket(final String json) throws IllegalArgumentException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException, ClassNotFoundException {
final Object serializedChatComponent = fromJsonMethod.invoke(nmsChatSerializerGsonInstance, json, nmsIChatBaseComponentClass);
return nmsPacketPlayOutChatConstructor.newInstance(serializedChatComponent);
}
}