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

@ -123,7 +123,14 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain
@Override @Override
public void onEnable() { public void onEnable() {
getServer().getName();
new PS(this, "Bukkit"); new PS(this, "Bukkit");
if (Settings.Enabled_Components.METRICS) {
new Metrics(this).start();
PS.log(C.PREFIX + "&6Metrics enabled.");
} else {
PS.log(C.CONSOLE_PLEASE_ENABLE_METRICS);
}
} }
@Override @Override
@ -572,8 +579,7 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain
@Override @Override
public void startMetrics() { public void startMetrics() {
Metrics metrics = new Metrics(this); new Metrics(this).start();
metrics.start();
PS.log(C.PREFIX + "&6Metrics enabled."); PS.log(C.PREFIX + "&6Metrics enabled.");
} }

View File

@ -1,10 +1,25 @@
package com.plotsquared.bukkit.chat; package com.plotsquared.bukkit.chat;
import static com.plotsquared.bukkit.chat.TextualComponent.rawText;
import com.google.gson.JsonArray; import com.google.gson.JsonArray;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.JsonParser; import com.google.gson.JsonParser;
import com.google.gson.stream.JsonWriter; 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.IOException;
import java.io.StringWriter; import java.io.StringWriter;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
@ -19,21 +34,6 @@ import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.logging.Level; 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>. * 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 @Override
public FancyMessage clone() throws CloneNotSupportedException { public FancyMessage clone() throws CloneNotSupportedException {
FancyMessage instance = (FancyMessage) super.clone(); 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++) { for (int i = 0; i < messageParts.size(); i++) {
instance.messageParts.add(i, messageParts.get(i).clone()); instance.messageParts.add(i, messageParts.get(i).clone());
} }
@ -78,15 +78,15 @@ public class FancyMessage implements JsonRepresentedObject, Cloneable, Iterable<
this(rawText(firstPartText)); this(rawText(firstPartText));
} }
public FancyMessage(final com.plotsquared.bukkit.chat.TextualComponent firstPartText) { public FancyMessage(final TextualComponent firstPartText) {
messageParts = new ArrayList<MessagePart>(); messageParts = new ArrayList<>();
messageParts.add(new MessagePart(firstPartText)); messageParts.add(new MessagePart(firstPartText));
jsonString = null; jsonString = null;
dirty = false; dirty = false;
if (nmsPacketPlayOutChatConstructor == null) { if (nmsPacketPlayOutChatConstructor == null) {
try { 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); nmsPacketPlayOutChatConstructor.setAccessible(true);
} catch (NoSuchMethodException e) { } catch (NoSuchMethodException e) {
Bukkit.getLogger().log(Level.SEVERE, "Could not find Minecraft method or constructor.", 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. * Creates a JSON message without text.
*/ */
public FancyMessage() { 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. * @param text The new text of the current editing component.
* @return This builder instance. * @return This builder instance.
*/ */
public FancyMessage text(com.plotsquared.bukkit.chat.TextualComponent text) { public FancyMessage text(TextualComponent text) {
MessagePart latest = latest(); MessagePart latest = latest();
latest.text = text; latest.text = text;
dirty = true; dirty = true;
@ -243,8 +243,8 @@ public class FancyMessage implements JsonRepresentedObject, Cloneable, Iterable<
*/ */
public FancyMessage achievementTooltip(final Achievement which) { public FancyMessage achievementTooltip(final Achievement which) {
try { try {
Object achievement = com.plotsquared.bukkit.chat.Reflection.getMethod(com.plotsquared.bukkit.chat.Reflection.getOBCClass("CraftStatistic"), "getNMSAchievement", Achievement.class).invoke(null, which); Object achievement = Reflection.getMethod(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)); return achievementTooltip((String) Reflection.getField(Reflection.getNMSClass("Achievement"), "name").get(achievement));
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
Bukkit.getLogger().log(Level.WARNING, "Could not access method.", e); Bukkit.getLogger().log(Level.WARNING, "Could not access method.", e);
return this; return this;
@ -252,7 +252,7 @@ public class FancyMessage implements JsonRepresentedObject, Cloneable, Iterable<
Bukkit.getLogger().log(Level.WARNING, "Argument could not be passed.", e); Bukkit.getLogger().log(Level.WARNING, "Argument could not be passed.", e);
return this; return this;
} catch (InvocationTargetException 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);
return this; return this;
} }
} }
@ -271,8 +271,8 @@ public class FancyMessage implements JsonRepresentedObject, Cloneable, Iterable<
throw new IllegalArgumentException("That statistic requires an additional " + type + " parameter!"); throw new IllegalArgumentException("That statistic requires an additional " + type + " parameter!");
} }
try { try {
Object statistic = com.plotsquared.bukkit.chat.Reflection.getMethod(com.plotsquared.bukkit.chat.Reflection.getOBCClass("CraftStatistic"), "getNMSStatistic", Statistic.class).invoke(null, which); Object statistic = Reflection.getMethod(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)); return achievementTooltip((String) Reflection.getField(Reflection.getNMSClass("Statistic"), "name").get(statistic));
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
Bukkit.getLogger().log(Level.WARNING, "Could not access method.", e); Bukkit.getLogger().log(Level.WARNING, "Could not access method.", e);
return this; return this;
@ -280,7 +280,7 @@ public class FancyMessage implements JsonRepresentedObject, Cloneable, Iterable<
Bukkit.getLogger().log(Level.WARNING, "Argument could not be passed.", e); Bukkit.getLogger().log(Level.WARNING, "Argument could not be passed.", e);
return this; return this;
} catch (InvocationTargetException 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);
return this; return this;
} }
} }
@ -303,8 +303,8 @@ public class FancyMessage implements JsonRepresentedObject, Cloneable, Iterable<
throw new IllegalArgumentException("Wrong parameter type for that statistic - needs " + type + "!"); throw new IllegalArgumentException("Wrong parameter type for that statistic - needs " + type + "!");
} }
try { 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); Object statistic = Reflection.getMethod(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)); return achievementTooltip((String) Reflection.getField(Reflection.getNMSClass("Statistic"), "name").get(statistic));
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
Bukkit.getLogger().log(Level.WARNING, "Could not access method.", e); Bukkit.getLogger().log(Level.WARNING, "Could not access method.", e);
return this; return this;
@ -312,7 +312,7 @@ public class FancyMessage implements JsonRepresentedObject, Cloneable, Iterable<
Bukkit.getLogger().log(Level.WARNING, "Argument could not be passed.", e); Bukkit.getLogger().log(Level.WARNING, "Argument could not be passed.", e);
return this; return this;
} catch (InvocationTargetException 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);
return this; return this;
} }
} }
@ -335,8 +335,8 @@ public class FancyMessage implements JsonRepresentedObject, Cloneable, Iterable<
throw new IllegalArgumentException("Wrong parameter type for that statistic - needs " + type + "!"); throw new IllegalArgumentException("Wrong parameter type for that statistic - needs " + type + "!");
} }
try { 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); Object statistic = Reflection.getMethod(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)); return achievementTooltip((String) Reflection.getField(Reflection.getNMSClass("Statistic"), "name").get(statistic));
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
Bukkit.getLogger().log(Level.WARNING, "Could not access method.", e); Bukkit.getLogger().log(Level.WARNING, "Could not access method.", e);
return this; return this;
@ -344,7 +344,7 @@ public class FancyMessage implements JsonRepresentedObject, Cloneable, Iterable<
Bukkit.getLogger().log(Level.WARNING, "Argument could not be passed.", e); Bukkit.getLogger().log(Level.WARNING, "Argument could not be passed.", e);
return this; return this;
} catch (InvocationTargetException 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);
return this; return this;
} }
} }
@ -370,8 +370,8 @@ public class FancyMessage implements JsonRepresentedObject, Cloneable, Iterable<
*/ */
public FancyMessage itemTooltip(final ItemStack itemStack) { public FancyMessage itemTooltip(final ItemStack itemStack) {
try { try {
Object nmsItem = com.plotsquared.bukkit.chat.Reflection.getMethod(com.plotsquared.bukkit.chat.Reflection.getOBCClass("inventory.CraftItemStack"), "asNMSCopy", ItemStack.class).invoke(null, itemStack); Object nmsItem = Reflection.getMethod(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()); return itemTooltip(Reflection.getMethod(Reflection.getNMSClass("ItemStack"), "save", Reflection.getNMSClass("NBTTagCompound")).invoke(nmsItem, Reflection.getNMSClass("NBTTagCompound").newInstance()).toString());
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
return this; return this;
@ -565,7 +565,7 @@ public class FancyMessage implements JsonRepresentedObject, Cloneable, Iterable<
* @param text The text which will populate the new message component. * @param text The text which will populate the new message component.
* @return This builder instance. * @return This builder instance.
*/ */
public FancyMessage then(final com.plotsquared.bukkit.chat.TextualComponent text) { public FancyMessage then(final TextualComponent text) {
if (!latest().hasText()) { if (!latest().hasText()) {
throw new IllegalStateException("previous message part has no text"); throw new IllegalStateException("previous message part has no text");
} }
@ -641,9 +641,9 @@ public class FancyMessage implements JsonRepresentedObject, Cloneable, Iterable<
} }
Player player = (Player) sender; Player player = (Player) sender;
try { try {
Object handle = com.plotsquared.bukkit.chat.Reflection.getHandle(player); Object handle = Reflection.getHandle(player);
Object connection = com.plotsquared.bukkit.chat.Reflection.getField(handle.getClass(), "playerConnection").get(handle); Object connection = 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)); Reflection.getMethod(connection.getClass(), "sendPacket", Reflection.getNMSClass("Packet")).invoke(connection, createChatPacket(jsonString));
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
Bukkit.getLogger().log(Level.WARNING, "Argument could not be passed.", e); Bukkit.getLogger().log(Level.WARNING, "Argument could not be passed.", e);
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
@ -651,7 +651,7 @@ public class FancyMessage implements JsonRepresentedObject, Cloneable, Iterable<
} catch (InstantiationException e) { } catch (InstantiationException e) {
Bukkit.getLogger().log(Level.WARNING, "Underlying class is abstract.", e); Bukkit.getLogger().log(Level.WARNING, "Underlying class is abstract.", e);
} catch (InvocationTargetException 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) { } catch (NoSuchMethodException e) {
Bukkit.getLogger().log(Level.WARNING, "Could not find method.", e); Bukkit.getLogger().log(Level.WARNING, "Could not find method.", e);
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
@ -673,16 +673,16 @@ public class FancyMessage implements JsonRepresentedObject, Cloneable, Iterable<
// X = major // X = major
// Y = minor // Y = minor
// Z = revision // 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 String[] split = version.substring(1, version.length() - 1).split("_"); // Remove trailing dot
//int majorVersion = Integer.parseInt(split[0]); //int majorVersion = Integer.parseInt(split[0]);
int minorVersion = Integer.parseInt(split[1]); int minorVersion = Integer.parseInt(split[1]);
int revisionVersion = Integer.parseInt(split[2].substring(1)); // Substring to ignore R int revisionVersion = Integer.parseInt(split[2].substring(1)); // Substring to ignore R
if (minorVersion < 8 || (minorVersion == 8 && revisionVersion == 1)) { if (minorVersion < 8 || (minorVersion == 8 && revisionVersion == 1)) {
chatSerializerClazz = com.plotsquared.bukkit.chat.Reflection.getNMSClass("ChatSerializer"); chatSerializerClazz = Reflection.getNMSClass("ChatSerializer");
} else { } else {
chatSerializerClazz = com.plotsquared.bukkit.chat.Reflection.getNMSClass("IChatBaseComponent$ChatSerializer"); chatSerializerClazz = Reflection.getNMSClass("IChatBaseComponent$ChatSerializer");
} }
if (chatSerializerClazz == null) { 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 // 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 // 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); return nmsPacketPlayOutChatConstructor.newInstance(serializedChatComponent);
} }
@ -781,7 +781,7 @@ public class FancyMessage implements JsonRepresentedObject, Cloneable, Iterable<
// Doc copied from interface // Doc copied from interface
public Map<String, Object> serialize() { 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("messageParts", messageParts);
// map.put("JSON", toJSONString()); // map.put("JSON", toJSONString());
return map; return map;
@ -829,9 +829,9 @@ public class FancyMessage implements JsonRepresentedObject, Cloneable, Iterable<
JsonObject messagePart = mPrt.getAsJsonObject(); JsonObject messagePart = mPrt.getAsJsonObject();
for (Map.Entry<String, JsonElement> entry : messagePart.entrySet()) { for (Map.Entry<String, JsonElement> entry : messagePart.entrySet()) {
// Deserialize text // 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 // 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()); serializedMapForm.put("key", entry.getKey());
if (entry.getValue().isJsonPrimitive()) { if (entry.getValue().isJsonPrimitive()) {
// Assume string // Assume string
@ -842,7 +842,7 @@ public class FancyMessage implements JsonRepresentedObject, Cloneable, Iterable<
serializedMapForm.put("value." + compositeNestedElement.getKey(), compositeNestedElement.getValue().getAsString()); 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())) { } else if (MessagePart.stylesToNames.inverse().containsKey(entry.getKey())) {
if (entry.getValue().getAsBoolean()) { if (entry.getValue().getAsBoolean()) {
component.styles.add(MessagePart.stylesToNames.inverse().get(entry.getKey())); 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 { final class MessagePart implements JsonRepresentedObject, ConfigurationSerializable, Cloneable {
ChatColor color = ChatColor.WHITE; ChatColor color = ChatColor.WHITE;
ArrayList<ChatColor> styles = new ArrayList<ChatColor>(); ArrayList<ChatColor> styles = new ArrayList<>();
String clickActionName = null, clickActionData = null, hoverActionName = null; String clickActionName = null;
JsonRepresentedObject hoverActionData = null; String clickActionData = null;
TextualComponent text = null; String hoverActionName = null;
String insertionData = null; JsonRepresentedObject hoverActionData = null;
ArrayList<JsonRepresentedObject> translationReplacements = new ArrayList<JsonRepresentedObject>(); TextualComponent text = null;
String insertionData = null;
ArrayList<JsonRepresentedObject> translationReplacements = new ArrayList<>();
MessagePart(final TextualComponent text) { MessagePart(final TextualComponent text) {
this.text = text; this.text = text;
} }
MessagePart() { MessagePart() {
this.text = null; this.text = null;
} }
boolean hasText() { boolean hasText() {
return text != null; return text != null;
} }
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public MessagePart clone() throws CloneNotSupportedException { public MessagePart clone() throws CloneNotSupportedException {
MessagePart obj = (MessagePart) super.clone(); MessagePart obj = (MessagePart) super.clone();
obj.styles = (ArrayList<ChatColor>) styles.clone(); obj.styles = (ArrayList<ChatColor>) styles.clone();
if (hoverActionData instanceof JsonString) { if (hoverActionData instanceof JsonString) {
obj.hoverActionData = new JsonString(((JsonString) hoverActionData).getValue()); obj.hoverActionData = new JsonString(((JsonString) hoverActionData).getValue());
} else if (hoverActionData instanceof FancyMessage) { } else if (hoverActionData instanceof FancyMessage) {
obj.hoverActionData = ((FancyMessage) hoverActionData).clone(); obj.hoverActionData = ((FancyMessage) hoverActionData).clone();
} }
obj.translationReplacements = (ArrayList<JsonRepresentedObject>) translationReplacements.clone(); obj.translationReplacements = (ArrayList<JsonRepresentedObject>) translationReplacements.clone();
return obj; return obj;
} }
static final BiMap<ChatColor, String> stylesToNames; static final BiMap<ChatColor, String> stylesToNames;
static { static {
ImmutableBiMap.Builder<ChatColor, String> builder = ImmutableBiMap.builder(); ImmutableBiMap.Builder<ChatColor, String> builder = ImmutableBiMap.builder();
for (final ChatColor style : ChatColor.values()) { for (final ChatColor style : ChatColor.values()) {
if (!style.isFormat()) { if (!style.isFormat()) {
continue; continue;
} }
String styleName; String styleName;
switch (style) { switch (style) {
case MAGIC: case MAGIC:
styleName = "obfuscated"; styleName = "obfuscated";
break; break;
case UNDERLINE: case UNDERLINE:
styleName = "underlined"; styleName = "underlined";
break; break;
default: default:
styleName = style.name().toLowerCase(); styleName = style.name().toLowerCase();
break; break;
} }
builder.put(style, styleName); builder.put(style, styleName);
} }
stylesToNames = builder.build(); stylesToNames = builder.build();
} }
public void writeJson(JsonWriter json) { public void writeJson(JsonWriter json) {
try { try {
json.beginObject(); json.beginObject();
text.writeJson(json); text.writeJson(json);
json.name("color").value(color.name().toLowerCase()); json.name("color").value(color.name().toLowerCase());
for (final ChatColor style : styles) { for (final ChatColor style : styles) {
json.name(stylesToNames.get(style)).value(true); json.name(stylesToNames.get(style)).value(true);
} }
if (clickActionName != null && clickActionData != null) { if (clickActionName != null && clickActionData != null) {
json.name("clickEvent") json.name("clickEvent")
.beginObject() .beginObject()
.name("action").value(clickActionName) .name("action").value(clickActionName)
.name("value").value(clickActionData) .name("value").value(clickActionData)
.endObject(); .endObject();
} }
if (hoverActionName != null && hoverActionData != null) { if (hoverActionName != null && hoverActionData != null) {
json.name("hoverEvent") json.name("hoverEvent")
.beginObject() .beginObject()
.name("action").value(hoverActionName) .name("action").value(hoverActionName)
.name("value"); .name("value");
hoverActionData.writeJson(json); hoverActionData.writeJson(json);
json.endObject(); json.endObject();
} }
if (insertionData != null) { if (insertionData != null) {
json.name("insertion").value(insertionData); json.name("insertion").value(insertionData);
} }
if (translationReplacements.size() > 0 && text != null && TextualComponent.isTranslatableText(text)) { if (translationReplacements.size() > 0 && text != null && TextualComponent.isTranslatableText(text)) {
json.name("with").beginArray(); json.name("with").beginArray();
for (JsonRepresentedObject obj : translationReplacements) { for (JsonRepresentedObject obj : translationReplacements) {
obj.writeJson(json); obj.writeJson(json);
} }
json.endArray(); json.endArray();
} }
json.endObject(); json.endObject();
} catch (IOException e) { } catch (IOException e) {
Bukkit.getLogger().log(Level.WARNING, "A problem occured during writing of JSON string", e); Bukkit.getLogger().log(Level.WARNING, "A problem occured during writing of JSON string", e);
} }
} }
public Map<String, Object> serialize() { public Map<String, Object> serialize() {
HashMap<String, Object> map = new HashMap<String, Object>(); HashMap<String, Object> map = new HashMap<>();
map.put("text", text); map.put("text", text);
map.put("styles", styles); map.put("styles", styles);
map.put("color", color.getChar()); map.put("color", color.getChar());
map.put("hoverActionName", hoverActionName); map.put("hoverActionName", hoverActionName);
map.put("hoverActionData", hoverActionData); map.put("hoverActionData", hoverActionData);
map.put("clickActionName", clickActionName); map.put("clickActionName", clickActionName);
map.put("clickActionData", clickActionData); map.put("clickActionData", clickActionData);
map.put("insertion", insertionData); map.put("insertion", insertionData);
map.put("translationReplacements", translationReplacements); map.put("translationReplacements", translationReplacements);
return map; return map;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static MessagePart deserialize(Map<String, Object> serialized) { public static MessagePart deserialize(Map<String, Object> serialized) {
MessagePart part = new MessagePart((TextualComponent) serialized.get("text")); MessagePart part = new MessagePart((TextualComponent) serialized.get("text"));
part.styles = (ArrayList<ChatColor>) serialized.get("styles"); part.styles = (ArrayList<ChatColor>) serialized.get("styles");
part.color = ChatColor.getByChar(serialized.get("color").toString()); part.color = ChatColor.getByChar(serialized.get("color").toString());
part.hoverActionName = (String) serialized.get("hoverActionName"); part.hoverActionName = (String) serialized.get("hoverActionName");
part.hoverActionData = (JsonRepresentedObject) serialized.get("hoverActionData"); part.hoverActionData = (JsonRepresentedObject) serialized.get("hoverActionData");
part.clickActionName = (String) serialized.get("clickActionName"); part.clickActionName = (String) serialized.get("clickActionName");
part.clickActionData = (String) serialized.get("clickActionData"); part.clickActionData = (String) serialized.get("clickActionData");
part.insertionData = (String) serialized.get("insertion"); part.insertionData = (String) serialized.get("insertion");
part.translationReplacements = (ArrayList<JsonRepresentedObject>) serialized.get("translationReplacements"); part.translationReplacements = (ArrayList<JsonRepresentedObject>) serialized.get("translationReplacements");
return part; return part;
} }
static { static {
ConfigurationSerialization.registerClass(MessagePart.class); ConfigurationSerialization.registerClass(MessagePart.class);
} }
} }

View File

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

View File

@ -28,16 +28,6 @@ import com.plotsquared.bukkit.object.BukkitPlayer;
import com.plotsquared.bukkit.util.BukkitUtil; import com.plotsquared.bukkit.util.BukkitUtil;
import com.plotsquared.listener.PlayerBlockEventType; import com.plotsquared.listener.PlayerBlockEventType;
import com.plotsquared.listener.PlotListener; import com.plotsquared.listener.PlotListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.regex.Pattern;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.Material; import org.bukkit.Material;
@ -121,6 +111,17 @@ import org.bukkit.projectiles.BlockProjectileSource;
import org.bukkit.projectiles.ProjectileSource; import org.bukkit.projectiles.ProjectileSource;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.regex.Pattern;
/** /**
* Player Events involving plots. * Player Events involving plots.
* *
@ -1467,6 +1468,7 @@ public class PlayerEvents extends PlotListener implements Listener {
case MINECART_TNT: case MINECART_TNT:
case BOAT: case BOAT:
return checkEntity(plot, Flags.ENTITY_CAP, Flags.VEHICLE_CAP); return checkEntity(plot, Flags.ENTITY_CAP, Flags.VEHICLE_CAP);
case POLAR_BEAR:
case RABBIT: case RABBIT:
case SHEEP: case SHEEP:
case MUSHROOM_COW: case MUSHROOM_COW:

View File

@ -1,6 +1,5 @@
package com.plotsquared.bukkit.util; package com.plotsquared.bukkit.util;
import com.intellectualcrafters.plot.PS;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
@ -9,71 +8,38 @@ import org.bukkit.scheduler.BukkitTask;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.net.Proxy;
import java.net.URL; import java.net.URL;
import java.net.URLConnection; import java.net.URLConnection;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.logging.Level;
import java.util.zip.GZIPOutputStream; import java.util.zip.GZIPOutputStream;
public class Metrics { public class Metrics {
/** /** The current revision number. */
* The current revision number.
*/
private static final int REVISION = 7; private static final int REVISION = 7;
/** /** The base url of the metrics domain.*/
* The base url of the metrics domain.
*/
private static final String BASE_URL = "http://report.mcstats.org"; private static final String BASE_URL = "http://report.mcstats.org";
/** /** The url used to report a server's status. */
* The url used to report a server's status.
*/
private static final String REPORT_URL = "/plugin/%s"; private static final String REPORT_URL = "/plugin/%s";
/** /** Interval of time to ping (in minutes). */
* Interval of time to ping (in minutes).
*/
private static final int PING_INTERVAL = 15; private static final int PING_INTERVAL = 15;
/** /** The plugin this metrics submits for. */
* The plugin this metrics submits for.
*/
private final Plugin plugin; private final Plugin plugin;
/** /** Unique server id. */
* All of the custom graphs to submit to metrics.
*/
private final Set<Graph> graphs = Collections.synchronizedSet(new HashSet<Graph>());
/**
* Unique server id.
*/
private final String guid; private final String guid;
/** /** The scheduled task. */
* Debug mode.
*/
private final boolean debug;
/**
* The scheduled task.
*/
private volatile BukkitTask task = null; private volatile BukkitTask task = null;
public Metrics(Plugin plugin) { public Metrics(Plugin plugin) {
if (plugin == null) {
throw new IllegalArgumentException("Plugin cannot be null");
}
this.plugin = plugin; this.plugin = plugin;
this.guid = UUID.randomUUID().toString(); this.guid = UUID.randomUUID().toString();
this.debug = false;
} }
/** /**
@ -186,38 +152,6 @@ public class Metrics {
return URLEncoder.encode(text, "UTF-8"); return URLEncoder.encode(text, "UTF-8");
} }
/**
* Construct and create a Graph that can be used to separate specific plotters to their own graphs on the metrics
* website. Plotters can be added to the graph object returned.
*
* @param name The name of the graph
*
* @return Graph object created. Will never return NULL under normal circumstances unless bad parameters are given
*/
public Graph createGraph(String name) {
if (name == null) {
throw new IllegalArgumentException("Graph name cannot be null");
}
// Construct the graph object
Graph graph = new Graph(name);
// Now we can add our graph
this.graphs.add(graph);
// and return back
return graph;
}
/**
* Add a Graph object to BukkitMetrics that represents data for the plugin that should be sent to the backend
*
* @param graph The name of the graph
*/
public void addGraph(Graph graph) {
if (graph == null) {
throw new IllegalArgumentException("Graph cannot be null");
}
this.graphs.add(graph);
}
/** /**
* Start measuring statistics. This will immediately create an async repeating task as the plugin and send the * Start measuring statistics. This will immediately create an async repeating task as the plugin and send the
* initial data to the metrics backend, and then after that it will post in increments of PING_INTERVAL * 1200 * initial data to the metrics backend, and then after that it will post in increments of PING_INTERVAL * 1200
@ -244,54 +178,12 @@ public class Metrics {
this.firstPost = false; this.firstPost = false;
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
if (Metrics.this.debug) {
Bukkit.getLogger().log(Level.INFO, "[Metrics] " + e.getMessage());
}
} }
} }
}, 0, PING_INTERVAL * 1200); }, 0, PING_INTERVAL * 1200);
return true; return true;
} }
/**
* Enables metrics for the server by setting "opt-out" to false in the config file and starting the metrics task.
*/
public void enable() {
// Enable Task, if it is not running
if (this.task == null) {
start();
}
}
/**
* Disables metrics for the server by setting "opt-out" to true in the config file and canceling the metrics task.
*/
public void disable() {
// Disable Task, if it is running
if (this.task != null) {
this.task.cancel();
this.task = null;
}
}
/**
* Gets the File object of the config file that should be used to store
* data such as the GUID and opt-out status.
*
* @return the File object for the config file
*/
public File getConfigFile() {
// I believe the easiest way to get the base folder (e.g craftbukkit set
// via -P) for plugins to use
// is to abuse the plugin object we already have
// plugin.getDataFolder() => base/plugins/PluginA/
// pluginsFolder => base/plugins/
// The base is not necessarily relative to the startup directory.
File pluginsFolder = this.plugin.getDataFolder().getParentFile();
// return => base/plugins/PluginMetrics/config.yml
return new File(new File(pluginsFolder, "PluginMetrics"), "config.yml");
}
/** /**
* Generic method that posts a plugin to the metrics website. * Generic method that posts a plugin to the metrics website.
*/ */
@ -342,46 +234,12 @@ public class Metrics {
if (isPing) { if (isPing) {
appendJSONPair(json, "ping", "1"); appendJSONPair(json, "ping", "1");
} }
if (!this.graphs.isEmpty()) {
synchronized (this.graphs) {
json.append(',');
json.append('"');
json.append("graphs");
json.append('"');
json.append(':');
json.append('{');
boolean firstGraph = true;
for (Graph graph : this.graphs) {
StringBuilder graphJson = new StringBuilder();
graphJson.append('{');
for (Plotter plotter : graph.getPlotters()) {
appendJSONPair(graphJson, plotter.getColumnName(), Integer.toString(plotter.getValue()));
}
graphJson.append('}');
if (!firstGraph) {
json.append(',');
}
json.append(escapeJSON(graph.getName()));
json.append(':');
json.append(graphJson);
firstGraph = false;
}
json.append('}');
}
}
// close json // close json
json.append('}'); json.append('}');
// Create the url // Create the url
URL url = new URL(BASE_URL + String.format(REPORT_URL, urlEncode(pluginName))); URL url = new URL(BASE_URL + String.format(REPORT_URL, urlEncode(pluginName)));
// Connect to the website // Connect to the website
URLConnection connection; URLConnection connection = url.openConnection();
// Mineshafter creates a socks proxy, so we can safely bypass it
// It does not reroute POST requests so we need to go around it
if (isMineshafterPresent()) {
connection = url.openConnection(Proxy.NO_PROXY);
} else {
connection = url.openConnection();
}
byte[] uncompressed = json.toString().getBytes(); byte[] uncompressed = json.toString().getBytes();
byte[] compressed = gzip(json.toString()); byte[] compressed = gzip(json.toString());
// Headers // Headers
@ -392,9 +250,6 @@ public class Metrics {
connection.addRequestProperty("Accept", "application/json"); connection.addRequestProperty("Accept", "application/json");
connection.addRequestProperty("Connection", "close"); connection.addRequestProperty("Connection", "close");
connection.setDoOutput(true); connection.setDoOutput(true);
if (this.debug) {
PS.debug("[Metrics] Prepared request for " + pluginName + " uncompressed=" + uncompressed.length + " compressed=" + compressed.length);
}
try { try {
try (OutputStream os = connection.getOutputStream()) { try (OutputStream os = connection.getOutputStream()) {
os.write(compressed); os.write(compressed);
@ -403,9 +258,6 @@ public class Metrics {
String response; String response;
try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) { try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
response = reader.readLine(); response = reader.readLine();
if (this.debug) {
PS.debug("[Metrics] Response for " + pluginName + ": " + response);
}
} }
if (response == null || response.startsWith("ERR") || response.startsWith("7")) { if (response == null || response.startsWith("ERR") || response.startsWith("7")) {
if (response == null) { if (response == null) {
@ -414,171 +266,7 @@ public class Metrics {
response = response.substring(response.startsWith("7,") ? 2 : 1); response = response.substring(response.startsWith("7,") ? 2 : 1);
} }
throw new IOException(response); throw new IOException(response);
} else {
// Is this the first update this hour?
if ("1".equals(response) || response.contains("This is your first update this hour")) {
synchronized (this.graphs) {
for (Graph graph : this.graphs) {
for (Plotter plotter : graph.getPlotters()) {
plotter.reset();
}
}
}
}
} }
} catch (Exception e) { } catch (IOException ignored) {}
if (this.debug) {
e.printStackTrace();
}
}
}
/**
* Check if mineshafter is present. If it is, we need to bypass it to send POST requests
*
* @return true if mineshafter is installed on the server
*/
private boolean isMineshafterPresent() {
try {
Class.forName("mineshafter.MineServer");
return true;
} catch (ClassNotFoundException ignored) {
return false;
}
}
/**
* Represents a custom graph on the website
*/
public static class Graph {
/**
* The graph's name, alphanumeric and spaces only :) If it does not comply to the above when submitted, it is
* rejected
*/
private final String name;
/**
* The set of plotters that are contained within this graph
*/
private final Set<Plotter> plotters = new LinkedHashSet<>();
private Graph(String name) {
this.name = name;
}
/**
* Gets the graph's name
*
* @return the Graph's name
*/
public String getName() {
return this.name;
}
/**
* Add a plotter to the graph, which will be used to plot entries
*
* @param plotter the plotter to add to the graph
*/
public void addPlotter(Plotter plotter) {
this.plotters.add(plotter);
}
/**
* Remove a plotter from the graph
*
* @param plotter the plotter to remove from the graph
*/
public void removePlotter(Plotter plotter) {
this.plotters.remove(plotter);
}
/**
* Gets an <b>unmodifiable</b> set of the plotter objects in the graph
*
* @return an unmodifiable {@link Set} of the plotter objects
*/
public Set<Plotter> getPlotters() {
return Collections.unmodifiableSet(this.plotters);
}
@Override
public int hashCode() {
return this.name.hashCode();
}
@Override
public boolean equals(Object object) {
if (!(object instanceof Graph)) {
return false;
}
Graph graph = (Graph) object;
return graph.name.equals(this.name);
}
}
/**
* Interface used to collect custom data for a plugin
*/
public abstract static class Plotter {
/**
* The plot's name
*/
private final String name;
/**
* Construct a plotter with the default plot name
*/
public Plotter() {
this("Default");
}
/**
* Construct a plotter with a specific plot name
*
* @param name the name of the plotter to use, which will show up on the website
*/
public Plotter(String name) {
this.name = name;
}
/**
* Get the current value for the plotted point. Since this function defers to an external function it may or may
* not return immediately thus cannot be guaranteed to be thread friendly or safe. This function can be called
* from any thread so care should be taken when accessing resources that need to be synchronized.
*
* @return the current value for the point to be plotted.
*/
public abstract int getValue();
/**
* Get the column name for the plotted point
*
* @return the plotted point's column name
*/
public String getColumnName() {
return this.name;
}
/**
* Called after the website graphs have been updated
*/
public void reset() {}
@Override
public int hashCode() {
return getColumnName().hashCode();
}
@Override
public boolean equals(Object object) {
if (!(object instanceof Plotter)) {
return false;
}
Plotter plotter = (Plotter) object;
return plotter.name.equals(this.name) && plotter.getValue() == getValue();
}
} }
} }

View File

@ -0,0 +1,9 @@
package com.intellectualcrafters.plot;
public enum Platform {
Bukkit,
Sponge,
Spigot,
Cauldron
}

View File

@ -118,7 +118,7 @@ public class Auto extends SubCommand {
} }
if (EconHandler.manager != null && plotarea.USE_ECONOMY) { if (EconHandler.manager != null && plotarea.USE_ECONOMY) {
Expression<Double> costExp = plotarea.PRICES.get("claim"); Expression<Double> costExp = plotarea.PRICES.get("claim");
double cost = costExp.evalute((double) currentPlots); double cost = costExp.evaluate((double) currentPlots);
cost = (size_x * size_z) * cost; cost = (size_x * size_z) * cost;
if (cost > 0d) { if (cost > 0d) {
if (EconHandler.manager.getMoney(player) < cost) { if (EconHandler.manager.getMoney(player) < cost) {

View File

@ -50,7 +50,7 @@ public class Claim extends SubCommand {
PlotArea world = plot.getArea(); PlotArea world = plot.getArea();
if ((EconHandler.manager != null) && world.USE_ECONOMY) { if ((EconHandler.manager != null) && world.USE_ECONOMY) {
Expression<Double> costExr = world.PRICES.get("claim"); Expression<Double> costExr = world.PRICES.get("claim");
double cost = costExr.evalute((double) currentPlots); double cost = costExr.evaluate((double) currentPlots);
if (cost > 0d) { if (cost > 0d) {
if (EconHandler.manager.getMoney(player) < cost) { if (EconHandler.manager.getMoney(player) < cost) {
return sendMessage(player, C.CANNOT_AFFORD_PLOT, "" + cost); return sendMessage(player, C.CANNOT_AFFORD_PLOT, "" + cost);

View File

@ -56,7 +56,7 @@ public class Delete extends SubCommand {
plot.removeRunning(); plot.removeRunning();
if ((EconHandler.manager != null) && plotArea.USE_ECONOMY) { if ((EconHandler.manager != null) && plotArea.USE_ECONOMY) {
Expression<Double> valueExr = plotArea.PRICES.get("sell"); Expression<Double> valueExr = plotArea.PRICES.get("sell");
double value = plots.size() * valueExr.evalute((double) currentPlots); double value = plots.size() * valueExr.evaluate((double) currentPlots);
if (value > 0d) { if (value > 0d) {
EconHandler.manager.depositMoney(player, value); EconHandler.manager.depositMoney(player, value);
sendMessage(player, C.ADDED_BALANCE, String.valueOf(value)); sendMessage(player, C.ADDED_BALANCE, String.valueOf(value));

View File

@ -141,7 +141,7 @@ public class MainCommand extends Command {
PlotArea area = player.getApplicablePlotArea(); PlotArea area = player.getApplicablePlotArea();
if (area != null) { if (area != null) {
Expression<Double> priceEval = area.PRICES.get(cmd.getFullId()); Expression<Double> priceEval = area.PRICES.get(cmd.getFullId());
Double price = priceEval != null ? priceEval.evalute(0d) : 0d; Double price = priceEval != null ? priceEval.evaluate(0d) : 0d;
if (price != null && EconHandler.manager.getMoney(player) < price) { if (price != null && EconHandler.manager.getMoney(player) < price) {
if (failure != null) { if (failure != null) {
failure.run(); failure.run();
@ -161,7 +161,7 @@ public class MainCommand extends Command {
PlotArea area = player.getApplicablePlotArea(); PlotArea area = player.getApplicablePlotArea();
if (area != null) { if (area != null) {
Expression<Double> priceEval = area.PRICES.get(cmd.getFullId()); Expression<Double> priceEval = area.PRICES.get(cmd.getFullId());
Double price = priceEval != null ? priceEval.evalute(0d) : 0d; Double price = priceEval != null ? priceEval.evaluate(0d) : 0d;
if (price != 0d && EconHandler.manager.getMoney(player) < price) { if (price != 0d && EconHandler.manager.getMoney(player) < price) {
if (failure != null) { if (failure != null) {
failure.run(); failure.run();

View File

@ -74,7 +74,7 @@ public class Merge extends SubCommand {
final PlotArea plotArea = plot.getArea(); final PlotArea plotArea = plot.getArea();
Expression<Double> priceExr = plotArea.PRICES.containsKey("merge") ? plotArea.PRICES.get("merge") : null; Expression<Double> priceExr = plotArea.PRICES.containsKey("merge") ? plotArea.PRICES.get("merge") : null;
final int size = plot.getConnectedPlots().size(); final int size = plot.getConnectedPlots().size();
final double price = priceExr == null ? 0d : priceExr.evalute((double) size); final double price = priceExr == null ? 0d : priceExr.evaluate((double) size);
if (EconHandler.manager != null && plotArea.USE_ECONOMY && price > 0d && EconHandler.manager.getMoney(player) < price) { if (EconHandler.manager != null && plotArea.USE_ECONOMY && price > 0d && EconHandler.manager.getMoney(player) < price) {
sendMessage(player, C.CANNOT_AFFORD_MERGE, String.valueOf(price)); sendMessage(player, C.CANNOT_AFFORD_MERGE, String.valueOf(price));
return false; return false;

View File

@ -75,7 +75,7 @@ public enum C {
*/ */
CONSOLE_JAVA_OUTDATED_1_8("&cYour version of java is outdated. It is highly recommended that you update to Java 8 as it increases performance " CONSOLE_JAVA_OUTDATED_1_8("&cYour version of java is outdated. It is highly recommended that you update to Java 8 as it increases performance "
+ "and security. PlotSquared will require Java 9 in a future update.", "static.console"), + "and security. PlotSquared will require Java 9 in a future update.", "static.console"),
CONSOLE_PLEASE_ENABLE_METRICS("&dPlease enable metrics for PlotSquared. Using metrics improves plugin stabability, performance, and features. " CONSOLE_PLEASE_ENABLE_METRICS("&dPlease enable metrics for PlotSquared. Using metrics improves plugin stability, performance, and features. "
+ "Bug fixes and new features are influenced on metrics.", "static.console"), + "Bug fixes and new features are influenced on metrics.", "static.console"),
/* /*
* Confirm * Confirm
@ -368,7 +368,7 @@ public enum C {
/* /*
* Unknown Error * Unknown Error
*/ */
ERROR("$2An error occured: %s", "Errors"), ERROR("$2An error occurred: %s", "Errors"),
// SETTINGS_PASTE_UPLOADED("$2settings.yml was uploaded to: $1%url%", "Paste"), // SETTINGS_PASTE_UPLOADED("$2settings.yml was uploaded to: $1%url%", "Paste"),
// LATEST_LOG_UPLOADED("$2latest.log was uploaded to: $1%url%", "Paste"), // LATEST_LOG_UPLOADED("$2latest.log was uploaded to: $1%url%", "Paste"),
DEBUG_REPORT_CREATED("$1Uploaded a full debug to: $1%url%", "Paste"), DEBUG_REPORT_CREATED("$1Uploaded a full debug to: $1%url%", "Paste"),

View File

@ -296,7 +296,7 @@ public class Settings extends Config {
public static boolean WORLDEDIT_RESTRICTIONS = true; public static boolean WORLDEDIT_RESTRICTIONS = true;
@Comment("Allow economy to be used") @Comment("Allow economy to be used")
public static boolean ECONOMY = true; public static boolean ECONOMY = true;
@Comment("Send anonymous usage statistics") @Comment("Send anonymous usage statistics. Bukkit only setting.")
public static boolean METRICS = true; public static boolean METRICS = true;
@Comment("Expiry will clear old or simplistic plots") @Comment("Expiry will clear old or simplistic plots")
public static boolean PLOT_EXPIRY = false; public static boolean PLOT_EXPIRY = false;

View File

@ -6,12 +6,12 @@ import com.intellectualcrafters.plot.commands.MainCommand;
import javax.script.ScriptException; import javax.script.ScriptException;
public abstract class Expression<T> { public abstract class Expression<T> {
public abstract T evalute(T arg); public abstract T evaluate(T arg);
public static <U> Expression<U> constant(final U value) { public static <U> Expression<U> constant(final U value) {
return new Expression<U>() { return new Expression<U>() {
@Override @Override
public U evalute(U arg) { public U evaluate(U arg) {
return value; return value;
} }
}; };
@ -20,8 +20,8 @@ public abstract class Expression<T> {
public static Expression<Double> linearDouble(final Double value) { public static Expression<Double> linearDouble(final Double value) {
return new Expression<Double>() { return new Expression<Double>() {
@Override @Override
public Double evalute(Double arg) { public Double evaluate(Double arg) {
return (arg.doubleValue() * value.doubleValue()); return (arg * value);
} }
}; };
} }
@ -29,15 +29,15 @@ public abstract class Expression<T> {
public static Expression<Double> doubleExpression(final String expression) { public static Expression<Double> doubleExpression(final String expression) {
try { try {
return constant(Double.parseDouble(expression)); return constant(Double.parseDouble(expression));
} catch (Exception ignore) {} } catch (NumberFormatException ignore) {}
if (expression.endsWith("*{arg}")) { if (expression.endsWith("*{arg}")) {
try { try {
return linearDouble(Double.parseDouble(expression.substring(0, expression.length() - 6))); return linearDouble(Double.parseDouble(expression.substring(0, expression.length() - 6)));
} catch (Exception ignore) {} } catch (NumberFormatException ignore) {}
} }
return new Expression<Double>() { return new Expression<Double>() {
@Override @Override
public Double evalute(Double arg) { public Double evaluate(Double arg) {
DebugExec exec = (DebugExec) MainCommand.getInstance().getCommand(DebugExec.class); DebugExec exec = (DebugExec) MainCommand.getInstance().getCommand(DebugExec.class);
try { try {
return (Double) exec.getEngine().eval(expression.replace("{arg}", "" + arg)); return (Double) exec.getEngine().eval(expression.replace("{arg}", "" + arg));

View File

@ -19,12 +19,18 @@ apply plugin: 'net.minecrell.vanilla.server.library'
dependencies { dependencies {
compile project(':Core') compile project(':Core')
compile 'org.spongepowered:spongeapi:5.0.0-SNAPSHOT' compile 'org.spongepowered:spongeapi:5.0.0-SNAPSHOT'
compile 'net.minecrell.mcstats:statslite-sponge:0.2.2'
} }
sourceCompatibility = 1.8 sourceCompatibility = 1.8
targetCompatibility = 1.8 targetCompatibility = 1.8
repositories { repositories {
maven {
name = 'minecrell'
url = 'http://repo.minecrell.net/releases'
}
maven { maven {
name = 'forge' name = 'forge'
url = 'http://files.minecraftforge.net/maven' url = 'http://files.minecraftforge.net/maven'
@ -51,9 +57,9 @@ processResources {
shadowJar { shadowJar {
dependencies { dependencies {
include(dependency(':Core')) include(dependency(':Core'))
//include(dependency('org.mcstats.sponge:metrics:R8-SNAPSHOT')) include dependency('net.minecrell.mcstats:statslite-sponge')
} }
//relocate 'org.mcstats', 'com.plotsquared.stats' relocate 'net.minecrell.mcstats', 'com.plotsquared.util.mcstats'
archiveName = "${parent.name}-${project.name}-${parent.version}.jar" archiveName = "${parent.name}-${project.name}-${parent.version}.jar"
destinationDir = file '../target' destinationDir = file '../target'
} }

View File

@ -41,7 +41,6 @@ import com.plotsquared.sponge.util.SpongeEconHandler;
import com.plotsquared.sponge.util.SpongeEventUtil; import com.plotsquared.sponge.util.SpongeEventUtil;
import com.plotsquared.sponge.util.SpongeHybridUtils; import com.plotsquared.sponge.util.SpongeHybridUtils;
import com.plotsquared.sponge.util.SpongeInventoryUtil; import com.plotsquared.sponge.util.SpongeInventoryUtil;
import com.plotsquared.sponge.util.SpongeMetrics;
import com.plotsquared.sponge.util.SpongeSchematicHandler; import com.plotsquared.sponge.util.SpongeSchematicHandler;
import com.plotsquared.sponge.util.SpongeSetupUtils; import com.plotsquared.sponge.util.SpongeSetupUtils;
import com.plotsquared.sponge.util.SpongeTaskManager; import com.plotsquared.sponge.util.SpongeTaskManager;
@ -51,6 +50,7 @@ import com.plotsquared.sponge.util.block.SpongeLocalQueue;
import com.plotsquared.sponge.uuid.SpongeLowerOfflineUUIDWrapper; import com.plotsquared.sponge.uuid.SpongeLowerOfflineUUIDWrapper;
import com.plotsquared.sponge.uuid.SpongeOnlineUUIDWrapper; import com.plotsquared.sponge.uuid.SpongeOnlineUUIDWrapper;
import com.plotsquared.sponge.uuid.SpongeUUIDHandler; import com.plotsquared.sponge.uuid.SpongeUUIDHandler;
import net.minecrell.mcstats.SpongeStatsLite;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.spongepowered.api.Game; import org.spongepowered.api.Game;
import org.spongepowered.api.Server; import org.spongepowered.api.Server;
@ -59,6 +59,7 @@ import org.spongepowered.api.config.ConfigDir;
import org.spongepowered.api.entity.living.player.Player; import org.spongepowered.api.entity.living.player.Player;
import org.spongepowered.api.event.Listener; import org.spongepowered.api.event.Listener;
import org.spongepowered.api.event.game.state.GameAboutToStartServerEvent; import org.spongepowered.api.event.game.state.GameAboutToStartServerEvent;
import org.spongepowered.api.event.game.state.GamePreInitializationEvent;
import org.spongepowered.api.plugin.Plugin; import org.spongepowered.api.plugin.Plugin;
import org.spongepowered.api.plugin.PluginContainer; import org.spongepowered.api.plugin.PluginContainer;
import org.spongepowered.api.profile.GameProfileManager; import org.spongepowered.api.profile.GameProfileManager;
@ -90,6 +91,9 @@ public class SpongeMain implements IPlotMain {
@Inject @Inject
private Game game; private Game game;
@Inject
public SpongeStatsLite stats;
private Server server; private Server server;
@Inject @Inject
@ -98,8 +102,7 @@ public class SpongeMain implements IPlotMain {
private GameProfileManager resolver; private GameProfileManager resolver;
// @Override private Logger getLogger() {
public Logger getLogger() {
return this.logger; return this.logger;
} }
@ -122,6 +125,12 @@ public class SpongeMain implements IPlotMain {
return THIS; return THIS;
} }
@Listener
public void onPreInitialize(GamePreInitializationEvent event) {
getLogger().info("The metrics section in PlotSquared is ignored in favor of the actual metrics reporter configurations.");
this.stats.start();
}
@Listener @Listener
public void onServerAboutToStart(GameAboutToStartServerEvent event) { public void onServerAboutToStart(GameAboutToStartServerEvent event) {
THIS = this; THIS = this;
@ -295,9 +304,6 @@ public class SpongeMain implements IPlotMain {
@Override @Override
public void startMetrics() { public void startMetrics() {
SpongeMetrics metrics = new SpongeMetrics(this.game, this.plugin);
metrics.start();
PS.log(C.PREFIX.s() + "&6Metrics enabled.");
} }
@Override @Override