Rewrite to use Shuriken libraries

This commit is contained in:
Mark Vainomaa 2017-03-22 01:09:03 +02:00
parent a5131f534b
commit 230e0ffda7
4 changed files with 104 additions and 103 deletions

View File

@ -10,24 +10,25 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<artifactId>bukkitutils</artifactId> <artifactId>bukkitutils</artifactId>
<version>1.7-SNAPSHOT</version> <version>1.8-SNAPSHOT</version>
<repositories> <repositories>
<repository> <repository>
<id>destroystokyo-repo</id> <id>destroystokyo-repo</id>
<url>https://repo.destroystokyo.com/repository/maven-public//</url> <url>https://repo.destroystokyo.com/repository/maven-public//</url>
</repository> </repository>
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
</repositories> </repositories>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>eu.mikroskeem</groupId> <groupId>eu.mikroskeem</groupId>
<artifactId>reflect</artifactId> <artifactId>shuriken.reflect</artifactId>
<version>1.1-SNAPSHOT</version> <version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>eu.mikroskeem</groupId>
<artifactId>shuriken.instrumentation</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.destroystokyo.paper</groupId> <groupId>com.destroystokyo.paper</groupId>
@ -35,22 +36,11 @@
<version>1.11.2-R0.1-SNAPSHOT</version> <version>1.11.2-R0.1-SNAPSHOT</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
<version>1.11.2-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
<version>1.16.10</version> <version>1.16.12</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations-java5</artifactId>
<version>RELEASE</version>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -1,11 +1,11 @@
package eu.mikroskeem.utils.bukkit; package eu.mikroskeem.utils.bukkit;
import eu.mikroskeem.utils.reflect.Reflect; import eu.mikroskeem.shuriken.reflect.Reflect;
import eu.mikroskeem.shuriken.reflect.wrappers.ClassWrapper;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static eu.mikroskeem.utils.bukkit.ServerUtils.getNmsVersion; import static eu.mikroskeem.utils.bukkit.ServerUtils.getNmsVersion;
@ -19,20 +19,22 @@ public class PlayerUtils {
* @param player Player who ping to query * @param player Player who ping to query
* @return Player's ping (-1 if reflection failed) * @return Player's ping (-1 if reflection failed)
*/ */
public static int getNMSPing(@NotNull Player player){ @SuppressWarnings("unchecked")
public static <CraftPlayer, NMSPlayer> int getNMSPing(@NotNull Player player){
try { try {
String nmsVer = getNmsVersion(); String nmsVer = getNmsVersion();
Class<?> craftPlayerClass = checkNotNull(Reflect.getClass( ClassWrapper<CraftPlayer> craftPlayerClass = (ClassWrapper<CraftPlayer>) checkNotNull(Reflect.getClass(
String.format("org.bukkit.craftbukkit.%s.entity.CraftPlayer", nmsVer))); String.format("org.bukkit.craftbukkit.%s.entity.CraftPlayer", nmsVer)).orElse(null))
Class<?> craftEntityPlayerClass = checkNotNull(Reflect.getClass( .setClassInstance(player);
String.format("net.minecraft.server.%s.EntityPlayer", nmsVer))); ClassWrapper<NMSPlayer> nmsEntityPlayerClass = (ClassWrapper<NMSPlayer>) checkNotNull(Reflect.getClass(
Method getHandle = checkNotNull(Reflect.getMethod(craftPlayerClass, "getHandle")); String.format("net.minecraft.server.%s.EntityPlayer", nmsVer)).orElse(null));
Object handle = checkNotNull(Reflect.invokeMethod(getHandle, player)); NMSPlayer nmsPlayer = craftPlayerClass
Field pingField = checkNotNull(Reflect.getField(craftEntityPlayerClass, "ping")); .invokeMethod("getHandle", nmsEntityPlayerClass.getWrappedClass());
return (Integer) checkNotNull(Reflect.readField(pingField, handle)); nmsEntityPlayerClass.setClassInstance(nmsPlayer);
} return checkNotNull(nmsEntityPlayerClass.getField("ping", int.class).orElse(null)).read();
catch (NullPointerException ignored){
return -1;
} }
catch (NullPointerException|NoSuchFieldException|NoSuchMethodException|
IllegalAccessException|InvocationTargetException ignored){}
return -1;
} }
} }

View File

@ -1,13 +1,17 @@
package eu.mikroskeem.utils.bukkit; package eu.mikroskeem.utils.bukkit;
import eu.mikroskeem.utils.reflect.Reflect; import eu.mikroskeem.shuriken.instrumentation.validate.ClassDescriptor;
import eu.mikroskeem.shuriken.instrumentation.validate.FieldDescriptor;
import eu.mikroskeem.shuriken.instrumentation.validate.Validate;
import eu.mikroskeem.shuriken.reflect.Reflect;
import eu.mikroskeem.shuriken.reflect.wrappers.ClassWrapper;
import eu.mikroskeem.shuriken.reflect.wrappers.FieldWrapper;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.plugin.java.JavaPluginLoader; import org.bukkit.plugin.java.JavaPluginLoader;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
@ -21,18 +25,25 @@ public class ServerUtils {
* Will use PaperSpigot's API if available, reflection otherwise * Will use PaperSpigot's API if available, reflection otherwise
* @return double array of TPS (not rounded!), values are -1 if reflection failed * @return double array of TPS (not rounded!), values are -1 if reflection failed
*/ */
public static double[] getTPS(){ @SuppressWarnings("unchecked")
if(Reflect.getMethod(Bukkit.class, "getTps") != null) { public static <C> double[] getTPS(){
return Bukkit.getTPS(); Class<C> _t = (Class<C>)double[].class;
} else { try {
return Reflect.wrapClass(Bukkit.class).invokeMethod("getTPS", double[].class);
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
try { try {
Class<?> MinecraftServerClass = checkNotNull(Reflect.getClass( Optional<ClassWrapper<?>> minecraftServerClassOpt = Reflect.getClass(String.format(
String.format("net.minecraft.server.%s.MinecraftServer", getNmsVersion()))); "net.minecraft.server.%s.MinecraftServer", getNmsVersion()
Method getServer = checkNotNull(Reflect.getMethod(MinecraftServerClass, "getServer")); ));
Field recentTPS = checkNotNull(Reflect.getField(MinecraftServerClass, "recentTps")); if (minecraftServerClassOpt.isPresent()) {
Object server = checkNotNull(Reflect.invokeMethod(getServer, null)); ClassWrapper<?> minecraftServerClass = minecraftServerClassOpt.get();
return (double[]) checkNotNull(Reflect.readField(recentTPS, server)); minecraftServerClass.invokeMethod("getServer", minecraftServerClass.getWrappedClass());
} catch (NullPointerException ignored){} Optional<FieldWrapper<C>> recentTpsOpt = minecraftServerClass.getField("recentTps", _t);
if(recentTpsOpt.isPresent())
return (double[]) recentTpsOpt.get().read();
}
}
catch (NoSuchMethodException|NoSuchFieldException|InvocationTargetException|IllegalAccessException ignored){}
} }
return new double[]{-1, -1, -1}; return new double[]{-1, -1, -1};
} }
@ -54,34 +65,42 @@ public class ServerUtils {
*/ */
JavaPluginLoader pl = (JavaPluginLoader) plugin.getPluginLoader(); JavaPluginLoader pl = (JavaPluginLoader) plugin.getPluginLoader();
try { try {
Field loadersField = checkNotNull(Reflect.getField(pl.getClass(), "loaders")); Optional<FieldWrapper<Object>> loadersFieldOpt = Reflect
switch (getNmsVersion()){ .wrapClass(pl.getClass())
case "v1_8_R3": .setClassInstance(pl)
case "v1_9_R1": .getField("loaders", Object.class);
case "v1_9_R2": if(loadersFieldOpt.isPresent()) {
try { FieldWrapper<Object> loadersField = loadersFieldOpt.get();
Map<String, ClassLoader> loaderMap = (Map<String, ClassLoader>) switch (ServerUtils.getNmsVersion()){
checkNotNull(Reflect.readField(loadersField, pl)); case "v1_8_R3":
case "v1_9_R1":
case "v1_9_R2":
Map<String, ClassLoader> loaderMap = (Map<String, ClassLoader>) loadersField.read();
return loaderMap.get(plugin.getName()); return loaderMap.get(plugin.getName());
} case "v1_10_R1":
catch (NullPointerException ignored){} case "v1_11_R1":
break; Optional<ClassWrapper<?>> pluginClassLoaderOpt = Reflect
case "v1_10_R1": .getClass("org.bukkit.plugin.java.PluginClassLoader");
case "v1_11_R1": if(pluginClassLoaderOpt.isPresent()){
Class<?> pluginClassLoader = checkNotNull(Reflect.getClass( List<ClassLoader> loaders = (List<ClassLoader>) loadersField.read();
"org.bukkit.plugin.java.PluginClassLoader")); return loaders.stream().filter(loader -> {
List<ClassLoader> loaders = (List<ClassLoader>) try {
checkNotNull(Reflect.readField(loadersField, pl)); String pluginName = Reflect.wrapInstance(loader)
Optional<ClassLoader> loader = loaders.stream() .getField("plugin", JavaPlugin.class)
.filter(l->{ .get()
Field f = checkNotNull(Reflect.getField(pluginClassLoader, "plugin")); .read()
return checkNotNull(((JavaPlugin)Reflect.readField(f, l))) .getName();
.getName().equals(plugin.getName()); return pluginName.equals(plugin.getName());
}).findFirst(); }
return loader.isPresent()?loader.get():null; catch (NoSuchFieldException|IllegalAccessException|NullPointerException ignored){}
return false;
}).findFirst().orElse(null);
}
break;
}
} }
} }
catch (NullPointerException ignored){} catch (NoSuchFieldException|IllegalAccessException ignored){}
return null; return null;
} }
@ -89,27 +108,22 @@ public class ServerUtils {
* Get PluginClassLoader classes map * Get PluginClassLoader classes map
* @param classLoader PluginClassLoader instance * @param classLoader PluginClassLoader instance
* @return Classes map * @return Classes map
* @throws RuntimeException if ClassLoader doesn't extend PluginClassLoader
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Nullable @Nullable
public static Map<String, Class<?>> getClassesMap(ClassLoader classLoader){ public static Map<String, Class<?>> getClassesMap(ClassLoader classLoader){
Class<?> clClass = classLoader.getClass(); Class<?> clClass = classLoader.getClass();
try { try {
Class<?> pluginClassLoader = checkNotNull(Reflect.getClass( ClassWrapper<?> pluginClassLoader = checkNotNull(Reflect
"org.bukkit.plugin.java.PluginClassLoader"), .getClass("org.bukkit.plugin.java.PluginClassLoader").orElse(null),
"Couldn't find org.bukkit.plugin.java.PluginClassLoader class"); "Couldn't find org.bukkit.plugin.java.PluginClassLoader class")
if(pluginClassLoader.isAssignableFrom(clClass)){ .setClassInstance(classLoader);
Field classesField = checkNotNull(Reflect.getField(clClass, "classes"), Validate.checkFields(pluginClassLoader, FieldDescriptor.of("classes", Map.class));
"Failed to get classes field"); Validate.checkClass(ClassDescriptor.ofWrapped(clClass, pluginClassLoader));
return (Map<String, Class<?>>) checkNotNull(Reflect.readField(classesField, classLoader)); return (Map<String, Class<?>>) checkNotNull(pluginClassLoader.getField("classes", Map.class)
} else { .orElse(null),
throw new RuntimeException( "Failed to get classes field").read();
clClass.getName() } catch(NoSuchFieldException|IllegalAccessException|NullPointerException e){
+ " does not extend "
+ pluginClassLoader.getName());
}
} catch(NullPointerException e){
e.printStackTrace(); e.printStackTrace();
} }
return null; return null;

View File

@ -1,12 +1,13 @@
package eu.mikroskeem.utils.bukkit.fakeplugin; package eu.mikroskeem.utils.bukkit.fakeplugin;
import eu.mikroskeem.utils.reflect.Reflect; import eu.mikroskeem.shuriken.reflect.Reflect;
import eu.mikroskeem.shuriken.reflect.simple.SimpleReflect;
import eu.mikroskeem.shuriken.reflect.wrappers.ClassWrapper;
import lombok.Getter; import lombok.Getter;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.SimplePluginManager; import org.bukkit.plugin.SimplePluginManager;
import java.lang.reflect.Field;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
@ -25,23 +26,17 @@ public class FakePluginFactory {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public FakePluginFactory(Plugin parentPlugin){ public FakePluginFactory(Plugin parentPlugin){
this.plugin = parentPlugin; this.plugin = parentPlugin;
Field lookupNamesField, pluginsField;
if(plugin.getServer().getPluginManager().getClass() != SimplePluginManager.class){ if(plugin.getServer().getPluginManager().getClass() != SimplePluginManager.class){
throw new RuntimeException("Server PluginManager is not SimplePluginManager"); throw new RuntimeException("Server PluginManager is not SimplePluginManager");
} }
isPaper = Reflect.getMethod(Bukkit.class, "getTPS") != null; isPaper = SimpleReflect.getMethod(Bukkit.class, "getTPS", double[].class) != null;
try { try {
pluginsField = checkNotNull(Reflect.getField( ClassWrapper<SimplePluginManager> spm = Reflect.wrapClass(SimplePluginManager.class)
SimplePluginManager.class, .setClassInstance(plugin.getServer().getPluginManager());
"plugins")); plugins = (List<Plugin>) checkNotNull(spm.getField("plugins", List.class).orElse(null)).read();
lookupNamesField = checkNotNull(Reflect.getField( lookupNames = (Map<String, Plugin>) checkNotNull(spm.getField("lookupNames", Map.class).orElse(null)).read();
SimplePluginManager.class, } catch (Exception e){
"lookupNames")); e.printStackTrace();
plugins = (List<Plugin>) checkNotNull(Reflect.readField(pluginsField,
plugin.getServer().getPluginManager()));
lookupNames = (Map<String, Plugin>) checkNotNull(Reflect.readField(lookupNamesField,
plugin.getServer().getPluginManager()));
} catch (NullPointerException e){
throw new RuntimeException("Failed to get 'plugins' and 'lookupNames' field!"); throw new RuntimeException("Failed to get 'plugins' and 'lookupNames' field!");
} }
} }