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(); + } +}