diff --git a/pom.xml b/pom.xml
index 92ace9e..bdcc452 100644
--- a/pom.xml
+++ b/pom.xml
@@ -237,6 +237,20 @@
system
${basedir}/libs/BossBarAPI.jar
+
+ viaversion
+ viaversion
+ 1
+ system
+ ${basedir}/libs/ViaVersion.jar
+
+
+ protocolsupport
+ protocolsupport
+ 1
+ system
+ ${basedir}/libs/ProtocolSupport.jar
+
deprecated
deprecated
diff --git a/src/main/java/com/ilummc/tlib/resources/TLocale.java b/src/main/java/com/ilummc/tlib/resources/TLocale.java
index e148ea2..8f3f115 100644
--- a/src/main/java/com/ilummc/tlib/resources/TLocale.java
+++ b/src/main/java/com/ilummc/tlib/resources/TLocale.java
@@ -2,7 +2,6 @@ package com.ilummc.tlib.resources;
import com.ilummc.tlib.TLib;
import com.ilummc.tlib.bungee.api.ChatColor;
-import com.ilummc.tlib.bungee.api.chat.BaseComponent;
import com.ilummc.tlib.bungee.api.chat.TextComponent;
import com.ilummc.tlib.bungee.chat.ComponentSerializer;
import com.ilummc.tlib.inject.TLoggerManager;
@@ -10,15 +9,11 @@ import com.ilummc.tlib.util.Ref;
import com.ilummc.tlib.util.Strings;
import me.clip.placeholderapi.PlaceholderAPI;
import me.skymc.taboolib.Main;
-import me.skymc.taboolib.nms.NMSUtil19;
-import me.skymc.taboolib.nms.NMSUtils;
+import me.skymc.taboolib.json.tellraw.TellrawCreator;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
@@ -139,23 +134,12 @@ public class TLocale {
public static class Tellraw extends TLocale {
- private static final Class> chatSerializer = NMSUtils.getNMSClassSilent("ChatSerializer", "IChatBaseComponent");
- private static final Method chatSerializerA = NMSUtils.getMethodSilent(chatSerializer, "a", String.class);
- private static final Field playerConnection = NMSUtils.getFieldSilent(NMSUtil19.class_EntityPlayer, "playerConnection");
- private static final Method sendPacket = NMSUtils.getMethodSilent(NMSUtil19.class_PlayerConnection, "sendPacket", NMSUtil19.class_Packet);
- private static final Constructor> PacketPlayOutChat = NMSUtils.getConstructorSilent(NMSUtil19.class_PacketPlayOutChat, NMSUtil19.class_IChatBaseComponent);
-
public static void send(CommandSender sender, String rawMessage) {
if (sender instanceof Player) {
- try {
- sendPacket.invoke(playerConnection.get(NMSUtils.getHandle(sender)), PacketPlayOutChat.newInstance(chatSerializerA.invoke(null, rawMessage)));
- } catch (Exception e) {
- Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), "tellraw " + sender.getName() + " " + rawMessage);
- }
+ TellrawCreator.getAbstractTellraw().sendRawMessage((Player) sender, rawMessage);
} else {
sender.sendMessage(TextComponent.toLegacyText(ComponentSerializer.parse(rawMessage)));
}
}
-
}
}
diff --git a/src/main/java/me/skymc/taboolib/common/util/SimpleReflection.java b/src/main/java/me/skymc/taboolib/common/util/SimpleReflection.java
new file mode 100644
index 0000000..5fcba1d
--- /dev/null
+++ b/src/main/java/me/skymc/taboolib/common/util/SimpleReflection.java
@@ -0,0 +1,85 @@
+package me.skymc.taboolib.common.util;
+
+import com.google.common.collect.Maps;
+
+import java.lang.reflect.Field;
+import java.util.Arrays;
+import java.util.Map;
+
+/**
+ * @Author 坏黑
+ * @Since 2018-10-25 22:51
+ */
+public class SimpleReflection {
+
+ private static Map> fieldCached = Maps.newHashMap();
+
+ public static void saveFiled(Class> nmsClass) {
+ try {
+ Arrays.stream(nmsClass.getDeclaredFields()).forEach(declaredField -> saveFiled(nmsClass, declaredField.getName()));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static void saveFiled(Class> nmsClass, String fieldName) {
+ try {
+ Field declaredField = nmsClass.getDeclaredField(fieldName);
+ declaredField.setAccessible(true);
+ fieldCached.computeIfAbsent(nmsClass.getName(), name -> Maps.newHashMap()).put(fieldName, declaredField);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static void setFieldValue(Class> nmsClass, Object instance, String fieldName, Object value) {
+ try {
+ Map fields = fieldCached.get(nmsClass.getName());
+ if (fields == null) {
+ return;
+ }
+ Field field = fields.get(fieldName);
+ if (value == null) {
+ return;
+ }
+ field.set(instance, value);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static Object getFieldValue(Class> nmsClass, Object instance, String fieldName) {
+ try {
+ Map fields = fieldCached.get(nmsClass.getName());
+ if (fields == null) {
+ return null;
+ }
+ Field field = fields.get(fieldName);
+ if (field == null) {
+ return null;
+ }
+ return field.get(instance);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ public static T getFieldValue(Class> nmsClass, Object instance, String fieldName, T def) {
+ try {
+ Map fields = fieldCached.get(nmsClass.getName());
+ if (fields == null) {
+ return def;
+ }
+ Field field = fields.get(fieldName);
+ if (field == null) {
+ return def;
+ }
+ return (T) field.get(instance);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return def;
+ }
+
+}
diff --git a/src/main/java/me/skymc/taboolib/json/tellraw/TellrawCreator.java b/src/main/java/me/skymc/taboolib/json/tellraw/TellrawCreator.java
new file mode 100644
index 0000000..d634aeb
--- /dev/null
+++ b/src/main/java/me/skymc/taboolib/json/tellraw/TellrawCreator.java
@@ -0,0 +1,50 @@
+package me.skymc.taboolib.json.tellraw;
+
+import me.skymc.taboolib.common.loader.Instantiable;
+import me.skymc.taboolib.common.versioncontrol.SimpleVersionControl;
+import me.skymc.taboolib.json.tellraw.internal.AbstractTellraw;
+import org.bukkit.Bukkit;
+
+/**
+ * @Author 坏黑
+ * @Since 2018-11-07 22:58
+ */
+@Instantiable("TabooLib|TellrawCreator")
+public class TellrawCreator {
+
+ private static AbstractTellraw abstractTellraw;
+ private static boolean viaVersionLoaded;
+ private static boolean protocolSupportLoaded;
+
+ public TellrawCreator() {
+ viaVersionLoaded = Bukkit.getPluginManager().getPlugin("ViaVersion") != null;
+ protocolSupportLoaded = Bukkit.getPluginManager().getPlugin("ProtocolSupport") != null;
+ try {
+ abstractTellraw = (AbstractTellraw) SimpleVersionControl.create()
+ .from("v1_8_R3")
+ .target("me.skymc.taboolib.json.tellraw.internal.InternalTellraw")
+ .translate()
+ .newInstance();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ // *********************************
+ //
+ // Getter and Setter
+ //
+ // *********************************
+
+ public static AbstractTellraw getAbstractTellraw() {
+ return abstractTellraw;
+ }
+
+ public static boolean isViaVersionLoaded() {
+ return viaVersionLoaded;
+ }
+
+ public static boolean isProtocolSupportLoaded() {
+ return protocolSupportLoaded;
+ }
+}
diff --git a/src/main/java/me/skymc/taboolib/json/tellraw/TellrawJson.java b/src/main/java/me/skymc/taboolib/json/tellraw/TellrawJson.java
index ba2e288..6f3bf5d 100644
--- a/src/main/java/me/skymc/taboolib/json/tellraw/TellrawJson.java
+++ b/src/main/java/me/skymc/taboolib/json/tellraw/TellrawJson.java
@@ -2,17 +2,20 @@ package me.skymc.taboolib.json.tellraw;
import com.ilummc.tlib.bungee.api.chat.*;
import com.ilummc.tlib.bungee.chat.ComponentSerializer;
-import com.ilummc.tlib.logger.TLogger;
import com.ilummc.tlib.resources.TLocale;
-import me.skymc.taboolib.methods.ReflectionUtils;
-import me.skymc.taboolib.nms.NMSUtils;
+import com.ilummc.tlib.util.Strings;
+import me.skymc.taboolib.TabooLib;
import me.skymc.taboolib.string.ArrayUtils;
import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
+import protocolsupport.api.ProtocolSupportAPI;
+import us.myles.ViaVersion.api.Via;
-import java.lang.reflect.Method;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.stream.Collectors;
/**
@@ -24,10 +27,8 @@ public class TellrawJson {
private List components = new ArrayList<>();
private List componentsLatest = new ArrayList<>();
- private static final Class> craftItemStackClazz = NMSUtils.getOBCClass("inventory.CraftItemStack");
- private static final Class> nmsItemStackClazz = NMSUtils.getNMSClass("ItemStack");
- private static final Class> nbtTagCompoundClazz = NMSUtils.getNMSClass("NBTTagCompound");
- private static final String INVALID_ITEM = "{id:stone,tag:{display:{Name:§c* Invalid ItemStack *}}}";
+ private Map itemTag = new HashMap<>();
+ private int bukkitVersion = TabooLib.getVersionNumber();
TellrawJson() {
}
@@ -37,13 +38,38 @@ public class TellrawJson {
}
public void send(CommandSender sender) {
- TLocale.Tellraw.send(sender, toRawMessage());
+ send(sender, new String[0]);
+ }
+
+ public void send(CommandSender sender, String... args) {
+ if (sender instanceof Player) {
+ if (TellrawCreator.isViaVersionLoaded()) {
+ TLocale.Tellraw.send(sender, Strings.replaceWithOrder(toRawMessage(Via.getAPI().getPlayerVersion(sender) > 316 ? TellrawVersion.HIGH_VERSION : TellrawVersion.LOW_VERSION), args));
+ } else if (TellrawCreator.isProtocolSupportLoaded()) {
+ TLocale.Tellraw.send(sender, Strings.replaceWithOrder(toRawMessage(ProtocolSupportAPI.getProtocolVersion((Player) sender).getId() > 316 ? TellrawVersion.HIGH_VERSION : TellrawVersion.LOW_VERSION), args));
+ } else {
+ TLocale.Tellraw.send(sender, Strings.replaceWithOrder(toRawMessage(), args));
+ }
+ } else {
+ TLocale.Tellraw.send(sender, Strings.replaceWithOrder(toRawMessage(), args));
+ }
}
public String toRawMessage() {
return ComponentSerializer.toString(getComponentsAll());
}
+ public String toRawMessage(TellrawVersion version) {
+ String rawMessage = toRawMessage();
+ if (version == TellrawVersion.CURRENT_VERSION) {
+ return rawMessage;
+ }
+ for (Map.Entry stringEntry : itemTag.entrySet()) {
+ rawMessage = rawMessage.replace(stringEntry.getKey(), version == TellrawVersion.HIGH_VERSION ? stringEntry.getValue()[1] : stringEntry.getValue()[0]);
+ }
+ return rawMessage;
+ }
+
public String toLegacyText() {
return TextComponent.toLegacyText(getComponentsAll());
}
@@ -61,6 +87,7 @@ public class TellrawJson {
public TellrawJson append(TellrawJson json) {
appendComponents();
componentsLatest.addAll(ArrayUtils.asList(json.getComponentsAll()));
+ itemTag.putAll(json.itemTag);
return this;
}
@@ -70,7 +97,18 @@ public class TellrawJson {
}
public TellrawJson hoverItem(ItemStack itemStack) {
- getLatestComponent().forEach(component -> component.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_ITEM, new ComponentBuilder(getItemComponent(itemStack)).create())));
+ return hoverItem(itemStack, true);
+ }
+
+ public TellrawJson hoverItem(ItemStack itemStack, boolean supportVersion) {
+ BaseComponent[] itemComponentCurrentVersion = new ComponentBuilder(TellrawCreator.getAbstractTellraw().getItemComponent(itemStack, TellrawVersion.CURRENT_VERSION)).create();
+ getLatestComponent().forEach(component -> component.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_ITEM, itemComponentCurrentVersion)));
+ if (supportVersion) {
+ itemTag.put(ComponentSerializer.toString(itemComponentCurrentVersion), new String[] {
+ ComponentSerializer.toString(new ComponentBuilder(TellrawCreator.getAbstractTellraw().getItemComponent(itemStack, TellrawVersion.LOW_VERSION)).create()),
+ ComponentSerializer.toString(new ComponentBuilder(TellrawCreator.getAbstractTellraw().getItemComponent(itemStack, TellrawVersion.HIGH_VERSION)).create())
+ });
+ }
return this;
}
@@ -100,19 +138,6 @@ public class TellrawJson {
return components.toArray(new BaseComponent[0]);
}
- public String getItemComponent(ItemStack itemStack) {
- try {
- Method asNMSCopyMethod = ReflectionUtils.getMethod(craftItemStackClazz, "asNMSCopy", ItemStack.class);
- Method saveNmsItemStackMethod = ReflectionUtils.getMethod(nmsItemStackClazz, "save", nbtTagCompoundClazz);
- Object nmsNbtTagCompoundObj = nbtTagCompoundClazz.newInstance();
- Object nmsItemStackObj = asNMSCopyMethod.invoke(null, itemStack);
- return saveNmsItemStackMethod.invoke(nmsItemStackObj, nmsNbtTagCompoundObj).toString();
- } catch (Throwable t) {
- TLogger.getGlobalLogger().error("failed to serialize bukkit item to nms item: " + t.toString());
- return INVALID_ITEM;
- }
- }
-
// *********************************
//
// Private Methods
diff --git a/src/main/java/me/skymc/taboolib/json/tellraw/TellrawVersion.java b/src/main/java/me/skymc/taboolib/json/tellraw/TellrawVersion.java
new file mode 100644
index 0000000..81bc02d
--- /dev/null
+++ b/src/main/java/me/skymc/taboolib/json/tellraw/TellrawVersion.java
@@ -0,0 +1,10 @@
+package me.skymc.taboolib.json.tellraw;
+
+/**
+ * @Author 坏黑
+ * @Since 2018-11-07 22:53
+ */
+public enum TellrawVersion {
+
+ LOW_VERSION, HIGH_VERSION, CURRENT_VERSION
+}
diff --git a/src/main/java/me/skymc/taboolib/json/tellraw/internal/AbstractTellraw.java b/src/main/java/me/skymc/taboolib/json/tellraw/internal/AbstractTellraw.java
new file mode 100644
index 0000000..5bbf71e
--- /dev/null
+++ b/src/main/java/me/skymc/taboolib/json/tellraw/internal/AbstractTellraw.java
@@ -0,0 +1,19 @@
+package me.skymc.taboolib.json.tellraw.internal;
+
+import me.skymc.taboolib.json.tellraw.TellrawVersion;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+
+/**
+ * @Author 坏黑
+ * @Since 2018-11-07 22:52
+ */
+public interface AbstractTellraw {
+
+ void sendRawMessage(Player player, String rawMessage);
+
+ String getItemComponent(ItemStack itemStack);
+
+ String getItemComponent(ItemStack itemStack, TellrawVersion version);
+
+}
diff --git a/src/main/java/me/skymc/taboolib/json/tellraw/internal/InternalTellraw.java b/src/main/java/me/skymc/taboolib/json/tellraw/internal/InternalTellraw.java
new file mode 100644
index 0000000..52f6240
--- /dev/null
+++ b/src/main/java/me/skymc/taboolib/json/tellraw/internal/InternalTellraw.java
@@ -0,0 +1,81 @@
+package me.skymc.taboolib.json.tellraw.internal;
+
+import me.skymc.taboolib.TabooLib;
+import me.skymc.taboolib.common.packet.TPacketHandler;
+import me.skymc.taboolib.common.util.SimpleReflection;
+import me.skymc.taboolib.json.tellraw.TellrawVersion;
+import net.minecraft.server.v1_8_R3.IChatBaseComponent;
+import net.minecraft.server.v1_8_R3.NBTTagCompound;
+import net.minecraft.server.v1_8_R3.NBTTagList;
+import net.minecraft.server.v1_8_R3.PacketPlayOutChat;
+import org.bukkit.craftbukkit.v1_8_R3.inventory.CraftItemStack;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @Author 坏黑
+ * @Since 2018-11-07 22:54
+ */
+public class InternalTellraw implements AbstractTellraw {
+
+ private int bukkitVersion = TabooLib.getVersionNumber();
+
+ public InternalTellraw() {
+ SimpleReflection.saveFiled(NBTTagCompound.class, "map");
+ SimpleReflection.saveFiled(NBTTagList.class, "list");
+ }
+
+ @Override
+ public void sendRawMessage(Player player, String rawMessage) {
+ TPacketHandler.sendPacket(player, new PacketPlayOutChat(IChatBaseComponent.ChatSerializer.a(rawMessage)));
+ }
+
+ @Override
+ public String getItemComponent(ItemStack itemStack) {
+ return getItemComponent(itemStack, TellrawVersion.CURRENT_VERSION);
+ }
+
+ @Override
+ public String getItemComponent(ItemStack itemStack, TellrawVersion version) {
+ return nbtToString(CraftItemStack.asNMSCopy(itemStack).save(new NBTTagCompound()), version);
+ }
+
+ private String nbtToString(Object nbtTagCompound, TellrawVersion version) {
+ StringBuilder builder = new StringBuilder("{");
+ Map map = (Map) SimpleReflection.getFieldValue(NBTTagCompound.class, nbtTagCompound, "map");
+ int index = 0;
+ for (Object nbtBaseEntry : map.entrySet()) {
+ if (index++ != 0) {
+ builder.append(",");
+ }
+ Object value = ((Map.Entry) nbtBaseEntry).getValue();
+ if (value instanceof NBTTagList ) {
+ builder.append(((Map.Entry) nbtBaseEntry).getKey()).append(":").append(nbtListToString(value, version));
+ } else if (value instanceof NBTTagCompound) {
+ builder.append(((Map.Entry) nbtBaseEntry).getKey()).append(":").append(nbtToString(value, version));
+ } else {
+ builder.append(((Map.Entry) nbtBaseEntry).getKey()).append(":").append(value);
+ }
+ }
+ return builder.append('}').toString();
+ }
+
+ private String nbtListToString(Object nbtTagList, TellrawVersion version) {
+ StringBuilder builder = new StringBuilder("[");
+ List list = (List) SimpleReflection.getFieldValue(NBTTagList.class, nbtTagList, "list");
+ for (int i = 0; i < list.size(); ++i) {
+ if (i != 0) {
+ builder.append(',');
+ }
+ if (version == TellrawVersion.HIGH_VERSION || (this.bukkitVersion >= 11200 && version == TellrawVersion.CURRENT_VERSION)) {
+ builder.append(list.get(i));
+ } else {
+ builder.append(i).append(':').append(list.get(i));
+ }
+ }
+ return builder.append(']').toString();
+ }
+}