mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-09-23 19:23:12 -04:00
新增辅助方法 GameVersionNumber#isAtLeast(String, String)
(#4458)
This commit is contained in:
parent
8708e7f8b1
commit
356960cc82
@ -31,7 +31,7 @@ import java.util.regex.Pattern;
|
|||||||
/**
|
/**
|
||||||
* @author Glavo
|
* @author Glavo
|
||||||
*/
|
*/
|
||||||
public abstract class GameVersionNumber implements Comparable<GameVersionNumber> {
|
public abstract sealed class GameVersionNumber implements Comparable<GameVersionNumber> {
|
||||||
|
|
||||||
public static String[] getDefaultGameVersions() {
|
public static String[] getDefaultGameVersions() {
|
||||||
return Versions.DEFAULT_GAME_VERSIONS;
|
return Versions.DEFAULT_GAME_VERSIONS;
|
||||||
@ -103,8 +103,7 @@ public abstract class GameVersionNumber implements Comparable<GameVersionNumber>
|
|||||||
if (this instanceof Special)
|
if (this instanceof Special)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (this instanceof Snapshot) {
|
if (this instanceof Snapshot snapshot) {
|
||||||
Snapshot snapshot = (Snapshot) this;
|
|
||||||
return snapshot.intValue == Snapshot.toInt(15, 14, 'a');
|
return snapshot.intValue == Snapshot.toInt(15, 14, 'a');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,6 +130,39 @@ public abstract class GameVersionNumber implements Comparable<GameVersionNumber>
|
|||||||
return compareToImpl(other);
|
return compareToImpl(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @see #isAtLeast(String, String, boolean)
|
||||||
|
public boolean isAtLeast(@NotNull String releaseVersion, @NotNull String snapshotVersion) {
|
||||||
|
return isAtLeast(releaseVersion, snapshotVersion, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// When comparing between Release Version and Snapshot Version, it is necessary to load `/assets/game/versions.txt` and perform a lookup, which is less efficient.
|
||||||
|
/// Therefore, when checking whether a version contains a certain feature, you should use this method and provide both the first release version and the exact snapshot version that introduced the feature,
|
||||||
|
/// so that the comparison can be performed quickly without a lookup.
|
||||||
|
///
|
||||||
|
/// For example, the datapack feature was introduced in Minecraft 1.13, and more specifically in snapshot `17w43a`.
|
||||||
|
/// So you can test whether a game version supports datapacks like this:
|
||||||
|
///
|
||||||
|
/// ```java
|
||||||
|
/// GameVersionNumber.asVersion("...").isAtLeast("1.13", "17w43a");
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// @param strictReleaseVersion When `strictReleaseVersion` is `false`, `releaseVersion` is considered less than
|
||||||
|
/// its corresponding pre/rc versions.
|
||||||
|
public boolean isAtLeast(@NotNull String releaseVersion, @NotNull String snapshotVersion, boolean strictReleaseVersion) {
|
||||||
|
if (this instanceof Release self) {
|
||||||
|
Release other;
|
||||||
|
if (strictReleaseVersion) {
|
||||||
|
other = Release.parse(releaseVersion);
|
||||||
|
} else {
|
||||||
|
other = Release.parseSimple(releaseVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
return self.compareToRelease(other) >= 0;
|
||||||
|
} else {
|
||||||
|
return this.compareTo(Snapshot.parse(snapshotVersion)) >= 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return value;
|
return value;
|
||||||
@ -201,9 +233,7 @@ public abstract class GameVersionNumber implements Comparable<GameVersionNumber>
|
|||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (!(o instanceof Old)) return false;
|
return o instanceof Old other && type == other.type && this.versionNumber.compareTo(other.versionNumber) == 0;
|
||||||
Old other = (Old) o;
|
|
||||||
return type == other.type && this.versionNumber.compareTo(other.versionNumber) == 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -256,6 +286,52 @@ public abstract class GameVersionNumber implements Comparable<GameVersionNumber>
|
|||||||
return new Release(value, 1, minor, patch, eaType, eaVersion);
|
return new Release(value, 1, minor, patch, eaType, eaVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static int getNumberLength(String value, int offset) {
|
||||||
|
int current = offset;
|
||||||
|
while (current < value.length()) {
|
||||||
|
char ch = value.charAt(current);
|
||||||
|
if (ch < '0' || ch > '9')
|
||||||
|
break;
|
||||||
|
|
||||||
|
current++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return current - offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Quickly parses a simple format (`1\.[0-9]+(\.[0-9]+)?`) release version.
|
||||||
|
/// The returned [#eaType] will be set to [#TYPE_UNKNOWN], meaning it will be less than all pre/rc and official versions of this version.
|
||||||
|
///
|
||||||
|
/// @see GameVersionNumber#isAtLeast(String, String)
|
||||||
|
static Release parseSimple(String value) {
|
||||||
|
if (!value.startsWith("1."))
|
||||||
|
throw new IllegalArgumentException(value);
|
||||||
|
|
||||||
|
final int minorOffset = 2;
|
||||||
|
|
||||||
|
int minorLength = getNumberLength(value, minorOffset);
|
||||||
|
if (minorLength == 0)
|
||||||
|
throw new IllegalArgumentException(value);
|
||||||
|
|
||||||
|
try {
|
||||||
|
int minor = Integer.parseInt(value.substring(minorOffset, minorOffset + minorLength));
|
||||||
|
int patch = 0;
|
||||||
|
|
||||||
|
if (minorOffset + minorLength < value.length()) {
|
||||||
|
int patchOffset = minorOffset + minorLength + 1;
|
||||||
|
|
||||||
|
if (patchOffset >= value.length() || value.charAt(patchOffset - 1) != '.')
|
||||||
|
throw new IllegalArgumentException(value);
|
||||||
|
|
||||||
|
patch = Integer.parseInt(value.substring(patchOffset));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Release(value, 1, minor, patch, TYPE_UNKNOWN, VersionNumber.ZERO);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
throw new IllegalArgumentException(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private final int major;
|
private final int major;
|
||||||
private final int minor;
|
private final int minor;
|
||||||
private final int patch;
|
private final int patch;
|
||||||
@ -280,24 +356,20 @@ public abstract class GameVersionNumber implements Comparable<GameVersionNumber>
|
|||||||
|
|
||||||
int compareToRelease(Release other) {
|
int compareToRelease(Release other) {
|
||||||
int c = Integer.compare(this.major, other.major);
|
int c = Integer.compare(this.major, other.major);
|
||||||
if (c != 0) {
|
if (c != 0)
|
||||||
return c;
|
return c;
|
||||||
}
|
|
||||||
|
|
||||||
c = Integer.compare(this.minor, other.minor);
|
c = Integer.compare(this.minor, other.minor);
|
||||||
if (c != 0) {
|
if (c != 0)
|
||||||
return c;
|
return c;
|
||||||
}
|
|
||||||
|
|
||||||
c = Integer.compare(this.patch, other.patch);
|
c = Integer.compare(this.patch, other.patch);
|
||||||
if (c != 0) {
|
if (c != 0)
|
||||||
return c;
|
return c;
|
||||||
}
|
|
||||||
|
|
||||||
c = Integer.compare(this.eaType, other.eaType);
|
c = Integer.compare(this.eaType, other.eaType);
|
||||||
if (c != 0) {
|
if (c != 0)
|
||||||
return c;
|
return c;
|
||||||
}
|
|
||||||
|
|
||||||
return this.eaVersion.compareTo(other.eaVersion);
|
return this.eaVersion.compareTo(other.eaVersion);
|
||||||
}
|
}
|
||||||
@ -356,9 +428,12 @@ public abstract class GameVersionNumber implements Comparable<GameVersionNumber>
|
|||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
return o instanceof Release other
|
||||||
Release other = (Release) o;
|
&& major == other.major
|
||||||
return major == other.major && minor == other.minor && patch == other.patch && eaType == other.eaType && eaVersion.equals(other.eaVersion);
|
&& minor == other.minor
|
||||||
|
&& patch == other.patch
|
||||||
|
&& eaType == other.eaType
|
||||||
|
&& eaVersion.equals(other.eaVersion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -428,9 +503,7 @@ public abstract class GameVersionNumber implements Comparable<GameVersionNumber>
|
|||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
return o instanceof Snapshot other && this.intValue == other.intValue;
|
||||||
Snapshot other = (Snapshot) o;
|
|
||||||
return this.intValue == other.intValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -534,9 +607,7 @@ public abstract class GameVersionNumber implements Comparable<GameVersionNumber>
|
|||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
return o instanceof Special other && this.value.equals(other.value);
|
||||||
Special other = (Special) o;
|
|
||||||
return Objects.equals(this.value, other.value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -566,8 +637,7 @@ public abstract class GameVersionNumber implements Comparable<GameVersionNumber>
|
|||||||
if (currentRelease == null)
|
if (currentRelease == null)
|
||||||
currentRelease = (Release) version;
|
currentRelease = (Release) version;
|
||||||
|
|
||||||
if (version instanceof Snapshot) {
|
if (version instanceof Snapshot snapshot) {
|
||||||
Snapshot snapshot = (Snapshot) version;
|
|
||||||
snapshots.add(snapshot);
|
snapshots.add(snapshot);
|
||||||
snapshotPrev.add(currentRelease);
|
snapshotPrev.add(currentRelease);
|
||||||
} else if (version instanceof Release) {
|
} else if (version instanceof Release) {
|
||||||
@ -576,8 +646,7 @@ public abstract class GameVersionNumber implements Comparable<GameVersionNumber>
|
|||||||
if (currentRelease.eaType == Release.TYPE_GA) {
|
if (currentRelease.eaType == Release.TYPE_GA) {
|
||||||
defaultGameVersions.addFirst(currentRelease.value);
|
defaultGameVersions.addFirst(currentRelease.value);
|
||||||
}
|
}
|
||||||
} else if (version instanceof Special) {
|
} else if (version instanceof Special special) {
|
||||||
Special special = (Special) version;
|
|
||||||
special.prev = prev;
|
special.prev = prev;
|
||||||
SPECIALS.put(special.value, special);
|
SPECIALS.put(special.value, special);
|
||||||
} else
|
} else
|
||||||
|
@ -26,6 +26,7 @@ import java.io.UncheckedIOException;
|
|||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import static org.jackhuang.hmcl.util.versioning.GameVersionNumber.asGameVersion;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -66,8 +67,8 @@ public final class GameVersionNumberTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void assertGameVersionEquals(String version1, String version2) {
|
private static void assertGameVersionEquals(String version1, String version2) {
|
||||||
assertEquals(0, GameVersionNumber.asGameVersion(version1).compareTo(version2), errorMessage(version1, version2));
|
assertEquals(0, asGameVersion(version1).compareTo(version2), errorMessage(version1, version2));
|
||||||
assertEquals(GameVersionNumber.asGameVersion(version1), GameVersionNumber.asGameVersion(version2), errorMessage(version1, version2));
|
assertEquals(asGameVersion(version1), asGameVersion(version2), errorMessage(version1, version2));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String toString(GameVersionNumber gameVersionNumber) {
|
private static String toString(GameVersionNumber gameVersionNumber) {
|
||||||
@ -76,12 +77,12 @@ public final class GameVersionNumberTest {
|
|||||||
|
|
||||||
private static void assertOrder(String... versions) {
|
private static void assertOrder(String... versions) {
|
||||||
for (int i = 0; i < versions.length - 1; i++) {
|
for (int i = 0; i < versions.length - 1; i++) {
|
||||||
GameVersionNumber version1 = GameVersionNumber.asGameVersion(versions[i]);
|
GameVersionNumber version1 = asGameVersion(versions[i]);
|
||||||
|
|
||||||
assertGameVersionEquals(versions[i]);
|
assertGameVersionEquals(versions[i]);
|
||||||
|
|
||||||
for (int j = i + 1; j < versions.length; j++) {
|
for (int j = i + 1; j < versions.length; j++) {
|
||||||
GameVersionNumber version2 = GameVersionNumber.asGameVersion(versions[j]);
|
GameVersionNumber version2 = asGameVersion(versions[j]);
|
||||||
|
|
||||||
assertEquals(-1, version1.compareTo(version2), String.format("version1=%s (%s), version2=%s (%s)", versions[i], toString(version1), versions[j], toString(version2)));
|
assertEquals(-1, version1.compareTo(version2), String.format("version1=%s (%s), version2=%s (%s)", versions[i], toString(version1), versions[j], toString(version2)));
|
||||||
assertEquals(1, version2.compareTo(version1), String.format("version1=%s (%s), version2=%s (%s)", versions[i], toString(version1), versions[j], toString(version2)));
|
assertEquals(1, version2.compareTo(version1), String.format("version1=%s (%s), version2=%s (%s)", versions[i], toString(version1), versions[j], toString(version2)));
|
||||||
@ -92,7 +93,7 @@ public final class GameVersionNumberTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void assertOldVersion(String oldVersion, GameVersionNumber.Type type, String versionNumber) {
|
private void assertOldVersion(String oldVersion, GameVersionNumber.Type type, String versionNumber) {
|
||||||
GameVersionNumber version = GameVersionNumber.asGameVersion(oldVersion);
|
GameVersionNumber version = asGameVersion(oldVersion);
|
||||||
assertInstanceOf(GameVersionNumber.Old.class, version);
|
assertInstanceOf(GameVersionNumber.Old.class, version);
|
||||||
GameVersionNumber.Old old = (GameVersionNumber.Old) version;
|
GameVersionNumber.Old old = (GameVersionNumber.Old) version;
|
||||||
assertSame(type, old.type);
|
assertSame(type, old.type);
|
||||||
@ -100,7 +101,7 @@ public final class GameVersionNumberTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isAprilFools(String version) {
|
private static boolean isAprilFools(String version) {
|
||||||
return GameVersionNumber.asGameVersion(version).isAprilFools();
|
return asGameVersion(version).isAprilFools();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -142,10 +143,36 @@ public final class GameVersionNumberTest {
|
|||||||
public void testParseNew() {
|
public void testParseNew() {
|
||||||
List<String> versions = readVersions();
|
List<String> versions = readVersions();
|
||||||
for (String version : versions) {
|
for (String version : versions) {
|
||||||
assertFalse(GameVersionNumber.asGameVersion(version) instanceof GameVersionNumber.Old, "version=" + version);
|
assertFalse(asGameVersion(version) instanceof GameVersionNumber.Old, "version=" + version);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void assertSimpleReleaseVersion(String simpleReleaseVersion, int minor, int patch) {
|
||||||
|
GameVersionNumber.Release release = GameVersionNumber.Release.parseSimple(simpleReleaseVersion);
|
||||||
|
assertAll("Assert Simple Release Version " + simpleReleaseVersion,
|
||||||
|
() -> assertEquals(1, release.getMajor()),
|
||||||
|
() -> assertEquals(minor, release.getMinor()),
|
||||||
|
() -> assertEquals(patch, release.getPatch()),
|
||||||
|
() -> assertEquals(GameVersionNumber.Release.TYPE_UNKNOWN, release.getEaType()),
|
||||||
|
() -> assertEquals(VersionNumber.ZERO, release.getEaVersion())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParseSimpleRelease() {
|
||||||
|
assertSimpleReleaseVersion("1.0", 0, 0);
|
||||||
|
assertSimpleReleaseVersion("1.13", 13, 0);
|
||||||
|
assertSimpleReleaseVersion("1.21.8", 21, 8);
|
||||||
|
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> GameVersionNumber.Release.parseSimple("2.0"));
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> GameVersionNumber.Release.parseSimple("1..0"));
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> GameVersionNumber.Release.parseSimple("1.0."));
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> GameVersionNumber.Release.parseSimple("1.a"));
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> GameVersionNumber.Release.parseSimple("1.1a"));
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> GameVersionNumber.Release.parseSimple("1.0a"));
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> GameVersionNumber.Release.parseSimple("1.0.0.0"));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCompareRelease() {
|
public void testCompareRelease() {
|
||||||
assertGameVersionEquals("0.0");
|
assertGameVersionEquals("0.0");
|
||||||
@ -281,4 +308,27 @@ public final class GameVersionNumberTest {
|
|||||||
"1.1"
|
"1.1"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isAtLeast() {
|
||||||
|
assertTrue(asGameVersion("1.13").isAtLeast("1.13", "17w43a"));
|
||||||
|
assertTrue(asGameVersion("1.13.1").isAtLeast("1.13", "17w43a"));
|
||||||
|
assertTrue(asGameVersion("1.14").isAtLeast("1.13", "17w43a"));
|
||||||
|
assertTrue(asGameVersion("1.13-rc1").isAtLeast("1.13", "17w43a"));
|
||||||
|
assertTrue(asGameVersion("1.13-pre1").isAtLeast("1.13", "17w43a"));
|
||||||
|
assertTrue(asGameVersion("17w43a").isAtLeast("1.13", "17w43a"));
|
||||||
|
assertTrue(asGameVersion("17w43b").isAtLeast("1.13", "17w43a"));
|
||||||
|
assertTrue(asGameVersion("17w45a").isAtLeast("1.13", "17w43a"));
|
||||||
|
|
||||||
|
assertFalse(asGameVersion("17w31a").isAtLeast("1.13", "17w43a"));
|
||||||
|
assertFalse(asGameVersion("1.12").isAtLeast("1.13", "17w43a"));
|
||||||
|
assertFalse(asGameVersion("1.12.2").isAtLeast("1.13", "17w43a"));
|
||||||
|
assertFalse(asGameVersion("1.12.2-pre1").isAtLeast("1.13", "17w43a"));
|
||||||
|
assertFalse(asGameVersion("rd-132211").isAtLeast("1.13", "17w43a"));
|
||||||
|
assertFalse(asGameVersion("a1.0.6").isAtLeast("1.13", "17w43a"));
|
||||||
|
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> asGameVersion("1.13").isAtLeast("17w43a", "17w43a"));
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> asGameVersion("17w43a").isAtLeast("1.13", "1.13"));
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> asGameVersion("17w43a").isAtLeast("1.13", "22w13oneblockatatime"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user