Resource Get Minecraft version(like x.x.x format) with reflect and cross-version (not switch or stupid thing)

Discussion in 'Spigot Plugin Development' started by Ghost_chu, Jan 10, 2020.

  1. Usually plugin internal using "v1_15_R1" NMS version, it not always update when Minecraft version changes.
    So i and my friend @SotrForgotten create this util to get minecraft server without NMS importing.
    Code (Text):
    public static String getServerVersion(){
            try {
                Field consoleField = Bukkit.getServer().getClass().getDeclaredField("console");
                consoleField.setAccessible(true); // protected
                Object console = consoleField.get(Bukkit.getServer()); // dedicated server
                return String.valueOf(console.getClass().getSuperclass().getMethod("getVersion").invoke(console));
            }catch (Exception e){
                e.printStackTrace();
                return "Unknown";
            }
        }
    Return: E.g 1.15.1, 1.7.10, 1.8.8

    Somebody ask me why not use replace package name, because you can't get expected result on all versions.

    In MC1.14, 1.14 1.14.1 1.14.2 1.14.3 1.14.4 they all use v1_14_R1
     
    #1 Ghost_chu, Jan 10, 2020
    Last edited: Jan 10, 2020
    • Like Like x 2
    • Funny Funny x 1
  2. You could simplify all that with 2 easy methods:

    With this method (will return the NMS package version like v1_15_R1):
    Code (Java):
    Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3];
    Or if you are just looking to get the version (like 1.15.1) you can do:
    Code (Java):
    Bukkit.getBukkitVersion().split("-")[0];
     
    #2 ShaneBee, Jan 10, 2020
    Last edited: Jan 10, 2020
    • Agree Agree x 1
  3. You can't, on 1.7.10, you won't get expected result, like in aricle `it not always update when Minecraft version changes`.
    In minecraft 1.14, 1.14 1.14.1 1.14.2 1.14.3 and 1.14.4 they all use v1_14_R1
     
  4. that's why I posted the second method (when I posted the first one I misread your post):
    Code (Java):
    Bukkit.getBukkitVersion().split("-")[0];
    this will return 1.7.10, 1.8.8, 1.15.1, etc
     
    • Like Like x 1
  5. I think my way will super stable, it won't change if you using a custom bukkit build.
    Pretty sure it won't break if some devs hard modify the bukkit...
     
  6. When using reflection, please cache.

    Code (Java):
    private static final Object CONSOLE;
    private static final Method GET_VERSION;

    static {
        try {
            final Server server = Bukkit.getServer();
            final Field consoleField = server.getClass().getDeclaredField("console");
            consoleField.setAccessible(true);
            CONSOLE = consoleField.get(server);
            GET_VERSION = CONSOLE.getClass().getSuperclass().getMethod("getVersion");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static String getServerVersion() throws Exception {
        return GET_VERSION.invoke(CONSOLE);
    }
    but shane's solution is the best regardless, this is just a tip regarding general reflection usage.
     
    • Like Like x 1
    • Agree Agree x 1
  7. How is yours more stable compared to Shane’s approach? IMO Shane’s approach is better (faster and more secure) because yours relies on a protected/private field. The devs restricted external access to it on purpose and the field (internal implementation) is bound to change in new versions.

    Shane’s method uses the getVersion() method, an API-documented method which is designed in a forward-compatible manner and is likely to be left untouched in future versions.
     
    #7 NascentNova, Jan 10, 2020
    Last edited: Jan 10, 2020
    • Agree Agree x 2
  8. It's Shane :p
     
    • Funny Funny x 1
  9. Mb sorry :eek: I scrolled too fast
     
    • Friendly Friendly x 1