Class XReflection

java.lang.Object
com.cryptomorin.xseries.reflection.XReflection

public final class XReflection extends Object
General Java reflection handler, but specialized for Minecraft NMS/CraftBukkit reflection as well.

Starting Points

Basic reflection starting points are through the ClassHandle methods:
  • of(Class): For static classes with known type at compile time.
  • classHandle(): For general classes that have unknown type at compile time.
  • ofMinecraft(): Specialized for Minecraft-related classes.
  • namespaced(): String-based API for getting classes with Java code inside strings that is more readable.

Fallback

Some methods exist to choose between different values depending on the situation:

Others

Also, there are a few other non-reflection APIs in this class that are a bit "hacky" which is why they're here.
Version:
11.2.1
Author:
Crypto Morin
See Also:
  • Field Details

    • NMS_VERSION

      @Nullable @Internal public static final String NMS_VERSION
      We use reflection mainly to avoid writing a new class for version barrier. The version barrier is for NMS that uses the Minecraft version as the main package name.

      E.g. EntityPlayer in 1.15 is in the class net.minecraft.server.v1_15_R1 but in 1.14 it's in net.minecraft.server.v1_14_R1 In order to maintain cross-version compatibility we cannot import these classes.

      Performance is not a concern for these specific statically initialized values.

      Versions Legacy

      This will no longer work because of Paper no-relocation strategy.

    • XSERIES_VERSION

      @Internal public static final String XSERIES_VERSION
      The current version of XSeries. Mostly used for the XSkull API.
      See Also:
    • MAJOR_NUMBER

      public static final int MAJOR_NUMBER
    • MINOR_NUMBER

      public static final int MINOR_NUMBER
      The raw minor version number. E.g. v1_17_R1 to 17
      Since:
      4.0.0
      See Also:
    • PATCH_NUMBER

      public static final int PATCH_NUMBER
      The raw patch version number. Refers to the major.minor.patch version scheme. E.g.
      • v1.20.4 to 4
      • v1.18.2 to 2
      • v1.19.1 to 1

      I'd not recommend developers to support individual patches at all. You should always support the latest patch. For example, between v1.14.0, v1.14.1, v1.14.2, v1.14.3 and v1.14.4 you should only support v1.14.4

      This can be used to warn server owners when your plugin will break on older patches.

      Since:
      7.0.0
      See Also:
    • CRAFTBUKKIT_PACKAGE

      @Internal public static final String CRAFTBUKKIT_PACKAGE
      Mojang remapped their NMS in 1.17: Spigot Thread
    • NMS_PACKAGE

      @Internal public static final String NMS_PACKAGE
      Mojang remapped their NMS in 1.17: Spigot Thread
    • SUPPORTED_MAPPINGS

      @Internal @Experimental public static final Set<MinecraftMapping> SUPPORTED_MAPPINGS
  • Method Details

    • findNMSVersionString

      @Nullable @Internal public static String findNMSVersionString()
    • getVersionInformation

      public static String getVersionInformation()
      Gets the full version information of the server. Useful for including in errors. "NMS" might return "Unknown NMS", which means that they're running a Paper server that removed the CraftBukkit NMS version guard.
      Since:
      7.0.0
    • getLatestPatchNumberOf

      @Nullable public static Integer getLatestPatchNumberOf(int minorVersion)
      Gets the latest known patch number of the given minor version. For example: 1.14 -> 4, 1.17 -> 10 The latest version is expected to get newer patches, so make sure to account for unexpected results.
      Parameters:
      minorVersion - the minor version to get the patch number of.
      Returns:
      the patch number of the given minor version if recognized, otherwise null.
      Since:
      7.0.0
    • v

      public static <T> VersionHandle<T> v(int version, T handle)
      Gives the handle object if the server version is equal or greater than the given version. This method is purely for readability and should be always used with VersionHandle.orElse(Object).
      Since:
      5.0.0
      See Also:
    • v

      public static <T> VersionHandle<T> v(int version, int patch, T handle)
      Since:
      9.5.0
    • v

      public static <T> VersionHandle<T> v(int version, Callable<T> handle)
    • v

      public static <T> VersionHandle<T> v(int version, int patch, Callable<T> handle)
    • supports

      public static boolean supports(int minorNumber)
      Checks whether the server version is equal or greater than the given version.
      Parameters:
      minorNumber - the version to compare the server version with.
      Returns:
      true if the version is equal or newer, otherwise false.
      Since:
      4.0.0
      See Also:
    • supports

      public static boolean supports(int majorNumber, int minorNumber, int patchNumber)
      A more friendly version of supports(int, int) for people with OCD.
    • supports

      public static boolean supports(int minorNumber, int patchNumber)
      Checks whether the server version is equal or greater than the given version.
      Parameters:
      minorNumber - the minor version to compare the server version with.
      patchNumber - the patch number to compare the server version with.
      Returns:
      true if the version is equal or newer, otherwise false.
      Since:
      7.1.0
      See Also:
    • supportsPatch

      @Deprecated public static boolean supportsPatch(int patchNumber)
      Deprecated.
      Checks whether the server version is equal or greater than the given version.
      Parameters:
      patchNumber - the version to compare the server version with.
      Returns:
      true if the version is equal or newer, otherwise false.
      Since:
      7.0.0
      See Also:
    • getNMSClass

      @Nonnull @Deprecated public static Class<?> getNMSClass(@Nullable String packageName, @Nonnull String name)
      Deprecated.
      use ofMinecraft() instead.
      Get a NMS (net.minecraft.server) class which accepts a package for 1.17 compatibility.
      Parameters:
      packageName - the 1.17+ package name of this class.
      name - the name of the class.
      Returns:
      the NMS class or null if not found.
      Throws:
      RuntimeException - if the class could not be found.
      Since:
      4.0.0
      See Also:
    • getNMSClass

      @Nonnull @Deprecated public static Class<?> getNMSClass(@Nonnull String name)
      Deprecated.
      Get a NMS NMS_PACKAGE class.
      Parameters:
      name - the name of the class.
      Returns:
      the NMS class or null if not found.
      Throws:
      RuntimeException - if the class could not be found.
      Since:
      1.0.0
      See Also:
    • getCraftClass

      @Nonnull @Deprecated public static Class<?> getCraftClass(@Nonnull String name)
      Deprecated.
      use ofMinecraft() instead.
      Get a CraftBukkit (org.bukkit.craftbukkit) class.
      Parameters:
      name - the name of the class to load.
      Returns:
      the CraftBukkit class or null if not found.
      Throws:
      RuntimeException - if the class could not be found.
      Since:
      1.0.0
    • toArrayClass

      @Nonnull public static Class<?> toArrayClass(Class<?> clazz)
      Gives an array version of a class. For example if you wanted EntityPlayer[] you'd use:
      
           Class EntityPlayer = ReflectionUtils.getNMSClass("...", "EntityPlayer");
           Class EntityPlayerArray = ReflectionUtils.toArrayClass(EntityPlayer);
       

      Note that this doesn't work on primitive classes.

      Parameters:
      clazz - the class to get the array version of. You could use for multi-dimensions arrays too.
      Throws:
      RuntimeException - if the class could not be found.
    • ofMinecraft

      public static MinecraftClassHandle ofMinecraft()
      Since:
      v9.0.0
    • classHandle

      public static DynamicClassHandle classHandle()
      Since:
      v9.0.0
    • of

      public static StaticClassHandle of(Class<?> clazz)
      Since:
      v11.0.0
    • namespaced

      public static ReflectiveNamespace namespaced()
      Read ReflectiveNamespace for more info.
      Since:
      v11.0.0
    • any

      @SafeVarargs public static <T, H extends ReflectiveHandle<T>> AggregateReflectiveHandle<T,H> any(H... handles)
      Since:
      v9.0.0
    • anyOf

      @SafeVarargs public static <T, H extends ReflectiveHandle<T>> AggregateReflectiveHandle<T,H> anyOf(Callable<H>... handles)
      Since:
      v9.0.0
    • relativizeSuppressedExceptions

      @Experimental public static <T extends Throwable> T relativizeSuppressedExceptions(T ex)
      Relativize the stacktrace of exceptions that are thrown from the same location. The suppressed exception's (Throwable.getSuppressed()) stacktrace are relativized against the given exceptions stacktrace.

      This is mostly useful when you have a trial-and-error mechanism that accumulates all the errors to throw them in case all the attempts have failed. This removes unnecessary line information to help the developer focus on important, non-repeated lines.

      Type Parameters:
      T - the type of the exception.
      Parameters:
      ex - the exception to have it's suppressed exceptions relativized.
      Returns:
      the same exception.
    • throwCheckedException

      public static RuntimeException throwCheckedException(Throwable exception)
      Throws a checked exception (see Exception) silently without forcing the programmer to handle it. This is usually considered a very bad practice, as those errors are meant to be handled, so please use sparingly. You should just create a RuntimeException instead and putting the checked exception as a cause if necessary.

      Usage

      
           void doStuff() throws IOException {}
      
           void rethrowAsRuntime() {
               try {
                   doStuff();
               } catch (IOException ex) {
                   throw new RuntimeException(ex);
               }
           }
      
           void ignoreTheLawsOfJavaQuantumMechanics() {
               try {
                   doStuff();
               } catch (IOException ex) {
                   throw XReflection.throwCheckedException(ex);
               }
           }
       
      Returns:
      null, but it's intended to be thrown, this is a hacky trick to stop the IDE from complaining about non-terminating statements.
    • stacktrace

      @Experimental public static <T> CompletableFuture<T> stacktrace(@Nonnull CompletableFuture<T> completableFuture)
      Adds the stacktrace of the current thread in case an error occurs in the given Future.
    • concatenate

      @Internal public static <T> T[] concatenate(T[] a, T[] b)