All source projects

MrUltimateLibrary Source

Standalone source project / 68 files

MrUltimateLibrary is the backbone of all my plugins; it offers features that facilitate plugin creation, maintenance, and updates.

java

MrUltimateLibrary/src/main/java/eu/mrneznamy/mrultimatelibrary/MrLibVersionDetector.java

JAVA · Read-only source

package eu.mrneznamy.mrultimatelibrary;

import org.bukkit.Bukkit;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Detects and normalises the Minecraft server version, supporting both:
 * <ul>
 *   <li>Old scheme: {@code 1.X.Y}  (e.g. 1.21.4) — used up to end of 2025</li>
 *   <li>New scheme: {@code YY.Drop.Patch} (e.g. 26.1.2) — introduced in 2026</li>
 * </ul>
 *
 * <p>The Bukkit version string contains {@code (MC: X.Y.Z)}.
 * For the old scheme, {@link #getMajorVersion()} returns the "significant" part
 * (e.g. 21 for 1.21.4). For the new scheme it returns the year component (e.g. 26).
 * {@link #getMinorVersion()} returns the drop equivalent (e.g. 1 for 26.1.2).
 */
public class MrLibVersionDetector {

    /** Matches (MC: X.Y) or (MC: X.Y.Z) in the Bukkit version string. */
    private static final Pattern VERSION_PATTERN =
            Pattern.compile("\\(MC: (\\d+)\\.(\\d+)(?:\\.(\\d+))?\\)");

    private static String  cachedVersion      = null;
    private static int[]   cachedVersionParts = null;   

    
    
    

    public static String getFullVersion() {
        return Bukkit.getVersion();
    }

    /** @return human-readable version string, e.g. {@code "26.1.2"} or {@code "1.21.4"} */
    public static String getVersion() {
        if (cachedVersion != null) return cachedVersion;
        parseVersion();
        if (cachedVersionParts == null) { cachedVersion = "Unknown"; return cachedVersion; }
        int[] p = cachedVersionParts;
        cachedVersion = p[0] + "." + p[1] + (p.length > 2 ? "." + p[2] : "");
        return cachedVersion;
    }

    /**
     * Returns the "significant major" version number:
     * <ul>
     *   <li>Old scheme {@code 1.21.4} → {@code 21}</li>
     *   <li>New scheme {@code 26.1.2} → {@code 26}</li>
     * </ul>
     */
    public static int getMajorVersion() {
        parseVersion();
        if (cachedVersionParts == null) return 0;
        
        
        return isNewVersionScheme() ? cachedVersionParts[0] : cachedVersionParts[1];
    }

    /**
     * Returns the "significant minor" / drop version number:
     * <ul>
     *   <li>Old scheme {@code 1.21.4} → {@code 4} (patch)</li>
     *   <li>New scheme {@code 26.1.2} → {@code 1} (drop)</li>
     * </ul>
     */
    public static int getMinorVersion() {
        parseVersion();
        if (cachedVersionParts == null) return 0;
        if (isNewVersionScheme()) {
            return cachedVersionParts.length > 1 ? cachedVersionParts[1] : 0;  
        }
        return cachedVersionParts.length > 2 ? cachedVersionParts[2] : 0;  
    }

    /** Returns the patch component: 26.1.2 → 2 ,  1.21.4 → 4 */
    public static int getPatchVersion() {
        parseVersion();
        if (cachedVersionParts == null) return 0;
        return cachedVersionParts.length > 2 ? cachedVersionParts[2] : 0;
    }

    /**
     * Returns {@code true} if the server uses the new Minecraft versioning scheme
     * (year-based, introduced in 2026). Detection rule: first component != 1.
     */
    public static boolean isNewVersionScheme() {
        parseVersion();
        return cachedVersionParts != null && cachedVersionParts[0] != 1;
    }

    
    
    

    public static boolean is1_19() { return !isNewVersionScheme() && getMajorVersion() == 19; }
    public static boolean is1_20() { return !isNewVersionScheme() && getMajorVersion() == 20; }
    public static boolean is1_21() { return !isNewVersionScheme() && getMajorVersion() == 21; }
    /** Is server on Minecraft 26.x (Tiny Takeover / 2026 era)? */
    public static boolean is26()   { return  isNewVersionScheme() && getMajorVersion() == 26; }

    
    
    

    /**
     * Is the server at least the given major version?
     * <p>Pass 21 for "1.21+", pass 26 for "26.1+".
     * New-scheme servers are always considered newer than any old-scheme version.
     */
    public static boolean isAtLeast(int major) {
        if (isNewVersionScheme()) {
            
            if (major < 24) return true;   
            return getMajorVersion() >= major;
        }
        return getMajorVersion() >= major;
    }

    /**
     * Is the server at least {@code major.minor}?
     * Old: isAtLeast(21, 4) = 1.21.4+.
     * New: isAtLeast(26, 1) = 26.1+.
     */
    public static boolean isAtLeast(int major, int minor) {
        if (!isAtLeast(major)) return false;
        if (getMajorVersion() > major) return true;
        return getMinorVersion() >= minor;
    }

    /** Is the server at least {@code major.minor.patch}? */
    public static boolean isAtLeast(int major, int minor, int patch) {
        if (!isAtLeast(major, minor)) return false;
        if (getMajorVersion() > major) return true;
        if (getMinorVersion() > minor) return true;
        return getPatchVersion() >= patch;
    }

    public static boolean isInRange(int minMajor, int maxMajor) {
        int v = getMajorVersion();
        return v >= minMajor && v <= maxMajor;
    }

    
    
    

    /**
     * Returns {@code true} if the server version is officially supported by MrUltimateLibrary.
     * <ul>
     *   <li>Old scheme: 1.19.x – 1.21.x</li>
     *   <li>New scheme: 26.1.0+</li>
     * </ul>
     */
    public static boolean isSupported() {
        parseVersion();
        if (cachedVersionParts == null) return false;
        if (isNewVersionScheme()) {
            return isAtLeast(26, 1);
        }
        int major = getMajorVersion();
        if (major < 19 || major > 21) return false;
        if (major == 21 && getMinorVersion() > 9) return false;
        return true;
    }

    
    
    

    /**
     * Encodes the version as a single comparable integer.
     * <pre>
     *  1.21.4  → 1_021_004
     *  26.1.2  → 26_001_002
     * </pre>
     */
    public static int getVersionNumber() {
        parseVersion();
        if (cachedVersionParts == null) return 0;
        int[] p = cachedVersionParts;
        return p[0] * 1_000_000 + p[1] * 1_000 + (p.length > 2 ? p[2] : 0);
    }

    
    
    

    private static void parseVersion() {
        if (cachedVersionParts != null) return;
        String version = Bukkit.getVersion();
        Matcher m = VERSION_PATTERN.matcher(version);
        if (m.find()) {
            int a = Integer.parseInt(m.group(1));
            int b = Integer.parseInt(m.group(2));
            String patchStr = m.group(3);
            cachedVersionParts = (patchStr != null)
                    ? new int[]{a, b, Integer.parseInt(patchStr)}
                    : new int[]{a, b};
        }
    }

    static void clearCache() {
        cachedVersion = null;
        cachedVersionParts = null;
    }
}
210 linesGNU GENERAL PUBLIC LICENSE · Version 3, 29 June 2007 · UTF-8 · Read only