Support all versions in titles via reflection. Resolves drtshock/Factions#1102

This commit is contained in:
Trent Hensler 2018-03-20 20:14:26 -07:00
parent 382f4c4b0c
commit 12ab4f4fed
3 changed files with 105 additions and 1 deletions

View File

@ -132,6 +132,7 @@ public class P extends MPlugin {
// since some other plugins execute commands directly through this command interface, provide it
this.getCommand(this.refCommand).setExecutor(this);
new TitleAPI();
setupPlaceholderAPI();
postEnable();
this.loadSuccessful = true;

View File

@ -0,0 +1,102 @@
package com.massivecraft.factions.util;
import com.massivecraft.factions.P;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
/**
* With help from https://www.spigotmc.org/threads/send-titles-to-players-using-spigot-1-8-1-11-2.48819/
*/
public class TitleAPI {
private static TitleAPI instance;
private boolean supportsAPI = false;
private Map<String, Class> classCache = new HashMap<>();
public TitleAPI() {
instance = this;
try {
Player.class.getMethod("sendTitle", String.class, String.class, int.class, int.class, int.class);
supportsAPI = true;
P.p.log(Level.INFO, "Found API support for sending player titles :D");
} catch (NoSuchMethodException e) {
P.p.log(Level.WARNING, "Didn't find API support for sending titles :( Will attempt reflection. No promises.");
}
}
/**
* Send a title to player
*
* @param player Player to send the title to
* @param title The text displayed in the title
* @param subtitle The text displayed in the subtitle
* @param fadeInTime The time the title takes to fade in
* @param showTime The time the title is displayed
* @param fadeOutTime The time the title takes to fade out
*/
public void sendTitle(Player player, String title, String subtitle, int fadeInTime, int showTime, int fadeOutTime) {
if (supportsAPI) {
player.sendTitle(title, subtitle, fadeInTime, showTime, fadeOutTime);
return;
}
try {
Object chatTitle = getNMSClass("IChatBaseComponent").getDeclaredClasses()[0].getMethod("a", String.class).invoke(null, "{\"text\": \"" + title + "\"}");
Object chatsubTitle = getNMSClass("IChatBaseComponent").getDeclaredClasses()[0].getMethod("a", String.class).invoke(null, "{\"text\": \"" + subtitle + "\"}");
Constructor<?> titleConstructor = getNMSClass("PacketPlayOutTitle").getConstructor(getNMSClass("PacketPlayOutTitle").getDeclaredClasses()[0], getNMSClass("IChatBaseComponent"), int.class, int.class, int.class);
Object titlePacket = titleConstructor.newInstance(getNMSClass("PacketPlayOutTitle").getDeclaredClasses()[0].getField("TITLE").get(null), chatTitle, fadeInTime, showTime, fadeOutTime);
Object subTitlePacket = titleConstructor.newInstance(getNMSClass("PacketPlayOutTitle").getDeclaredClasses()[0].getField("SUBTITLE").get(null), chatsubTitle, fadeInTime, showTime, fadeOutTime);
sendPacket(player, titlePacket);
sendPacket(player, subTitlePacket);
} catch (Exception e) {
e.printStackTrace();
}
}
private void sendPacket(Player player, Object packet) {
try {
Object handle = player.getClass().getMethod("getHandle").invoke(player);
Object playerConnection = handle.getClass().getField("playerConnection").get(handle);
playerConnection.getClass().getMethod("sendPacket", getNMSClass("Packet")).invoke(playerConnection, packet);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Get NMS class using reflection
*
* @param name Name of the class
* @return Class
*/
private Class<?> getNMSClass(String name) {
String versionName = "net.minecraft.server." + Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3] + "." + name;
if (classCache.containsKey(versionName)) {
return classCache.get(versionName);
}
try {
Class clazz = Class.forName(versionName);
classCache.put(name, clazz);
return clazz;
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
public static TitleAPI getInstance() {
return instance;
}
}

View File

@ -15,6 +15,7 @@ import com.massivecraft.factions.struct.Permission;
import com.massivecraft.factions.struct.Relation;
import com.massivecraft.factions.struct.Role;
import com.massivecraft.factions.util.RelationUtil;
import com.massivecraft.factions.util.TitleAPI;
import com.massivecraft.factions.util.WarmUpUtil;
import com.massivecraft.factions.zcore.fperms.Access;
import com.massivecraft.factions.zcore.fperms.PermissableAction;
@ -607,7 +608,7 @@ public abstract class MemoryFPlayer implements FPlayer {
// We send null instead of empty because Spigot won't touch the title if it's null, but clears if empty.
// We're just trying to be as unintrusive as possible.
player.sendTitle(title, sub, in, stay, out);
TitleAPI.getInstance().sendTitle(player, title, sub, in, stay, out);
showChat = P.p.getConfig().getBoolean("enter-titles.also-show-chat", true);
}