mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-09-23 03:04:07 -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
|
||||
*/
|
||||
public abstract class GameVersionNumber implements Comparable<GameVersionNumber> {
|
||||
public abstract sealed class GameVersionNumber implements Comparable<GameVersionNumber> {
|
||||
|
||||
public static String[] getDefaultGameVersions() {
|
||||
return Versions.DEFAULT_GAME_VERSIONS;
|
||||
@ -103,8 +103,7 @@ public abstract class GameVersionNumber implements Comparable<GameVersionNumber>
|
||||
if (this instanceof Special)
|
||||
return true;
|
||||
|
||||
if (this instanceof Snapshot) {
|
||||
Snapshot snapshot = (Snapshot) this;
|
||||
if (this instanceof Snapshot snapshot) {
|
||||
return snapshot.intValue == Snapshot.toInt(15, 14, 'a');
|
||||
}
|
||||
|
||||
@ -131,6 +130,39 @@ public abstract class GameVersionNumber implements Comparable<GameVersionNumber>
|
||||
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
|
||||
public String toString() {
|
||||
return value;
|
||||
@ -201,9 +233,7 @@ public abstract class GameVersionNumber implements Comparable<GameVersionNumber>
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof Old)) return false;
|
||||
Old other = (Old) o;
|
||||
return type == other.type && this.versionNumber.compareTo(other.versionNumber) == 0;
|
||||
return o instanceof Old other && type == other.type && this.versionNumber.compareTo(other.versionNumber) == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -256,6 +286,52 @@ public abstract class GameVersionNumber implements Comparable<GameVersionNumber>
|
||||
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 minor;
|
||||
private final int patch;
|
||||
@ -280,24 +356,20 @@ public abstract class GameVersionNumber implements Comparable<GameVersionNumber>
|
||||
|
||||
int compareToRelease(Release other) {
|
||||
int c = Integer.compare(this.major, other.major);
|
||||
if (c != 0) {
|
||||
if (c != 0)
|
||||
return c;
|
||||
}
|
||||
|
||||
c = Integer.compare(this.minor, other.minor);
|
||||
if (c != 0) {
|
||||
if (c != 0)
|
||||
return c;
|
||||
}
|
||||
|
||||
c = Integer.compare(this.patch, other.patch);
|
||||
if (c != 0) {
|
||||
if (c != 0)
|
||||
return c;
|
||||
}
|
||||
|
||||
c = Integer.compare(this.eaType, other.eaType);
|
||||
if (c != 0) {
|
||||
if (c != 0)
|
||||
return c;
|
||||
}
|
||||
|
||||
return this.eaVersion.compareTo(other.eaVersion);
|
||||
}
|
||||
@ -356,9 +428,12 @@ public abstract class GameVersionNumber implements Comparable<GameVersionNumber>
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Release other = (Release) o;
|
||||
return major == other.major && minor == other.minor && patch == other.patch && eaType == other.eaType && eaVersion.equals(other.eaVersion);
|
||||
return o instanceof Release other
|
||||
&& major == other.major
|
||||
&& 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
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Snapshot other = (Snapshot) o;
|
||||
return this.intValue == other.intValue;
|
||||
return o instanceof Snapshot other && this.intValue == other.intValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -534,9 +607,7 @@ public abstract class GameVersionNumber implements Comparable<GameVersionNumber>
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Special other = (Special) o;
|
||||
return Objects.equals(this.value, other.value);
|
||||
return o instanceof Special other && this.value.equals(other.value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -566,8 +637,7 @@ public abstract class GameVersionNumber implements Comparable<GameVersionNumber>
|
||||
if (currentRelease == null)
|
||||
currentRelease = (Release) version;
|
||||
|
||||
if (version instanceof Snapshot) {
|
||||
Snapshot snapshot = (Snapshot) version;
|
||||
if (version instanceof Snapshot snapshot) {
|
||||
snapshots.add(snapshot);
|
||||
snapshotPrev.add(currentRelease);
|
||||
} else if (version instanceof Release) {
|
||||
@ -576,8 +646,7 @@ public abstract class GameVersionNumber implements Comparable<GameVersionNumber>
|
||||
if (currentRelease.eaType == Release.TYPE_GA) {
|
||||
defaultGameVersions.addFirst(currentRelease.value);
|
||||
}
|
||||
} else if (version instanceof Special) {
|
||||
Special special = (Special) version;
|
||||
} else if (version instanceof Special special) {
|
||||
special.prev = prev;
|
||||
SPECIALS.put(special.value, special);
|
||||
} else
|
||||
|
@ -26,6 +26,7 @@ import java.io.UncheckedIOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
|
||||
import static org.jackhuang.hmcl.util.versioning.GameVersionNumber.asGameVersion;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
@ -66,8 +67,8 @@ public final class GameVersionNumberTest {
|
||||
}
|
||||
|
||||
private static void assertGameVersionEquals(String version1, String version2) {
|
||||
assertEquals(0, GameVersionNumber.asGameVersion(version1).compareTo(version2), errorMessage(version1, version2));
|
||||
assertEquals(GameVersionNumber.asGameVersion(version1), GameVersionNumber.asGameVersion(version2), errorMessage(version1, version2));
|
||||
assertEquals(0, asGameVersion(version1).compareTo(version2), errorMessage(version1, version2));
|
||||
assertEquals(asGameVersion(version1), asGameVersion(version2), errorMessage(version1, version2));
|
||||
}
|
||||
|
||||
private static String toString(GameVersionNumber gameVersionNumber) {
|
||||
@ -76,12 +77,12 @@ public final class GameVersionNumberTest {
|
||||
|
||||
private static void assertOrder(String... versions) {
|
||||
for (int i = 0; i < versions.length - 1; i++) {
|
||||
GameVersionNumber version1 = GameVersionNumber.asGameVersion(versions[i]);
|
||||
GameVersionNumber version1 = asGameVersion(versions[i]);
|
||||
|
||||
assertGameVersionEquals(versions[i]);
|
||||
|
||||
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, 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) {
|
||||
GameVersionNumber version = GameVersionNumber.asGameVersion(oldVersion);
|
||||
GameVersionNumber version = asGameVersion(oldVersion);
|
||||
assertInstanceOf(GameVersionNumber.Old.class, version);
|
||||
GameVersionNumber.Old old = (GameVersionNumber.Old) version;
|
||||
assertSame(type, old.type);
|
||||
@ -100,7 +101,7 @@ public final class GameVersionNumberTest {
|
||||
}
|
||||
|
||||
private static boolean isAprilFools(String version) {
|
||||
return GameVersionNumber.asGameVersion(version).isAprilFools();
|
||||
return asGameVersion(version).isAprilFools();
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -142,10 +143,36 @@ public final class GameVersionNumberTest {
|
||||
public void testParseNew() {
|
||||
List<String> versions = readVersions();
|
||||
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
|
||||
public void testCompareRelease() {
|
||||
assertGameVersionEquals("0.0");
|
||||
@ -281,4 +308,27 @@ public final class GameVersionNumberTest {
|
||||
"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