aboutsummaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorKrakenied <krakenied1@gmail.com>2026-01-19 11:24:06 +0100
committerKrakenied <krakenied1@gmail.com>2026-01-19 22:38:20 +0100
commit574ffa99bd822c983c2ae6e805197cae7c4bd601 (patch)
tree307e711b3f03db69ca57a1e995666db12b49549c /common
parent6f8d1d3bd8cefe7ec75bd568b5c5a7586ff1db08 (diff)
Prepare for Mojang version mess
New API to be used in server version detection and version specific handlers
Diffstat (limited to 'common')
-rw-r--r--common/build.gradle.kts14
-rw-r--r--common/src/main/java/com/leonardobishop/quests/common/versioning/Version.java184
-rw-r--r--common/src/test/java/com/leonardobishop/quests/common/VersionTest.java142
3 files changed, 340 insertions, 0 deletions
diff --git a/common/build.gradle.kts b/common/build.gradle.kts
index d8e3b2cd..259ecad6 100644
--- a/common/build.gradle.kts
+++ b/common/build.gradle.kts
@@ -12,4 +12,18 @@ dependencies {
// Use it for contracts and unmodifiability annotations
api("org.jetbrains:annotations:26.0.2")
+
+ // Testing dependencies
+ testImplementation("org.junit.jupiter:junit-jupiter:6.0.2")
+ testRuntimeOnly("org.junit.platform:junit-platform-launcher")
+}
+
+tasks.named<Test>("test") {
+ useJUnitPlatform()
+
+ maxHeapSize = "1G"
+
+ testLogging {
+ events("passed")
+ }
}
diff --git a/common/src/main/java/com/leonardobishop/quests/common/versioning/Version.java b/common/src/main/java/com/leonardobishop/quests/common/versioning/Version.java
new file mode 100644
index 00000000..0c316268
--- /dev/null
+++ b/common/src/main/java/com/leonardobishop/quests/common/versioning/Version.java
@@ -0,0 +1,184 @@
+package com.leonardobishop.quests.common.versioning;
+
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+import java.util.Arrays;
+import java.util.Objects;
+
+@NullMarked
+public final class Version implements Comparable<Version> {
+
+ public static final Version V1_8 = new Version(1, 8);
+ public static final Version V1_9 = new Version(1, 9);
+ public static final Version V1_11 = new Version(1, 11);
+ public static final Version V1_11_2 = new Version(1, 11, 2);
+ public static final Version V1_14 = new Version(1, 14);
+ public static final Version V1_15_2 = new Version(1, 15, 2);
+ public static final Version V1_16 = new Version(1, 16);
+ public static final Version V1_17 = new Version(1, 17);
+ public static final Version V1_19_2 = new Version(1, 19, 2);
+ public static final Version V1_20 = new Version(1, 20);
+ public static final Version V1_20_4 = new Version(1, 20, 4);
+ public static final Version V1_21_6 = new Version(1, 21, 6);
+ public static final Version V1_21_11 = new Version(1, 21, 11);
+ public static final Version UNKNOWN = new Version(Integer.MAX_VALUE);
+
+ private final @Nullable String preRelease;
+ private final @Nullable String buildMetaData;
+ private final int[] versionParts;
+
+ private Version(final @Nullable String preRelease, final @Nullable String buildMetaData, final int... versionParts) {
+ this.preRelease = preRelease;
+ this.buildMetaData = buildMetaData;
+ this.versionParts = versionParts;
+ }
+
+ private Version(final int... versionParts) {
+ this(null, null, versionParts);
+ }
+
+ public boolean isHigherThan(final Version other) {
+ return this.compareTo(other) > 0;
+ }
+
+ public boolean isHigherOrEqualTo(final Version other) {
+ return this.compareTo(other) >= 0;
+ }
+
+ public boolean isEqualTo(final Version other) {
+ return this.compareTo(other) == 0;
+ }
+
+ public boolean isLowerOrEqualTo(final Version other) {
+ return this.compareTo(other) <= 0;
+ }
+
+ public boolean isLowerThan(final Version other) {
+ return this.compareTo(other) < 0;
+ }
+
+ @SuppressWarnings("PointlessArithmeticExpression")
+ @Override
+ public int compareTo(final Version other) {
+ final int commonLength = Math.min(this.versionParts.length, other.versionParts.length);
+
+ for (int i = 0; i < commonLength; i++) {
+ final int diff = this.versionParts[i] - other.versionParts[i];
+
+ if (diff != 0) {
+ return diff;
+ }
+ }
+
+ for (int i = commonLength; i < this.versionParts.length; i++) {
+ final int diff = this.versionParts[i] - 0;
+
+ if (diff != 0) {
+ return diff;
+ }
+ }
+
+ for (int i = commonLength; i < other.versionParts.length; i++) {
+ final int diff = 0 - other.versionParts[i];
+
+ if (diff != 0) {
+ return diff;
+ }
+ }
+
+ return 0;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(this.preRelease, this.buildMetaData, Arrays.hashCode(this.versionParts));
+ }
+
+ @Override
+ public boolean equals(final Object other) {
+ if (other == null || this.getClass() != other.getClass()) {
+ return false;
+ }
+
+ final Version otherVersion = (Version) other;
+
+ return Objects.equals(this.preRelease, otherVersion.preRelease)
+ && Objects.equals(this.buildMetaData, otherVersion.buildMetaData)
+ && Objects.deepEquals(this.versionParts, otherVersion.versionParts);
+ }
+
+ public String toClassNameString() {
+ final StringBuilder builder = new StringBuilder();
+
+ builder.append('V');
+
+ for (int i = 0; i < this.versionParts.length; i++) {
+ builder.append(this.versionParts[i]);
+
+ if (i != this.versionParts.length - 1) {
+ builder.append('_');
+ }
+ }
+
+ return builder.toString();
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+
+ for (int i = 0; i < this.versionParts.length; i++) {
+ builder.append(this.versionParts[i]);
+
+ if (i != this.versionParts.length - 1) {
+ builder.append('.');
+ }
+ }
+
+ if (this.preRelease != null) {
+ builder.append('-');
+ builder.append(this.preRelease);
+ }
+
+ if (this.buildMetaData != null) {
+ builder.append('+');
+ builder.append(this.buildMetaData);
+ }
+
+ return builder.toString();
+ }
+
+ public static Version fromString(final String str) throws IllegalArgumentException {
+ final int minusIndex = str.indexOf('-');
+ final int plusIndex = str.indexOf('+', minusIndex + 1);
+
+ final String preRelease = minusIndex != -1
+ ? str.substring(minusIndex + 1, plusIndex != -1 ? plusIndex : str.length())
+ : null;
+
+ final String buildMetaData = plusIndex != -1
+ ? str.substring(plusIndex + 1)
+ : null;
+
+ final int optionalIndex = minusIndex != -1 ? minusIndex : plusIndex;
+ final String versionCore = optionalIndex != -1 ? str.substring(0, optionalIndex) : str;
+ final String[] stringVersionParts = versionCore.split("\\.");
+ final int[] versionParts = new int[stringVersionParts.length];
+
+ for (int i = 0; i < stringVersionParts.length; i++) {
+ final String stringVersionPart = stringVersionParts[i];
+ final int versionPart;
+
+ try {
+ versionPart = Integer.parseUnsignedInt(stringVersionPart);
+ } catch (final NumberFormatException e) {
+ throw new IllegalArgumentException("Unparsable version part: '" + stringVersionPart + "'");
+ }
+
+ versionParts[i] = versionPart;
+ }
+
+ return new Version(preRelease, buildMetaData, versionParts);
+ }
+}
diff --git a/common/src/test/java/com/leonardobishop/quests/common/VersionTest.java b/common/src/test/java/com/leonardobishop/quests/common/VersionTest.java
new file mode 100644
index 00000000..ceb97f86
--- /dev/null
+++ b/common/src/test/java/com/leonardobishop/quests/common/VersionTest.java
@@ -0,0 +1,142 @@
+package com.leonardobishop.quests.common;
+
+import com.leonardobishop.quests.common.versioning.Version;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public final class VersionTest {
+
+ @Test
+ public void oldVersioning() {
+ assertEquals("1.8-R0.1-SNAPSHOT", Version.fromString("1.8-R0.1-SNAPSHOT").toString());
+ assertEquals("1.8.3-R0.1-SNAPSHOT", Version.fromString("1.8.3-R0.1-SNAPSHOT").toString());
+ assertEquals("1.8.4-R0.1-SNAPSHOT", Version.fromString("1.8.4-R0.1-SNAPSHOT").toString());
+ assertEquals("1.8.5-R0.1-SNAPSHOT", Version.fromString("1.8.5-R0.1-SNAPSHOT").toString());
+ assertEquals("1.8.6-R0.1-SNAPSHOT", Version.fromString("1.8.6-R0.1-SNAPSHOT").toString());
+ assertEquals("1.8.7-R0.1-SNAPSHOT", Version.fromString("1.8.7-R0.1-SNAPSHOT").toString());
+ assertEquals("1.8.8-R0.1-SNAPSHOT", Version.fromString("1.8.8-R0.1-SNAPSHOT").toString());
+ assertEquals("1.9-R0.1-SNAPSHOT", Version.fromString("1.9-R0.1-SNAPSHOT").toString());
+ assertEquals("1.9.2-R0.1-SNAPSHOT", Version.fromString("1.9.2-R0.1-SNAPSHOT").toString());
+ assertEquals("1.9.4-R0.1-SNAPSHOT", Version.fromString("1.9.4-R0.1-SNAPSHOT").toString());
+ assertEquals("1.10-R0.1-SNAPSHOT", Version.fromString("1.10-R0.1-SNAPSHOT").toString());
+ assertEquals("1.10.2-R0.1-SNAPSHOT", Version.fromString("1.10.2-R0.1-SNAPSHOT").toString());
+ assertEquals("1.11-R0.1-SNAPSHOT", Version.fromString("1.11-R0.1-SNAPSHOT").toString());
+ assertEquals("1.11.1-R0.1-SNAPSHOT", Version.fromString("1.11.1-R0.1-SNAPSHOT").toString());
+ assertEquals("1.11.2-R0.1-SNAPSHOT", Version.fromString("1.11.2-R0.1-SNAPSHOT").toString());
+ assertEquals("1.12-pre2-SNAPSHOT", Version.fromString("1.12-pre2-SNAPSHOT").toString());
+ assertEquals("1.12-pre5-SNAPSHOT", Version.fromString("1.12-pre5-SNAPSHOT").toString());
+ assertEquals("1.12-pre6-SNAPSHOT", Version.fromString("1.12-pre6-SNAPSHOT").toString());
+ assertEquals("1.12-R0.1-SNAPSHOT", Version.fromString("1.12-R0.1-SNAPSHOT").toString());
+ assertEquals("1.12.1-R0.1-SNAPSHOT", Version.fromString("1.12.1-R0.1-SNAPSHOT").toString());
+ assertEquals("1.12.2-R0.1-SNAPSHOT", Version.fromString("1.12.2-R0.1-SNAPSHOT").toString());
+ assertEquals("1.13-pre7-R0.1-SNAPSHOT", Version.fromString("1.13-pre7-R0.1-SNAPSHOT").toString());
+ assertEquals("1.13-R0.1-SNAPSHOT", Version.fromString("1.13-R0.1-SNAPSHOT").toString());
+ assertEquals("1.13.1-R0.1-SNAPSHOT", Version.fromString("1.13.1-R0.1-SNAPSHOT").toString());
+ assertEquals("1.13.2-R0.1-SNAPSHOT", Version.fromString("1.13.2-R0.1-SNAPSHOT").toString());
+ assertEquals("1.14-pre5-SNAPSHOT", Version.fromString("1.14-pre5-SNAPSHOT").toString());
+ assertEquals("1.14-R0.1-SNAPSHOT", Version.fromString("1.14-R0.1-SNAPSHOT").toString());
+ assertEquals("1.14.1-R0.1-SNAPSHOT", Version.fromString("1.14.1-R0.1-SNAPSHOT").toString());
+ assertEquals("1.14.2-R0.1-SNAPSHOT", Version.fromString("1.14.2-R0.1-SNAPSHOT").toString());
+ assertEquals("1.14.3-SNAPSHOT", Version.fromString("1.14.3-SNAPSHOT").toString());
+ assertEquals("1.14.3-pre4-SNAPSHOT", Version.fromString("1.14.3-pre4-SNAPSHOT").toString());
+ assertEquals("1.14.3-R0.1-SNAPSHOT", Version.fromString("1.14.3-R0.1-SNAPSHOT").toString());
+ assertEquals("1.14.4-R0.1-SNAPSHOT", Version.fromString("1.14.4-R0.1-SNAPSHOT").toString());
+ assertEquals("1.15-R0.1-SNAPSHOT", Version.fromString("1.15-R0.1-SNAPSHOT").toString());
+ assertEquals("1.15.1-R0.1-SNAPSHOT", Version.fromString("1.15.1-R0.1-SNAPSHOT").toString());
+ assertEquals("1.15.2-R0.1-SNAPSHOT", Version.fromString("1.15.2-R0.1-SNAPSHOT").toString());
+ assertEquals("1.16.1-R0.1-SNAPSHOT", Version.fromString("1.16.1-R0.1-SNAPSHOT").toString());
+ assertEquals("1.16.2-R0.1-SNAPSHOT", Version.fromString("1.16.2-R0.1-SNAPSHOT").toString());
+ assertEquals("1.16.3-R0.1-SNAPSHOT", Version.fromString("1.16.3-R0.1-SNAPSHOT").toString());
+ assertEquals("1.16.4-R0.1-SNAPSHOT", Version.fromString("1.16.4-R0.1-SNAPSHOT").toString());
+ assertEquals("1.16.5-R0.1-SNAPSHOT", Version.fromString("1.16.5-R0.1-SNAPSHOT").toString());
+ assertEquals("1.17-R0.1-SNAPSHOT", Version.fromString("1.17-R0.1-SNAPSHOT").toString());
+ assertEquals("1.17.1-R0.1-SNAPSHOT", Version.fromString("1.17.1-R0.1-SNAPSHOT").toString());
+ assertEquals("1.18-rc3-R0.1-SNAPSHOT", Version.fromString("1.18-rc3-R0.1-SNAPSHOT").toString());
+ assertEquals("1.18-pre5-R0.1-SNAPSHOT", Version.fromString("1.18-pre5-R0.1-SNAPSHOT").toString());
+ assertEquals("1.18-pre8-R0.1-SNAPSHOT", Version.fromString("1.18-pre8-R0.1-SNAPSHOT").toString());
+ assertEquals("1.18-R0.1-SNAPSHOT", Version.fromString("1.18-R0.1-SNAPSHOT").toString());
+ assertEquals("1.18.1-R0.1-SNAPSHOT", Version.fromString("1.18.1-R0.1-SNAPSHOT").toString());
+ assertEquals("1.18.2-R0.1-SNAPSHOT", Version.fromString("1.18.2-R0.1-SNAPSHOT").toString());
+ assertEquals("1.19-R0.1-SNAPSHOT", Version.fromString("1.19-R0.1-SNAPSHOT").toString());
+ assertEquals("1.19.1-R0.1-SNAPSHOT", Version.fromString("1.19.1-R0.1-SNAPSHOT").toString());
+ assertEquals("1.19.2-R0.1-SNAPSHOT", Version.fromString("1.19.2-R0.1-SNAPSHOT").toString());
+ assertEquals("1.19.3-R0.1-SNAPSHOT", Version.fromString("1.19.3-R0.1-SNAPSHOT").toString());
+ assertEquals("1.19.4-R0.1-SNAPSHOT", Version.fromString("1.19.4-R0.1-SNAPSHOT").toString());
+ assertEquals("1.20-R0.1-SNAPSHOT", Version.fromString("1.20-R0.1-SNAPSHOT").toString());
+ assertEquals("1.20.1-experimental-SNAPSHOT", Version.fromString("1.20.1-experimental-SNAPSHOT").toString());
+ assertEquals("1.20.1-R0.1-SNAPSHOT", Version.fromString("1.20.1-R0.1-SNAPSHOT").toString());
+ assertEquals("1.20.2-experimental-SNAPSHOT", Version.fromString("1.20.2-experimental-SNAPSHOT").toString());
+ assertEquals("1.20.2-R0.1-SNAPSHOT", Version.fromString("1.20.2-R0.1-SNAPSHOT").toString());
+ assertEquals("1.20.3-R0.1-SNAPSHOT", Version.fromString("1.20.3-R0.1-SNAPSHOT").toString());
+ assertEquals("1.20.4-experimental-SNAPSHOT", Version.fromString("1.20.4-experimental-SNAPSHOT").toString());
+ assertEquals("1.20.4-R0.1-SNAPSHOT", Version.fromString("1.20.4-R0.1-SNAPSHOT").toString());
+ assertEquals("1.20.5-R0.1-SNAPSHOT", Version.fromString("1.20.5-R0.1-SNAPSHOT").toString());
+ assertEquals("1.20.6-experimental-SNAPSHOT", Version.fromString("1.20.6-experimental-SNAPSHOT").toString());
+ assertEquals("1.20.6-R0.1-SNAPSHOT", Version.fromString("1.20.6-R0.1-SNAPSHOT").toString());
+ assertEquals("1.21-R0.1-SNAPSHOT", Version.fromString("1.21-R0.1-SNAPSHOT").toString());
+ assertEquals("1.21.1-R0.1-SNAPSHOT", Version.fromString("1.21.1-R0.1-SNAPSHOT").toString());
+ assertEquals("1.21.2-R0.1-SNAPSHOT", Version.fromString("1.21.2-R0.1-SNAPSHOT").toString());
+ assertEquals("1.21.3-R0.1-SNAPSHOT", Version.fromString("1.21.3-R0.1-SNAPSHOT").toString());
+ assertEquals("1.21.4-R0.1-SNAPSHOT", Version.fromString("1.21.4-R0.1-SNAPSHOT").toString());
+ assertEquals("1.21.5-no-moonrise-SNAPSHOT", Version.fromString("1.21.5-no-moonrise-SNAPSHOT").toString());
+ assertEquals("1.21.5-R0.1-SNAPSHOT", Version.fromString("1.21.5-R0.1-SNAPSHOT").toString());
+ assertEquals("1.21.6-R0.1-SNAPSHOT", Version.fromString("1.21.6-R0.1-SNAPSHOT").toString());
+ assertEquals("1.21.7-R0.1-SNAPSHOT", Version.fromString("1.21.7-R0.1-SNAPSHOT").toString());
+ assertEquals("1.21.8-R0.1-SNAPSHOT", Version.fromString("1.21.8-R0.1-SNAPSHOT").toString());
+ assertEquals("1.21.9-pre2-R0.1-SNAPSHOT", Version.fromString("1.21.9-pre2-R0.1-SNAPSHOT").toString());
+ assertEquals("1.21.9-pre3-R0.1-SNAPSHOT", Version.fromString("1.21.9-pre3-R0.1-SNAPSHOT").toString());
+ assertEquals("1.21.9-pre4-R0.1-SNAPSHOT", Version.fromString("1.21.9-pre4-R0.1-SNAPSHOT").toString());
+ assertEquals("1.21.9-rc1-R0.1-SNAPSHOT", Version.fromString("1.21.9-rc1-R0.1-SNAPSHOT").toString());
+ assertEquals("1.21.9-R0.1-SNAPSHOT", Version.fromString("1.21.9-R0.1-SNAPSHOT").toString());
+ assertEquals("1.21.10-R0.1-SNAPSHOT", Version.fromString("1.21.10-R0.1-SNAPSHOT").toString());
+ assertEquals("1.21.11-pre3-R0.1-SNAPSHOT", Version.fromString("1.21.11-pre3-R0.1-SNAPSHOT").toString());
+ assertEquals("1.21.11-pre4-R0.1-SNAPSHOT", Version.fromString("1.21.11-pre4-R0.1-SNAPSHOT").toString());
+ assertEquals("1.21.11-pre5-R0.1-SNAPSHOT", Version.fromString("1.21.11-pre5-R0.1-SNAPSHOT").toString());
+ assertEquals("1.21.11-rc1-R0.1-SNAPSHOT", Version.fromString("1.21.11-rc1-R0.1-SNAPSHOT").toString());
+ assertEquals("1.21.11-rc2-R0.1-SNAPSHOT", Version.fromString("1.21.11-rc2-R0.1-SNAPSHOT").toString());
+ assertEquals("1.21.11-rc3-R0.1-SNAPSHOT", Version.fromString("1.21.11-rc3-R0.1-SNAPSHOT").toString());
+ assertEquals("1.21.11-R0.1-SNAPSHOT", Version.fromString("1.21.11-R0.1-SNAPSHOT").toString());
+ }
+
+ @Test
+ void weirdVersioning() {
+ // To ensure future compatibility no matter what monster they come up with
+
+ assertEquals("26", Version.fromString("26").toString());
+ assertEquals("26-SNAPSHOT", Version.fromString("26-SNAPSHOT").toString());
+ assertEquals("26-R0.1-SNAPSHOT", Version.fromString("26-R0.1-SNAPSHOT").toString());
+
+ assertEquals("26.0", Version.fromString("26.0").toString());
+ assertEquals("26.0-SNAPSHOT", Version.fromString("26.0-SNAPSHOT").toString());
+ assertEquals("26.0-R0.1-SNAPSHOT", Version.fromString("26.0-R0.1-SNAPSHOT").toString());
+
+ assertEquals("26.1", Version.fromString("26.1").toString());
+ assertEquals("26.1-SNAPSHOT", Version.fromString("26.1-SNAPSHOT").toString());
+ assertEquals("26.1-R0.1-SNAPSHOT", Version.fromString("26.1-R0.1-SNAPSHOT").toString());
+
+ assertEquals("26.1.0", Version.fromString("26.1.0").toString());
+ assertEquals("26.1.0-SNAPSHOT", Version.fromString("26.1.0-SNAPSHOT").toString());
+ assertEquals("26.1.0-R0.1-SNAPSHOT", Version.fromString("26.1.0-R0.1-SNAPSHOT").toString());
+
+ assertEquals("26.1.1", Version.fromString("26.1.1").toString());
+ assertEquals("26.1.1-SNAPSHOT", Version.fromString("26.1.1-SNAPSHOT").toString());
+ assertEquals("26.1.1-R0.1-SNAPSHOT", Version.fromString("26.1.1-R0.1-SNAPSHOT").toString());
+
+ assertEquals("26.1.1.0", Version.fromString("26.1.1.0").toString());
+ assertEquals("26.1.1.0-SNAPSHOT", Version.fromString("26.1.1.0-SNAPSHOT").toString());
+ assertEquals("26.1.1.0-R0.1-SNAPSHOT", Version.fromString("26.1.1.0-R0.1-SNAPSHOT").toString());
+
+ assertEquals("26.1.1.1", Version.fromString("26.1.1.1").toString());
+ assertEquals("26.1.1.1-SNAPSHOT", Version.fromString("26.1.1.1-SNAPSHOT").toString());
+ assertEquals("26.1.1.1-R0.1-SNAPSHOT", Version.fromString("26.1.1.1-R0.1-SNAPSHOT").toString());
+ }
+
+ @Test
+ void compareTo() {
+ assertEquals(0, Version.fromString("26.1.2.3.000.0.00000.0").compareTo(Version.fromString("26.1.2.3")));
+ assertEquals(-1, Version.fromString("26.0.0").compareTo(Version.fromString("26.1")));
+ assertEquals(3, Version.fromString("26.3.0").compareTo(Version.fromString("26")));
+ assertEquals(-5, Version.fromString("26.0.5").compareTo(Version.fromString("26.5.0")));
+ }
+}