This commit is contained in:
MattBDev
2016-07-16 22:51:49 -04:00
parent 8b0e59209c
commit 8538170cba
17 changed files with 268 additions and 554 deletions

View File

@ -1,10 +1,25 @@
package com.plotsquared.bukkit.chat;
import static com.plotsquared.bukkit.chat.TextualComponent.rawText;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.stream.JsonWriter;
import org.bukkit.Achievement;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.Statistic;
import org.bukkit.Statistic.Type;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
import org.bukkit.configuration.serialization.ConfigurationSerialization;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.io.IOException;
import java.io.StringWriter;
import java.lang.reflect.Constructor;
@ -19,21 +34,6 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import org.bukkit.Achievement;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.Statistic;
import org.bukkit.Statistic.Type;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
import org.bukkit.configuration.serialization.ConfigurationSerialization;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import static com.plotsquared.bukkit.chat.TextualComponent.rawText;
/**
* 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>.
@ -60,7 +60,7 @@ public class FancyMessage implements JsonRepresentedObject, Cloneable, Iterable<
@Override
public FancyMessage clone() throws CloneNotSupportedException {
FancyMessage instance = (FancyMessage) super.clone();
instance.messageParts = new ArrayList<MessagePart>(messageParts.size());
instance.messageParts = new ArrayList<>(messageParts.size());
for (int i = 0; i < messageParts.size(); i++) {
instance.messageParts.add(i, messageParts.get(i).clone());
}
@ -78,15 +78,15 @@ public class FancyMessage implements JsonRepresentedObject, Cloneable, Iterable<
this(rawText(firstPartText));
}
public FancyMessage(final com.plotsquared.bukkit.chat.TextualComponent firstPartText) {
messageParts = new ArrayList<MessagePart>();
public FancyMessage(final TextualComponent firstPartText) {
messageParts = new ArrayList<>();
messageParts.add(new MessagePart(firstPartText));
jsonString = null;
dirty = false;
if (nmsPacketPlayOutChatConstructor == null) {
try {
nmsPacketPlayOutChatConstructor = com.plotsquared.bukkit.chat.Reflection.getNMSClass("PacketPlayOutChat").getDeclaredConstructor(com.plotsquared.bukkit.chat.Reflection.getNMSClass("IChatBaseComponent"));
nmsPacketPlayOutChatConstructor = Reflection.getNMSClass("PacketPlayOutChat").getDeclaredConstructor(Reflection.getNMSClass("IChatBaseComponent"));
nmsPacketPlayOutChatConstructor.setAccessible(true);
} catch (NoSuchMethodException e) {
Bukkit.getLogger().log(Level.SEVERE, "Could not find Minecraft method or constructor.", e);
@ -100,7 +100,7 @@ public class FancyMessage implements JsonRepresentedObject, Cloneable, Iterable<
* Creates a JSON message without text.
*/
public FancyMessage() {
this((com.plotsquared.bukkit.chat.TextualComponent) null);
this((TextualComponent) null);
}
/**
@ -122,7 +122,7 @@ public class FancyMessage implements JsonRepresentedObject, Cloneable, Iterable<
* @param text The new text of the current editing component.
* @return This builder instance.
*/
public FancyMessage text(com.plotsquared.bukkit.chat.TextualComponent text) {
public FancyMessage text(TextualComponent text) {
MessagePart latest = latest();
latest.text = text;
dirty = true;
@ -243,8 +243,8 @@ public class FancyMessage implements JsonRepresentedObject, Cloneable, Iterable<
*/
public FancyMessage achievementTooltip(final Achievement which) {
try {
Object achievement = com.plotsquared.bukkit.chat.Reflection.getMethod(com.plotsquared.bukkit.chat.Reflection.getOBCClass("CraftStatistic"), "getNMSAchievement", Achievement.class).invoke(null, which);
return achievementTooltip((String) com.plotsquared.bukkit.chat.Reflection.getField(com.plotsquared.bukkit.chat.Reflection.getNMSClass("Achievement"), "name").get(achievement));
Object achievement = Reflection.getMethod(Reflection.getOBCClass("CraftStatistic"), "getNMSAchievement", Achievement.class).invoke(null, which);
return achievementTooltip((String) Reflection.getField(Reflection.getNMSClass("Achievement"), "name").get(achievement));
} catch (IllegalAccessException e) {
Bukkit.getLogger().log(Level.WARNING, "Could not access method.", e);
return this;
@ -252,7 +252,7 @@ public class FancyMessage implements JsonRepresentedObject, Cloneable, Iterable<
Bukkit.getLogger().log(Level.WARNING, "Argument could not be passed.", e);
return this;
} catch (InvocationTargetException e) {
Bukkit.getLogger().log(Level.WARNING, "A error has occured durring invoking of method.", e);
Bukkit.getLogger().log(Level.WARNING, "A error has occurred during invoking of method.", e);
return this;
}
}
@ -271,8 +271,8 @@ public class FancyMessage implements JsonRepresentedObject, Cloneable, Iterable<
throw new IllegalArgumentException("That statistic requires an additional " + type + " parameter!");
}
try {
Object statistic = com.plotsquared.bukkit.chat.Reflection.getMethod(com.plotsquared.bukkit.chat.Reflection.getOBCClass("CraftStatistic"), "getNMSStatistic", Statistic.class).invoke(null, which);
return achievementTooltip((String) com.plotsquared.bukkit.chat.Reflection.getField(com.plotsquared.bukkit.chat.Reflection.getNMSClass("Statistic"), "name").get(statistic));
Object statistic = Reflection.getMethod(Reflection.getOBCClass("CraftStatistic"), "getNMSStatistic", Statistic.class).invoke(null, which);
return achievementTooltip((String) Reflection.getField(Reflection.getNMSClass("Statistic"), "name").get(statistic));
} catch (IllegalAccessException e) {
Bukkit.getLogger().log(Level.WARNING, "Could not access method.", e);
return this;
@ -280,7 +280,7 @@ public class FancyMessage implements JsonRepresentedObject, Cloneable, Iterable<
Bukkit.getLogger().log(Level.WARNING, "Argument could not be passed.", e);
return this;
} catch (InvocationTargetException e) {
Bukkit.getLogger().log(Level.WARNING, "A error has occured durring invoking of method.", e);
Bukkit.getLogger().log(Level.WARNING, "A error has occurred during invoking of method.", e);
return this;
}
}
@ -303,8 +303,8 @@ public class FancyMessage implements JsonRepresentedObject, Cloneable, Iterable<
throw new IllegalArgumentException("Wrong parameter type for that statistic - needs " + type + "!");
}
try {
Object statistic = com.plotsquared.bukkit.chat.Reflection.getMethod(com.plotsquared.bukkit.chat.Reflection.getOBCClass("CraftStatistic"), "getMaterialStatistic", Statistic.class, Material.class).invoke(null, which, item);
return achievementTooltip((String) com.plotsquared.bukkit.chat.Reflection.getField(com.plotsquared.bukkit.chat.Reflection.getNMSClass("Statistic"), "name").get(statistic));
Object statistic = Reflection.getMethod(Reflection.getOBCClass("CraftStatistic"), "getMaterialStatistic", Statistic.class, Material.class).invoke(null, which, item);
return achievementTooltip((String) Reflection.getField(Reflection.getNMSClass("Statistic"), "name").get(statistic));
} catch (IllegalAccessException e) {
Bukkit.getLogger().log(Level.WARNING, "Could not access method.", e);
return this;
@ -312,7 +312,7 @@ public class FancyMessage implements JsonRepresentedObject, Cloneable, Iterable<
Bukkit.getLogger().log(Level.WARNING, "Argument could not be passed.", e);
return this;
} catch (InvocationTargetException e) {
Bukkit.getLogger().log(Level.WARNING, "A error has occured durring invoking of method.", e);
Bukkit.getLogger().log(Level.WARNING, "A error has occurred during invoking of method.", e);
return this;
}
}
@ -335,8 +335,8 @@ public class FancyMessage implements JsonRepresentedObject, Cloneable, Iterable<
throw new IllegalArgumentException("Wrong parameter type for that statistic - needs " + type + "!");
}
try {
Object statistic = com.plotsquared.bukkit.chat.Reflection.getMethod(com.plotsquared.bukkit.chat.Reflection.getOBCClass("CraftStatistic"), "getEntityStatistic", Statistic.class, EntityType.class).invoke(null, which, entity);
return achievementTooltip((String) com.plotsquared.bukkit.chat.Reflection.getField(com.plotsquared.bukkit.chat.Reflection.getNMSClass("Statistic"), "name").get(statistic));
Object statistic = Reflection.getMethod(Reflection.getOBCClass("CraftStatistic"), "getEntityStatistic", Statistic.class, EntityType.class).invoke(null, which, entity);
return achievementTooltip((String) Reflection.getField(Reflection.getNMSClass("Statistic"), "name").get(statistic));
} catch (IllegalAccessException e) {
Bukkit.getLogger().log(Level.WARNING, "Could not access method.", e);
return this;
@ -344,7 +344,7 @@ public class FancyMessage implements JsonRepresentedObject, Cloneable, Iterable<
Bukkit.getLogger().log(Level.WARNING, "Argument could not be passed.", e);
return this;
} catch (InvocationTargetException e) {
Bukkit.getLogger().log(Level.WARNING, "A error has occured durring invoking of method.", e);
Bukkit.getLogger().log(Level.WARNING, "A error has occurred during invoking of method.", e);
return this;
}
}
@ -370,8 +370,8 @@ public class FancyMessage implements JsonRepresentedObject, Cloneable, Iterable<
*/
public FancyMessage itemTooltip(final ItemStack itemStack) {
try {
Object nmsItem = com.plotsquared.bukkit.chat.Reflection.getMethod(com.plotsquared.bukkit.chat.Reflection.getOBCClass("inventory.CraftItemStack"), "asNMSCopy", ItemStack.class).invoke(null, itemStack);
return itemTooltip(com.plotsquared.bukkit.chat.Reflection.getMethod(com.plotsquared.bukkit.chat.Reflection.getNMSClass("ItemStack"), "save", com.plotsquared.bukkit.chat.Reflection.getNMSClass("NBTTagCompound")).invoke(nmsItem, com.plotsquared.bukkit.chat.Reflection.getNMSClass("NBTTagCompound").newInstance()).toString());
Object nmsItem = Reflection.getMethod(Reflection.getOBCClass("inventory.CraftItemStack"), "asNMSCopy", ItemStack.class).invoke(null, itemStack);
return itemTooltip(Reflection.getMethod(Reflection.getNMSClass("ItemStack"), "save", Reflection.getNMSClass("NBTTagCompound")).invoke(nmsItem, Reflection.getNMSClass("NBTTagCompound").newInstance()).toString());
} catch (Exception e) {
e.printStackTrace();
return this;
@ -565,7 +565,7 @@ public class FancyMessage implements JsonRepresentedObject, Cloneable, Iterable<
* @param text The text which will populate the new message component.
* @return This builder instance.
*/
public FancyMessage then(final com.plotsquared.bukkit.chat.TextualComponent text) {
public FancyMessage then(final TextualComponent text) {
if (!latest().hasText()) {
throw new IllegalStateException("previous message part has no text");
}
@ -641,9 +641,9 @@ public class FancyMessage implements JsonRepresentedObject, Cloneable, Iterable<
}
Player player = (Player) sender;
try {
Object handle = com.plotsquared.bukkit.chat.Reflection.getHandle(player);
Object connection = com.plotsquared.bukkit.chat.Reflection.getField(handle.getClass(), "playerConnection").get(handle);
com.plotsquared.bukkit.chat.Reflection.getMethod(connection.getClass(), "sendPacket", com.plotsquared.bukkit.chat.Reflection.getNMSClass("Packet")).invoke(connection, createChatPacket(jsonString));
Object handle = Reflection.getHandle(player);
Object connection = Reflection.getField(handle.getClass(), "playerConnection").get(handle);
Reflection.getMethod(connection.getClass(), "sendPacket", Reflection.getNMSClass("Packet")).invoke(connection, createChatPacket(jsonString));
} catch (IllegalArgumentException e) {
Bukkit.getLogger().log(Level.WARNING, "Argument could not be passed.", e);
} catch (IllegalAccessException e) {
@ -651,7 +651,7 @@ public class FancyMessage implements JsonRepresentedObject, Cloneable, Iterable<
} catch (InstantiationException e) {
Bukkit.getLogger().log(Level.WARNING, "Underlying class is abstract.", e);
} catch (InvocationTargetException e) {
Bukkit.getLogger().log(Level.WARNING, "A error has occured durring invoking of method.", e);
Bukkit.getLogger().log(Level.WARNING, "A error has occurred during invoking of method.", e);
} catch (NoSuchMethodException e) {
Bukkit.getLogger().log(Level.WARNING, "Could not find method.", e);
} catch (ClassNotFoundException e) {
@ -673,16 +673,16 @@ public class FancyMessage implements JsonRepresentedObject, Cloneable, Iterable<
// X = major
// Y = minor
// Z = revision
final String version = com.plotsquared.bukkit.chat.Reflection.getVersion();
final String version = Reflection.getVersion();
String[] split = version.substring(1, version.length() - 1).split("_"); // Remove trailing dot
//int majorVersion = Integer.parseInt(split[0]);
int minorVersion = Integer.parseInt(split[1]);
int revisionVersion = Integer.parseInt(split[2].substring(1)); // Substring to ignore R
if (minorVersion < 8 || (minorVersion == 8 && revisionVersion == 1)) {
chatSerializerClazz = com.plotsquared.bukkit.chat.Reflection.getNMSClass("ChatSerializer");
chatSerializerClazz = Reflection.getNMSClass("ChatSerializer");
} else {
chatSerializerClazz = com.plotsquared.bukkit.chat.Reflection.getNMSClass("IChatBaseComponent$ChatSerializer");
chatSerializerClazz = Reflection.getNMSClass("IChatBaseComponent$ChatSerializer");
}
if (chatSerializerClazz == null) {
@ -702,7 +702,7 @@ public class FancyMessage implements JsonRepresentedObject, Cloneable, Iterable<
// Since the method is so simple, and all the obfuscated methods have the same name, it's easier to reimplement 'IChatBaseComponent a(String)' than to reflectively call it
// Of course, the implementation may change, but fuzzy matches might break with signature changes
Object serializedChatComponent = fromJsonMethod.invoke(nmsChatSerializerGsonInstance, json, com.plotsquared.bukkit.chat.Reflection.getNMSClass("IChatBaseComponent"));
Object serializedChatComponent = fromJsonMethod.invoke(nmsChatSerializerGsonInstance, json, Reflection.getNMSClass("IChatBaseComponent"));
return nmsPacketPlayOutChatConstructor.newInstance(serializedChatComponent);
}
@ -781,7 +781,7 @@ public class FancyMessage implements JsonRepresentedObject, Cloneable, Iterable<
// Doc copied from interface
public Map<String, Object> serialize() {
HashMap<String, Object> map = new HashMap<String, Object>();
HashMap<String, Object> map = new HashMap<>();
map.put("messageParts", messageParts);
// map.put("JSON", toJSONString());
return map;
@ -829,9 +829,9 @@ public class FancyMessage implements JsonRepresentedObject, Cloneable, Iterable<
JsonObject messagePart = mPrt.getAsJsonObject();
for (Map.Entry<String, JsonElement> entry : messagePart.entrySet()) {
// Deserialize text
if (com.plotsquared.bukkit.chat.TextualComponent.isTextKey(entry.getKey())) {
if (TextualComponent.isTextKey(entry.getKey())) {
// The map mimics the YAML serialization, which has a "key" field and one or more "value" fields
Map<String, Object> serializedMapForm = new HashMap<String, Object>(); // Must be object due to Bukkit serializer API compliance
Map<String, Object> serializedMapForm = new HashMap<>(); // Must be object due to Bukkit serializer API compliance
serializedMapForm.put("key", entry.getKey());
if (entry.getValue().isJsonPrimitive()) {
// Assume string
@ -842,7 +842,7 @@ public class FancyMessage implements JsonRepresentedObject, Cloneable, Iterable<
serializedMapForm.put("value." + compositeNestedElement.getKey(), compositeNestedElement.getValue().getAsString());
}
}
component.text = com.plotsquared.bukkit.chat.TextualComponent.deserialize(serializedMapForm);
component.text = TextualComponent.deserialize(serializedMapForm);
} else if (MessagePart.stylesToNames.inverse().containsKey(entry.getKey())) {
if (entry.getValue().getAsBoolean()) {
component.styles.add(MessagePart.stylesToNames.inverse().get(entry.getKey()));

View File

@ -19,137 +19,139 @@ import java.util.logging.Level;
*/
final class MessagePart implements JsonRepresentedObject, ConfigurationSerializable, Cloneable {
ChatColor color = ChatColor.WHITE;
ArrayList<ChatColor> styles = new ArrayList<ChatColor>();
String clickActionName = null, clickActionData = null, hoverActionName = null;
JsonRepresentedObject hoverActionData = null;
TextualComponent text = null;
String insertionData = null;
ArrayList<JsonRepresentedObject> translationReplacements = new ArrayList<JsonRepresentedObject>();
ChatColor color = ChatColor.WHITE;
ArrayList<ChatColor> styles = new ArrayList<>();
String clickActionName = null;
String clickActionData = null;
String hoverActionName = null;
JsonRepresentedObject hoverActionData = null;
TextualComponent text = null;
String insertionData = null;
ArrayList<JsonRepresentedObject> translationReplacements = new ArrayList<>();
MessagePart(final TextualComponent text) {
this.text = text;
}
MessagePart(final TextualComponent text) {
this.text = text;
}
MessagePart() {
this.text = null;
}
MessagePart() {
this.text = null;
}
boolean hasText() {
return text != null;
}
boolean hasText() {
return text != null;
}
@Override
@SuppressWarnings("unchecked")
public MessagePart clone() throws CloneNotSupportedException {
MessagePart obj = (MessagePart) super.clone();
obj.styles = (ArrayList<ChatColor>) styles.clone();
if (hoverActionData instanceof JsonString) {
obj.hoverActionData = new JsonString(((JsonString) hoverActionData).getValue());
} else if (hoverActionData instanceof FancyMessage) {
obj.hoverActionData = ((FancyMessage) hoverActionData).clone();
}
obj.translationReplacements = (ArrayList<JsonRepresentedObject>) translationReplacements.clone();
return obj;
@Override
@SuppressWarnings("unchecked")
public MessagePart clone() throws CloneNotSupportedException {
MessagePart obj = (MessagePart) super.clone();
obj.styles = (ArrayList<ChatColor>) styles.clone();
if (hoverActionData instanceof JsonString) {
obj.hoverActionData = new JsonString(((JsonString) hoverActionData).getValue());
} else if (hoverActionData instanceof FancyMessage) {
obj.hoverActionData = ((FancyMessage) hoverActionData).clone();
}
obj.translationReplacements = (ArrayList<JsonRepresentedObject>) translationReplacements.clone();
return obj;
}
}
static final BiMap<ChatColor, String> stylesToNames;
static final BiMap<ChatColor, String> stylesToNames;
static {
ImmutableBiMap.Builder<ChatColor, String> builder = ImmutableBiMap.builder();
for (final ChatColor style : ChatColor.values()) {
if (!style.isFormat()) {
continue;
}
static {
ImmutableBiMap.Builder<ChatColor, String> builder = ImmutableBiMap.builder();
for (final ChatColor style : ChatColor.values()) {
if (!style.isFormat()) {
continue;
}
String styleName;
switch (style) {
case MAGIC:
styleName = "obfuscated";
break;
case UNDERLINE:
styleName = "underlined";
break;
default:
styleName = style.name().toLowerCase();
break;
}
String styleName;
switch (style) {
case MAGIC:
styleName = "obfuscated";
break;
case UNDERLINE:
styleName = "underlined";
break;
default:
styleName = style.name().toLowerCase();
break;
}
builder.put(style, styleName);
}
stylesToNames = builder.build();
}
builder.put(style, styleName);
}
stylesToNames = builder.build();
}
public void writeJson(JsonWriter json) {
try {
json.beginObject();
text.writeJson(json);
json.name("color").value(color.name().toLowerCase());
for (final ChatColor style : styles) {
json.name(stylesToNames.get(style)).value(true);
}
if (clickActionName != null && clickActionData != null) {
json.name("clickEvent")
.beginObject()
.name("action").value(clickActionName)
.name("value").value(clickActionData)
.endObject();
}
if (hoverActionName != null && hoverActionData != null) {
json.name("hoverEvent")
.beginObject()
.name("action").value(hoverActionName)
.name("value");
hoverActionData.writeJson(json);
json.endObject();
}
if (insertionData != null) {
json.name("insertion").value(insertionData);
}
if (translationReplacements.size() > 0 && text != null && TextualComponent.isTranslatableText(text)) {
json.name("with").beginArray();
for (JsonRepresentedObject obj : translationReplacements) {
obj.writeJson(json);
}
json.endArray();
}
json.endObject();
} catch (IOException e) {
Bukkit.getLogger().log(Level.WARNING, "A problem occured during writing of JSON string", e);
}
}
public void writeJson(JsonWriter json) {
try {
json.beginObject();
text.writeJson(json);
json.name("color").value(color.name().toLowerCase());
for (final ChatColor style : styles) {
json.name(stylesToNames.get(style)).value(true);
}
if (clickActionName != null && clickActionData != null) {
json.name("clickEvent")
.beginObject()
.name("action").value(clickActionName)
.name("value").value(clickActionData)
.endObject();
}
if (hoverActionName != null && hoverActionData != null) {
json.name("hoverEvent")
.beginObject()
.name("action").value(hoverActionName)
.name("value");
hoverActionData.writeJson(json);
json.endObject();
}
if (insertionData != null) {
json.name("insertion").value(insertionData);
}
if (translationReplacements.size() > 0 && text != null && TextualComponent.isTranslatableText(text)) {
json.name("with").beginArray();
for (JsonRepresentedObject obj : translationReplacements) {
obj.writeJson(json);
}
json.endArray();
}
json.endObject();
} catch (IOException e) {
Bukkit.getLogger().log(Level.WARNING, "A problem occured during writing of JSON string", e);
}
}
public Map<String, Object> serialize() {
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("text", text);
map.put("styles", styles);
map.put("color", color.getChar());
map.put("hoverActionName", hoverActionName);
map.put("hoverActionData", hoverActionData);
map.put("clickActionName", clickActionName);
map.put("clickActionData", clickActionData);
map.put("insertion", insertionData);
map.put("translationReplacements", translationReplacements);
return map;
}
public Map<String, Object> serialize() {
HashMap<String, Object> map = new HashMap<>();
map.put("text", text);
map.put("styles", styles);
map.put("color", color.getChar());
map.put("hoverActionName", hoverActionName);
map.put("hoverActionData", hoverActionData);
map.put("clickActionName", clickActionName);
map.put("clickActionData", clickActionData);
map.put("insertion", insertionData);
map.put("translationReplacements", translationReplacements);
return map;
}
@SuppressWarnings("unchecked")
public static MessagePart deserialize(Map<String, Object> serialized) {
MessagePart part = new MessagePart((TextualComponent) serialized.get("text"));
part.styles = (ArrayList<ChatColor>) serialized.get("styles");
part.color = ChatColor.getByChar(serialized.get("color").toString());
part.hoverActionName = (String) serialized.get("hoverActionName");
part.hoverActionData = (JsonRepresentedObject) serialized.get("hoverActionData");
part.clickActionName = (String) serialized.get("clickActionName");
part.clickActionData = (String) serialized.get("clickActionData");
part.insertionData = (String) serialized.get("insertion");
part.translationReplacements = (ArrayList<JsonRepresentedObject>) serialized.get("translationReplacements");
return part;
}
@SuppressWarnings("unchecked")
public static MessagePart deserialize(Map<String, Object> serialized) {
MessagePart part = new MessagePart((TextualComponent) serialized.get("text"));
part.styles = (ArrayList<ChatColor>) serialized.get("styles");
part.color = ChatColor.getByChar(serialized.get("color").toString());
part.hoverActionName = (String) serialized.get("hoverActionName");
part.hoverActionData = (JsonRepresentedObject) serialized.get("hoverActionData");
part.clickActionName = (String) serialized.get("clickActionName");
part.clickActionData = (String) serialized.get("clickActionData");
part.insertionData = (String) serialized.get("insertion");
part.translationReplacements = (ArrayList<JsonRepresentedObject>) serialized.get("translationReplacements");
return part;
}
static {
ConfigurationSerialization.registerClass(MessagePart.class);
}
static {
ConfigurationSerialization.registerClass(MessagePart.class);
}
}

View File

@ -3,6 +3,7 @@ package com.plotsquared.bukkit.chat;
import org.bukkit.Bukkit;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
@ -17,17 +18,17 @@ public final class Reflection {
/**
* Stores loaded classes from the {@code net.minecraft.server} package.
*/
private static final Map<String, Class<?>> _loadedNMSClasses = new HashMap<String, Class<?>>();
private static final Map<String, Class<?>> _loadedNMSClasses = new HashMap<>();
/**
* Stores loaded classes from the {@code org.bukkit.craftbukkit} package (and subpackages).
*/
private static final Map<String, Class<?>> _loadedOBCClasses = new HashMap<String, Class<?>>();
private static final Map<Class<?>, Map<String, Field>> _loadedFields = new HashMap<Class<?>, Map<String, Field>>();
private static final Map<String, Class<?>> _loadedOBCClasses = new HashMap<>();
private static final Map<Class<?>, Map<String, Field>> _loadedFields = new HashMap<>();
/**
* Contains loaded methods in a cache.
* The map maps [types to maps of [method names to maps of [parameter types to method instances]]].
*/
private static final Map<Class<?>, Map<String, Map<ArrayWrapper<Class<?>>, Method>>> _loadedMethods = new HashMap<Class<?>, Map<String, Map<ArrayWrapper<Class<?>>, Method>>>();
private static final Map<Class<?>, Map<String, Map<ArrayWrapper<Class<?>>, Method>>> _loadedMethods = new HashMap<>();
private static String _versionString;
private Reflection() { }
@ -64,10 +65,10 @@ public final class Reflection {
}
String fullName = "net.minecraft.server." + getVersion() + className;
Class<?> clazz = null;
Class<?> clazz;
try {
clazz = Class.forName(fullName);
} catch (Exception e) {
} catch (ClassNotFoundException e) {
_loadedNMSClasses.put(className, null);
throw new RuntimeException(e);
}
@ -88,10 +89,10 @@ public final class Reflection {
}
String fullName = "org.bukkit.craftbukkit." + getVersion() + className;
Class<?> clazz = null;
Class<?> clazz;
try {
clazz = Class.forName(fullName);
} catch (Exception e) {
} catch (ClassNotFoundException e) {
_loadedOBCClasses.put(className, null);
throw new RuntimeException(e);
}
@ -108,12 +109,8 @@ public final class Reflection {
* @param obj The object for which to retrieve an NMS handle.
* @return The NMS handle of the specified object, or {@code null} if it could not be retrieved using {@code getHandle()}.
*/
public synchronized static Object getHandle(Object obj) {
try {
public synchronized static Object getHandle(Object obj) throws InvocationTargetException, IllegalAccessException, IllegalArgumentException {
return getMethod(obj.getClass(), "getHandle").invoke(obj);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
@ -137,7 +134,7 @@ public final class Reflection {
public synchronized static Field getField(Class<?> clazz, String name) {
Map<String, Field> loaded;
if (!_loadedFields.containsKey(clazz)) {
loaded = new HashMap<String, Field>();
loaded = new HashMap<>();
_loadedFields.put(clazz, loaded);
} else {
loaded = _loadedFields.get(clazz);
@ -146,19 +143,19 @@ public final class Reflection {
// If the field is loaded (or cached as not existing), return the relevant value, which might be null
return loaded.get(name);
}
try {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
loaded.put(name, field);
return field;
} catch (Exception e) {
// Error loading
e.printStackTrace();
// Cache field as not existing
loaded.put(name, null);
return null;
}
}
try {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
loaded.put(name, field);
return field;
} catch (NoSuchFieldException | SecurityException e) {
// Error loading
e.printStackTrace();
// Cache field as not existing
loaded.put(name, null);
return null;
}
}
/**
* Retrieves a {@link Method} instance declared by the specified class with the specified name and argument types.
@ -167,11 +164,9 @@ public final class Reflection {
* <p>
* A global caching mechanism within this class is used to store method. Combined with synchronization, this guarantees that
* no method will be reflectively looked up twice.
* </p>
* <p>
* If a method is deemed suitable for return, {@link Method#setAccessible(boolean) setAccessible} will be invoked with an argument of {@code true} before it is returned.
* This ensures that callers do not have to check or worry about Java access modifiers when dealing with the returned instance.
* </p>
* <p>
* This method does <em>not</em> search superclasses of the specified type for methods with the specified signature.
* Callers wishing this behavior should use {@link Class#getDeclaredMethod(String, Class...)}.
@ -192,7 +187,7 @@ public final class Reflection {
}
Map<ArrayWrapper<Class<?>>, Method> loadedSignatures = loadedMethodNames.get(name);
ArrayWrapper<Class<?>> wrappedArg = new ArrayWrapper<Class<?>>(args);
ArrayWrapper<Class<?>> wrappedArg = new ArrayWrapper<>(args);
if (loadedSignatures.containsKey(wrappedArg)) {
return loadedSignatures.get(wrappedArg);
}