diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameLauncher.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameLauncher.java index 26f288436..f37ffe862 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameLauncher.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameLauncher.java @@ -25,7 +25,7 @@ import org.jackhuang.hmcl.util.Logging; import org.jackhuang.hmcl.util.i18n.I18n; import org.jackhuang.hmcl.util.io.FileUtils; import org.jackhuang.hmcl.util.platform.ManagedProcess; -import org.jackhuang.hmcl.util.versioning.VersionNumber; +import org.jackhuang.hmcl.util.versioning.GameVersionNumber; import java.io.File; import java.io.IOException; @@ -84,7 +84,7 @@ public final class HMCLGameLauncher extends DefaultLauncher { 1.11 ~ 12:zh_cn 时正常,zh_CN 时虽然显示了中文但语言设置会错误地显示选择英文 1.13+ :zh_cn 时正常,zh_CN 时自动切换为英文 */ - VersionNumber gameVersion = VersionNumber.asVersion(repository.getGameVersion(version).orElse("0.0")); + GameVersionNumber gameVersion = GameVersionNumber.asGameVersion(repository.getGameVersion(version)); if (gameVersion.compareTo("1.1") < 0) { lang = null; } else if (gameVersion.compareTo("1.11") < 0) { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java index 24e46a21e..a00b8ee9a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -45,6 +45,7 @@ import org.jackhuang.hmcl.util.*; import org.jackhuang.hmcl.util.i18n.I18n; import org.jackhuang.hmcl.util.io.ResponseCodeException; import org.jackhuang.hmcl.util.platform.*; +import org.jackhuang.hmcl.util.versioning.GameVersionNumber; import org.jackhuang.hmcl.util.versioning.VersionNumber; import java.io.File; @@ -332,7 +333,7 @@ public final class LauncherHelper { } private static Task checkGameState(Profile profile, VersionSetting setting, Version version) { - VersionNumber gameVersion = VersionNumber.asVersion(profile.getRepository().getGameVersion(version).orElse("Unknown")); + GameVersionNumber gameVersion = GameVersionNumber.asGameVersion(profile.getRepository().getGameVersion(version)); if (setting.isNotCheckJVM()) { return Task.composeAsync(() -> setting.getJavaVersion(gameVersion, version)) @@ -549,14 +550,14 @@ public final class LauncherHelper { // Forge 2760~2773 will crash game with LiteLoader. boolean hasForge2760 = forgeVersion != null && (forgeVersion.compareTo("1.12.2-14.23.5.2760") >= 0) && (forgeVersion.compareTo("1.12.2-14.23.5.2773") < 0); boolean hasLiteLoader = version.getLibraries().stream().anyMatch(it -> it.is("com.mumfrey", "liteloader")); - if (hasForge2760 && hasLiteLoader && gameVersion.compareTo(VersionNumber.asVersion("1.12.2")) == 0) { + if (hasForge2760 && hasLiteLoader && gameVersion.compareTo("1.12.2") == 0) { suggestions.add(i18n("launch.advice.forge2760_liteloader")); } // OptiFine 1.14.4 is not compatible with Forge 28.2.2 and later versions. boolean hasForge28_2_2 = forgeVersion != null && (forgeVersion.compareTo("1.14.4-28.2.2") >= 0); boolean hasOptiFine = version.getLibraries().stream().anyMatch(it -> it.is("optifine", "OptiFine")); - if (hasForge28_2_2 && hasOptiFine && gameVersion.compareTo(VersionNumber.asVersion("1.14.4")) == 0) { + if (hasForge28_2_2 && hasOptiFine && gameVersion.compareTo("1.14.4") == 0) { suggestions.add(i18n("launch.advice.forge28_2_2_optifine")); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java index 9b9b752bf..0d4feb2f8 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java @@ -31,7 +31,7 @@ import org.jackhuang.hmcl.util.platform.Architecture; import org.jackhuang.hmcl.util.platform.JavaVersion; import org.jackhuang.hmcl.util.platform.OperatingSystem; import org.jackhuang.hmcl.util.platform.Platform; -import org.jackhuang.hmcl.util.versioning.VersionNumber; +import org.jackhuang.hmcl.util.versioning.GameVersionNumber; import java.io.IOException; import java.lang.reflect.Type; @@ -644,11 +644,11 @@ public final class VersionSetting implements Cloneable { launcherVisibilityProperty.set(launcherVisibility); } - public Task getJavaVersion(VersionNumber gameVersion, Version version) { + public Task getJavaVersion(GameVersionNumber gameVersion, Version version) { return getJavaVersion(gameVersion, version, true); } - public Task getJavaVersion(VersionNumber gameVersion, Version version, boolean checkJava) { + public Task getJavaVersion(GameVersionNumber gameVersion, Version version, boolean checkJava) { return Task.runAsync(Schedulers.javafx(), () -> { if (StringUtils.isBlank(getJava())) { setJava(StringUtils.isBlank(getJavaDir()) ? "Auto" : "Custom"); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerItem.java index 9c3da9be6..4fe9995aa 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerItem.java @@ -39,7 +39,7 @@ import org.jackhuang.hmcl.setting.Theme; import org.jackhuang.hmcl.setting.VersionIconType; import org.jackhuang.hmcl.ui.construct.RipplerContainer; import org.jackhuang.hmcl.util.i18n.I18n; -import org.jackhuang.hmcl.util.versioning.VersionNumber; +import org.jackhuang.hmcl.util.versioning.GameVersionNumber; import java.util.HashMap; import java.util.HashSet; @@ -204,7 +204,7 @@ public class InstallerItem extends Control { if (gameVersion == null) { this.libraries = new InstallerItem[]{game, forge, neoForge, liteLoader, optiFine, fabric, fabricApi, quilt, quiltApi}; - } else if (VersionNumber.compare(gameVersion, "1.13") < 0) { + } else if (GameVersionNumber.compare(gameVersion, "1.13") < 0) { this.libraries = new InstallerItem[]{game, forge, liteLoader, optiFine}; } else { this.libraries = new InstallerItem[]{game, forge, neoForge, optiFine, fabric, fabricApi, quilt, quiltApi}; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/RootPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/RootPage.java index 36d5af536..b5cee07e5 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/RootPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/RootPage.java @@ -120,7 +120,7 @@ public class RootPage extends DecoratorAnimatedPage implements DecoratorPage { .sorted(Comparator .comparing((Version version) -> version.getReleaseTime() == null ? new Date(0L) : version.getReleaseTime()) - .thenComparing(a -> VersionNumber.asVersion(a.getId()))) + .thenComparing(version -> VersionNumber.asVersion(repository.getGameVersion(version).orElse(version.getId())))) .collect(Collectors.toList()); runInFX(() -> { if (profile == Profiles.getSelectedProfile()) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadListPage.java index 17ad04b11..0f300cae1 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadListPage.java @@ -37,7 +37,6 @@ import javafx.scene.control.Skin; import javafx.scene.control.SkinBase; import javafx.scene.image.ImageView; import javafx.scene.layout.*; -import org.jackhuang.hmcl.game.GameVersion; import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.mod.RemoteMod; import org.jackhuang.hmcl.mod.RemoteModRepository; @@ -57,8 +56,8 @@ import org.jackhuang.hmcl.util.Lang; import org.jackhuang.hmcl.util.StringUtils; import org.jackhuang.hmcl.util.i18n.I18n; import org.jackhuang.hmcl.util.javafx.BindingMapping; +import org.jackhuang.hmcl.util.versioning.GameVersionNumber; -import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.Locale; @@ -163,24 +162,23 @@ public class DownloadListPage extends Control implements DecoratorPage, VersionP retrySearch = null; setLoading(true); setFailed(false); - File versionJar = StringUtils.isNotBlank(version.get().getVersion()) - ? version.get().getProfile().getRepository().getVersionJar(version.get().getVersion()) - : null; + if (executor != null && !executor.isCancelled()) { executor.cancel(); } executor = Task.supplyAsync(() -> { - String gameVersion; - if (StringUtils.isBlank(version.get().getVersion())) { - gameVersion = userGameVersion; + Profile.ProfileVersion version = this.version.get(); + if (StringUtils.isBlank(version.getVersion())) { + return userGameVersion; } else { - gameVersion = GameVersion.minecraftVersion(versionJar).orElse(""); + return StringUtils.isNotBlank(version.getVersion()) + ? version.getProfile().getRepository().getGameVersion(version.getVersion()).orElse("") + : ""; } - return gameVersion; - }).thenApplyAsync(gameVersion -> { - return repository.search(gameVersion, category, pageOffset, 50, searchFilter, sort, RemoteModRepository.SortOrder.DESC); - }).whenComplete(Schedulers.javafx(), (result, exception) -> { + }).thenApplyAsync(gameVersion -> + repository.search(gameVersion, category, pageOffset, 50, searchFilter, sort, RemoteModRepository.SortOrder.DESC) + ).whenComplete(Schedulers.javafx(), (result, exception) -> { setLoading(false); if (exception == null) { items.setAll(result.getResults().collect(Collectors.toList())); @@ -295,7 +293,7 @@ public class DownloadListPage extends Control implements DecoratorPage, VersionP JFXComboBox gameVersionField = new JFXComboBox<>(); gameVersionField.setMaxWidth(Double.MAX_VALUE); gameVersionField.setEditable(true); - gameVersionField.getItems().setAll(RemoteModRepository.DEFAULT_GAME_VERSIONS); + gameVersionField.getItems().setAll(GameVersionNumber.getDefaultGameVersions()); Label lblGameVersion = new Label(i18n("world.game_version")); searchPane.addRow(rowIndex++, new Label(i18n("mods.name")), nameField, lblGameVersion, gameVersionField); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadPage.java index df728ff13..5ccc6b666 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadPage.java @@ -51,7 +51,7 @@ import org.jackhuang.hmcl.util.*; import org.jackhuang.hmcl.util.i18n.I18n; import org.jackhuang.hmcl.util.io.NetworkUtils; import org.jackhuang.hmcl.util.javafx.BindingMapping; -import org.jackhuang.hmcl.util.versioning.VersionNumber; +import org.jackhuang.hmcl.util.versioning.GameVersionNumber; import org.jetbrains.annotations.Nullable; import java.io.File; @@ -309,7 +309,7 @@ public class DownloadPage extends Control implements DecoratorPage { } for (String gameVersion : control.versions.keys().stream() - .sorted(Collections.reverseOrder(VersionNumber::compare)) + .sorted(Collections.reverseOrder(GameVersionNumber::compare)) .collect(Collectors.toList())) { ComponentList sublist = new ComponentList(() -> control.versions.get(gameVersion).stream() diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java index 45b835743..15c451a4f 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java @@ -46,7 +46,7 @@ import org.jackhuang.hmcl.util.javafx.SafeStringConverter; import org.jackhuang.hmcl.util.platform.Architecture; import org.jackhuang.hmcl.util.platform.JavaVersion; import org.jackhuang.hmcl.util.platform.OperatingSystem; -import org.jackhuang.hmcl.util.versioning.VersionNumber; +import org.jackhuang.hmcl.util.versioning.GameVersionNumber; import java.io.File; import java.nio.file.Path; @@ -611,10 +611,10 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag Task.composeAsync(Schedulers.javafx(), () -> { if (versionId == null) { - return versionSetting.getJavaVersion(VersionNumber.asVersion("Unknown"), null); + return versionSetting.getJavaVersion(GameVersionNumber.unknown(), null); } else { return versionSetting.getJavaVersion( - VersionNumber.asVersion(GameVersion.minecraftVersion(profile.getRepository().getVersionJar(versionId)).orElse("Unknown")), + GameVersionNumber.asGameVersion(profile.getRepository().getGameVersion(versionId)), profile.getRepository().getVersion(versionId)); } }).thenAcceptAsync(Schedulers.javafx(), javaVersion -> javaSublist.setSubtitle(Optional.ofNullable(javaVersion) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListItem.java index 2bc3119ae..5f98c2255 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListItem.java @@ -29,7 +29,7 @@ import org.jackhuang.hmcl.game.World; import org.jackhuang.hmcl.ui.Controllers; import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.wizard.SinglePageWizardProvider; -import org.jackhuang.hmcl.util.versioning.VersionNumber; +import org.jackhuang.hmcl.util.versioning.GameVersionNumber; import java.io.File; import java.time.Instant; @@ -94,8 +94,7 @@ public class WorldListItem extends Control { public void manageDatapacks() { if (world.getGameVersion() == null || // old game will not write game version to level.dat - (VersionNumber.isIntVersionNumber(world.getGameVersion()) // we don't parse snapshot version - && VersionNumber.asVersion(world.getGameVersion()).compareTo(VersionNumber.asVersion("1.13")) < 0)) { + GameVersionNumber.compare(world.getGameVersion(), "1.13") < 0) { Controllers.dialog(i18n("world.datapack.1_13")); return; } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateChecker.java b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateChecker.java index f91b4cc79..10569497b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateChecker.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateChecker.java @@ -32,13 +32,12 @@ import static org.jackhuang.hmcl.util.Lang.mapOf; import static org.jackhuang.hmcl.util.Lang.thread; import static org.jackhuang.hmcl.util.Logging.LOG; import static org.jackhuang.hmcl.util.Pair.pair; -import static org.jackhuang.hmcl.util.versioning.VersionNumber.asVersion; public final class UpdateChecker { private UpdateChecker() {} - private static ObjectProperty latestVersion = new SimpleObjectProperty<>(); - private static BooleanBinding outdated = Bindings.createBooleanBinding( + private static final ObjectProperty latestVersion = new SimpleObjectProperty<>(); + private static final BooleanBinding outdated = Bindings.createBooleanBinding( () -> { RemoteVersion latest = latestVersion.get(); if (latest == null || isDevelopmentVersion(Metadata.VERSION)) { @@ -46,11 +45,11 @@ public final class UpdateChecker { } else { // We can update from development version to stable version, // which can be downgrading. - return asVersion(latest.getVersion()).compareTo(asVersion(Metadata.VERSION)) != 0; + return !latest.getVersion().equals(Metadata.VERSION); } }, latestVersion); - private static ReadOnlyBooleanWrapper checkingUpdate = new ReadOnlyBooleanWrapper(false); + private static final ReadOnlyBooleanWrapper checkingUpdate = new ReadOnlyBooleanWrapper(false); public static void init() { requestCheckUpdate(UpdateChannel.getChannel()); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/util/NativePatcher.java b/HMCL/src/main/java/org/jackhuang/hmcl/util/NativePatcher.java index 073f9afd9..463fddd20 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/util/NativePatcher.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/util/NativePatcher.java @@ -8,7 +8,7 @@ import org.jackhuang.hmcl.util.platform.Architecture; import org.jackhuang.hmcl.util.platform.JavaVersion; import org.jackhuang.hmcl.util.platform.OperatingSystem; import org.jackhuang.hmcl.util.platform.Platform; -import org.jackhuang.hmcl.util.versioning.VersionNumber; +import org.jackhuang.hmcl.util.versioning.GameVersionNumber; import java.io.IOException; import java.io.InputStreamReader; @@ -45,7 +45,7 @@ public final class NativePatcher { public static Version patchNative(Version version, String gameVersion, JavaVersion javaVersion, VersionSetting settings) { if (settings.getNativesDirType() == NativesDirectoryType.CUSTOM) { - if (gameVersion != null && VersionNumber.compare(gameVersion, "1.19") < 0) + if (gameVersion != null && GameVersionNumber.compare(gameVersion, "1.19") < 0) return version; ArrayList newLibraries = new ArrayList<>(); @@ -66,7 +66,7 @@ public final class NativePatcher { final boolean useNativeOpenAL = settings.isUseNativeOpenAL(); if (OperatingSystem.CURRENT_OS.isLinuxOrBSD() && (useNativeGLFW || useNativeOpenAL) - && VersionNumber.compare(gameVersion, "1.19") >= 0) { + && GameVersionNumber.compare(gameVersion, "1.19") >= 0) { version = version.setLibraries(version.getLibraries().stream() .filter(library -> { @@ -88,7 +88,7 @@ public final class NativePatcher { OperatingSystem os = javaVersion.getPlatform().getOperatingSystem(); Architecture arch = javaVersion.getArchitecture(); - VersionNumber gameVersionNumber = gameVersion != null ? VersionNumber.asVersion(gameVersion) : null; + GameVersionNumber gameVersionNumber = gameVersion != null ? GameVersionNumber.asGameVersion(gameVersion) : null; if (settings.isNotPatchNatives()) return version; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeInstallTask.java index f2ab6befc..35a60f422 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeInstallTask.java @@ -24,7 +24,7 @@ import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.util.gson.JsonUtils; import org.jackhuang.hmcl.util.io.CompressingUtils; import org.jackhuang.hmcl.util.io.FileUtils; -import org.jackhuang.hmcl.util.versioning.VersionNumber; +import org.jackhuang.hmcl.util.versioning.GameVersionNumber; import java.io.IOException; import java.nio.file.FileSystem; @@ -100,7 +100,7 @@ public final class ForgeInstallTask extends Task { @Override public void execute() throws IOException, VersionMismatchException, UnsupportedInstallationException { String originalMainClass = version.resolve(dependencyManager.getGameRepository()).getMainClass(); - if (VersionNumber.compare("1.13", remote.getGameVersion()) <= 0) { + if (GameVersionNumber.compare("1.13", remote.getGameVersion()) <= 0) { // Forge 1.13 is not compatible with fabric. if (!LibraryAnalyzer.VANILLA_MAIN.equals(originalMainClass) && !LibraryAnalyzer.MOD_LAUNCHER_MAIN.equals(originalMainClass) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameVerificationFixTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameVerificationFixTask.java index e57b0fa84..22229f248 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameVerificationFixTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameVerificationFixTask.java @@ -22,7 +22,7 @@ import org.jackhuang.hmcl.download.LibraryAnalyzer; import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.util.io.CompressingUtils; -import org.jackhuang.hmcl.util.versioning.VersionNumber; +import org.jackhuang.hmcl.util.versioning.GameVersionNumber; import java.io.File; import java.io.IOException; @@ -65,7 +65,7 @@ public final class GameVerificationFixTask extends Task { File jar = dependencyManager.getGameRepository().getVersionJar(version); LibraryAnalyzer analyzer = LibraryAnalyzer.analyze(version); - if (jar.exists() && VersionNumber.compare(gameVersion, "1.6") < 0 && analyzer.has(LibraryAnalyzer.LibraryType.FORGE)) { + if (jar.exists() && GameVersionNumber.compare(gameVersion, "1.6") < 0 && analyzer.has(LibraryAnalyzer.LibraryType.FORGE)) { try (FileSystem fs = CompressingUtils.createWritableZipFileSystem(jar.toPath(), StandardCharsets.UTF_8)) { Files.deleteIfExists(fs.getPath("META-INF/MOJANG_C.DSA")); Files.deleteIfExists(fs.getPath("META-INF/MOJANG_C.SF")); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/optifine/OptiFineInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/optifine/OptiFineInstallTask.java index 20c20830b..03b7832f1 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/optifine/OptiFineInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/optifine/OptiFineInstallTask.java @@ -190,7 +190,7 @@ public final class OptiFineInstallTask extends Task { if (LibraryAnalyzer.BOOTSTRAP_LAUNCHER_MAIN.equals(originalMainClass)) { // OptiFine H1 Pre2+ is compatible with Forge 1.17 - if (buildofVer.compareTo(VersionNumber.asVersion("20210924-190833")) < 0) { + if (buildofVer.compareTo("20210924-190833") < 0) { throw new UnsupportedInstallationException(UnsupportedInstallationException.FORGE_1_17_OPTIFINE_H1_PRE2); } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/GameVersion.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/GameVersion.java index 0a7787a53..68a0f3a70 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/GameVersion.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/GameVersion.java @@ -42,7 +42,7 @@ import static org.jackhuang.hmcl.util.Logging.LOG; /** * @author huangyuhui */ -public final class GameVersion { +final class GameVersion { private GameVersion() { } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/JavaVersionConstraint.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/JavaVersionConstraint.java index c8f5a3799..754b99312 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/JavaVersionConstraint.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/JavaVersionConstraint.java @@ -22,6 +22,7 @@ import org.jackhuang.hmcl.util.Lang; import org.jackhuang.hmcl.util.platform.Architecture; import org.jackhuang.hmcl.util.platform.JavaVersion; import org.jackhuang.hmcl.util.platform.OperatingSystem; +import org.jackhuang.hmcl.util.versioning.GameVersionNumber; import org.jackhuang.hmcl.util.versioning.VersionNumber; import org.jackhuang.hmcl.util.versioning.VersionRange; import org.jetbrains.annotations.Nullable; @@ -30,48 +31,47 @@ import java.util.List; import java.util.Objects; import static org.jackhuang.hmcl.download.LibraryAnalyzer.LAUNCH_WRAPPER_MAIN; -import static org.jackhuang.hmcl.util.versioning.VersionRange.*; public enum JavaVersionConstraint { // Minecraft>=1.13 requires Java 8 - VANILLA_JAVA_8(JavaVersionConstraint.RULE_MANDATORY, atLeast("1.13"), atLeast("1.8")), + VANILLA_JAVA_8(JavaVersionConstraint.RULE_MANDATORY, GameVersionNumber.atLeast("1.13"), VersionNumber.atLeast("1.8")), // Minecraft 1.17 requires Java 16 - VANILLA_JAVA_16(JavaVersionConstraint.RULE_MANDATORY, atLeast("1.17"), atLeast("16")), + VANILLA_JAVA_16(JavaVersionConstraint.RULE_MANDATORY, GameVersionNumber.atLeast("1.17"), VersionNumber.atLeast("16")), // Minecraft>=1.18 requires Java 17 - VANILLA_JAVA_17(JavaVersionConstraint.RULE_MANDATORY, atLeast("1.18"), atLeast("17")), + VANILLA_JAVA_17(JavaVersionConstraint.RULE_MANDATORY, GameVersionNumber.atLeast("1.18"), VersionNumber.atLeast("17")), // Minecraft<=1.7.2+Forge requires Java<=7, But LegacyModFixer may fix that problem. So only suggest user using Java 7. - MODDED_JAVA_7(JavaVersionConstraint.RULE_SUGGESTED, atMost("1.7.2"), atMost("1.7.999")) { + MODDED_JAVA_7(JavaVersionConstraint.RULE_SUGGESTED, GameVersionNumber.atMost("1.7.2"), VersionNumber.atMost("1.7.999")) { @Override - protected boolean appliesToVersionImpl(VersionNumber gameVersionNumber, @Nullable Version version, + protected boolean appliesToVersionImpl(GameVersionNumber gameVersionNumber, @Nullable Version version, @Nullable JavaVersion javaVersion, @Nullable LibraryAnalyzer analyzer) { return version != null && analyzer != null && analyzer.has(LibraryAnalyzer.LibraryType.FORGE); } }, - MODDED_JAVA_8(JavaVersionConstraint.RULE_SUGGESTED, between("1.7.10", "1.16.999"), between("1.8", "1.8.999")) { + MODDED_JAVA_8(JavaVersionConstraint.RULE_SUGGESTED, GameVersionNumber.between("1.7.10", "1.16.999"), VersionNumber.between("1.8", "1.8.999")) { @Override - protected boolean appliesToVersionImpl(VersionNumber gameVersionNumber, @Nullable Version version, + protected boolean appliesToVersionImpl(GameVersionNumber gameVersionNumber, @Nullable Version version, @Nullable JavaVersion javaVersion, @Nullable LibraryAnalyzer analyzer) { return analyzer != null && analyzer.has(LibraryAnalyzer.LibraryType.FORGE); } }, - MODDED_JAVA_16(JavaVersionConstraint.RULE_SUGGESTED, between("1.17", "1.17.999"), between("16", "16.999")) { + MODDED_JAVA_16(JavaVersionConstraint.RULE_SUGGESTED, GameVersionNumber.between("1.17", "1.17.999"), VersionNumber.between("16", "16.999")) { @Override - protected boolean appliesToVersionImpl(VersionNumber gameVersionNumber, @Nullable Version version, + protected boolean appliesToVersionImpl(GameVersionNumber gameVersionNumber, @Nullable Version version, @Nullable JavaVersion javaVersion, @Nullable LibraryAnalyzer analyzer) { return analyzer != null && analyzer.has(LibraryAnalyzer.LibraryType.FORGE); } }, - MODDED_JAVA_17(JavaVersionConstraint.RULE_SUGGESTED, atLeast("1.18"), between("17", "17.999")) { + MODDED_JAVA_17(JavaVersionConstraint.RULE_SUGGESTED, GameVersionNumber.atLeast("1.18"), VersionNumber.between("17", "17.999")) { @Override - protected boolean appliesToVersionImpl(VersionNumber gameVersionNumber, @Nullable Version version, + protected boolean appliesToVersionImpl(GameVersionNumber gameVersionNumber, @Nullable Version version, @Nullable JavaVersion javaVersion, @Nullable LibraryAnalyzer analyzer) { return analyzer != null && analyzer.has(LibraryAnalyzer.LibraryType.FORGE); } }, // LaunchWrapper<=1.12 will crash because LaunchWrapper assumes the system class loader is an instance of URLClassLoader (Java 8) - LAUNCH_WRAPPER(JavaVersionConstraint.RULE_MANDATORY, atMost("1.12.999"), atMost("1.8.999")) { + LAUNCH_WRAPPER(JavaVersionConstraint.RULE_MANDATORY, GameVersionNumber.atMost("1.12.999"), VersionNumber.atMost("1.8.999")) { @Override - protected boolean appliesToVersionImpl(VersionNumber gameVersionNumber, @Nullable Version version, + protected boolean appliesToVersionImpl(GameVersionNumber gameVersionNumber, @Nullable Version version, @Nullable JavaVersion javaVersion, @Nullable LibraryAnalyzer analyzer) { if (version == null) return false; return LAUNCH_WRAPPER_MAIN.equals(version.getMainClass()) && @@ -81,15 +81,15 @@ public enum JavaVersionConstraint { } }, // Minecraft>=1.13 may crash when generating world on Java [1.8,1.8.0_51) - VANILLA_JAVA_8_51(JavaVersionConstraint.RULE_SUGGESTED, atLeast("1.13"), atLeast("1.8.0_51")), + VANILLA_JAVA_8_51(JavaVersionConstraint.RULE_SUGGESTED, GameVersionNumber.atLeast("1.13"), VersionNumber.atLeast("1.8.0_51")), // Minecraft with suggested java version recorded in game json is restrictedly constrained. GAME_JSON(JavaVersionConstraint.RULE_MANDATORY, VersionRange.all(), VersionRange.all()) { @Override - protected boolean appliesToVersionImpl(VersionNumber gameVersionNumber, @Nullable Version version, + protected boolean appliesToVersionImpl(GameVersionNumber gameVersionNumber, @Nullable Version version, @Nullable JavaVersion javaVersion, @Nullable LibraryAnalyzer analyzer) { if (version == null) return false; // We only checks for 1.7.10 and above, since 1.7.2 with Forge can only run on Java 7, but it is recorded Java 8 in game json, which is not correct. - return gameVersionNumber.compareTo(VersionNumber.asVersion("1.7.10")) >= 0 && version.getJavaVersion() != null; + return gameVersionNumber.compareTo("1.7.10") >= 0 && version.getJavaVersion() != null; } @Override @@ -100,14 +100,14 @@ public enum JavaVersionConstraint { } else { javaVersion = "1." + version.getJavaVersion().getMajorVersion(); } - return atLeast(javaVersion); + return VersionNumber.atLeast(javaVersion); } }, // On Linux, JDK 9+ cannot launch Minecraft<=1.12.2, since JDK 9+ does not accept loading native library built in different arch. // For example, JDK 9+ 64-bit cannot load 32-bit lwjgl native library. - VANILLA_LINUX_JAVA_8(JavaVersionConstraint.RULE_MANDATORY, atMost("1.12.999"), atMost("1.8.999")) { + VANILLA_LINUX_JAVA_8(JavaVersionConstraint.RULE_MANDATORY, GameVersionNumber.atMost("1.12.999"), VersionNumber.atMost("1.8.999")) { @Override - protected boolean appliesToVersionImpl(VersionNumber gameVersionNumber, @Nullable Version version, + protected boolean appliesToVersionImpl(GameVersionNumber gameVersionNumber, @Nullable Version version, @Nullable JavaVersion javaVersion, @Nullable LibraryAnalyzer analyzer) { return OperatingSystem.CURRENT_OS == OperatingSystem.LINUX && Architecture.SYSTEM_ARCH == Architecture.X86_64 @@ -115,33 +115,33 @@ public enum JavaVersionConstraint { } @Override - public boolean checkJava(VersionNumber gameVersionNumber, Version version, JavaVersion javaVersion) { + public boolean checkJava(GameVersionNumber gameVersionNumber, Version version, JavaVersion javaVersion) { return javaVersion.getArchitecture() != Architecture.X86_64 || super.checkJava(gameVersionNumber, version, javaVersion); } }, // Minecraft currently does not provide official support for architectures other than x86 and x86-64. VANILLA_X86(JavaVersionConstraint.RULE_SUGGESTED, VersionRange.all(), VersionRange.all()) { @Override - protected boolean appliesToVersionImpl(VersionNumber gameVersionNumber, @Nullable Version version, + protected boolean appliesToVersionImpl(GameVersionNumber gameVersionNumber, @Nullable Version version, @Nullable JavaVersion javaVersion, @Nullable LibraryAnalyzer analyzer) { if (javaVersion == null || javaVersion.getArchitecture() != Architecture.ARM64) return false; if (OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS || OperatingSystem.CURRENT_OS == OperatingSystem.OSX) - return gameVersionNumber.compareTo(VersionNumber.asVersion("1.6")) < 0; + return gameVersionNumber.compareTo("1.6") < 0; return false; } @Override - public boolean checkJava(VersionNumber gameVersionNumber, Version version, JavaVersion javaVersion) { + public boolean checkJava(GameVersionNumber gameVersionNumber, Version version, JavaVersion javaVersion) { return javaVersion.getArchitecture().isX86(); } }, // Minecraft 1.16+Forge with crash because JDK-8273826 - MODLAUNCHER_8(JavaVersionConstraint.RULE_SUGGESTED, between("1.16.3", "1.17.1"), VersionRange.all()) { + MODLAUNCHER_8(JavaVersionConstraint.RULE_SUGGESTED, GameVersionNumber.between("1.16.3", "1.17.1"), VersionRange.all()) { @Override - protected boolean appliesToVersionImpl(VersionNumber gameVersionNumber, @Nullable Version version, + protected boolean appliesToVersionImpl(GameVersionNumber gameVersionNumber, @Nullable Version version, @Nullable JavaVersion javaVersion, @Nullable LibraryAnalyzer analyzer) { if (version == null || javaVersion == null || analyzer == null) return false; VersionNumber forgePatchVersion = analyzer.getVersion(LibraryAnalyzer.LibraryType.FORGE) @@ -158,14 +158,14 @@ public enum JavaVersionConstraint { case "1.16.5": return forgePatchVersion.compareTo(VersionNumber.asVersion("36.2.23")) <= 0; case "1.17.1": - return between("37.0.60", "37.0.75").contains(forgePatchVersion); + return VersionNumber.between("37.0.60", "37.0.75").contains(forgePatchVersion); default: return false; } } @Override - public boolean checkJava(VersionNumber gameVersionNumber, Version version, JavaVersion javaVersion) { + public boolean checkJava(GameVersionNumber gameVersionNumber, Version version, JavaVersion javaVersion) { int parsedJavaVersion = javaVersion.getParsedVersion(); if (parsedJavaVersion > 17) { return false; @@ -181,13 +181,13 @@ public enum JavaVersionConstraint { return true; } } - };; + }; private final int type; - private final VersionRange gameVersionRange; - private final VersionRange javaVersionRange; + private final VersionRange gameVersionRange; + private final VersionRange javaVersionRange; - JavaVersionConstraint(int type, VersionRange gameVersionRange, VersionRange javaVersionRange) { + JavaVersionConstraint(int type, VersionRange gameVersionRange, VersionRange javaVersionRange) { this.type = type; this.gameVersionRange = gameVersionRange; this.javaVersionRange = javaVersionRange; @@ -197,39 +197,39 @@ public enum JavaVersionConstraint { return type; } - public VersionRange getGameVersionRange() { + public VersionRange getGameVersionRange() { return gameVersionRange; } - public VersionRange getJavaVersionRange(Version version) { + public VersionRange getJavaVersionRange(Version version) { return javaVersionRange; } - public final boolean appliesToVersion(@Nullable VersionNumber gameVersionNumber, @Nullable Version version, + public final boolean appliesToVersion(@Nullable GameVersionNumber gameVersionNumber, @Nullable Version version, @Nullable JavaVersion javaVersion, LibraryAnalyzer analyzer) { return gameVersionRange.contains(gameVersionNumber) && appliesToVersionImpl(gameVersionNumber, version, javaVersion, analyzer); } - protected boolean appliesToVersionImpl(VersionNumber gameVersionNumber, @Nullable Version version, + protected boolean appliesToVersionImpl(GameVersionNumber gameVersionNumber, @Nullable Version version, @Nullable JavaVersion javaVersion, @Nullable LibraryAnalyzer analyzer) { return true; } @SuppressWarnings("BooleanMethodIsAlwaysInverted") - public boolean checkJava(VersionNumber gameVersionNumber, Version version, JavaVersion javaVersion) { + public boolean checkJava(GameVersionNumber gameVersionNumber, Version version, JavaVersion javaVersion) { return getJavaVersionRange(version).contains(javaVersion.getVersionNumber()); } public static final List ALL = Lang.immutableListOf(values()); - public static VersionRanges findSuitableJavaVersionRange(VersionNumber gameVersion, Version version) { - VersionRange mandatoryJavaRange = VersionRange.all(); - VersionRange suggestedJavaRange = VersionRange.all(); + public static VersionRanges findSuitableJavaVersionRange(GameVersionNumber gameVersion, Version version) { + VersionRange mandatoryJavaRange = VersionRange.all(); + VersionRange suggestedJavaRange = VersionRange.all(); LibraryAnalyzer analyzer = version != null ? LibraryAnalyzer.analyze(version) : null; for (JavaVersionConstraint java : ALL) { if (java.appliesToVersion(gameVersion, version, null, analyzer)) { - VersionRange javaVersionRange = java.getJavaVersionRange(version); + VersionRange javaVersionRange = java.getJavaVersionRange(version); if (java.type == RULE_MANDATORY) { mandatoryJavaRange = mandatoryJavaRange.intersectionWith(javaVersionRange); suggestedJavaRange = suggestedJavaRange.intersectionWith(javaVersionRange); @@ -242,12 +242,12 @@ public enum JavaVersionConstraint { } @Nullable - public static JavaVersion findSuitableJavaVersion(VersionNumber gameVersion, Version version) throws InterruptedException { + public static JavaVersion findSuitableJavaVersion(GameVersionNumber gameVersion, Version version) throws InterruptedException { VersionRanges range = findSuitableJavaVersionRange(gameVersion, version); boolean forceX86 = Architecture.SYSTEM_ARCH == Architecture.ARM64 && (OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS || OperatingSystem.CURRENT_OS == OperatingSystem.OSX) - && gameVersion.compareTo(VersionNumber.asVersion("1.6")) < 0; + && gameVersion.compareTo("1.6") < 0; JavaVersion mandatory = null; JavaVersion suggested = null; @@ -298,19 +298,19 @@ public enum JavaVersionConstraint { public static final int RULE_SUGGESTED = 2; public static final class VersionRanges { - private final VersionRange mandatory; - private final VersionRange suggested; + private final VersionRange mandatory; + private final VersionRange suggested; - public VersionRanges(VersionRange mandatory, VersionRange suggested) { + public VersionRanges(VersionRange mandatory, VersionRange suggested) { this.mandatory = mandatory; this.suggested = suggested; } - public VersionRange getMandatory() { + public VersionRange getMandatory() { return mandatory; } - public VersionRange getSuggested() { + public VersionRange getSuggested() { return suggested; } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java index 39869b100..0c692f355 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java @@ -28,7 +28,7 @@ import org.jackhuang.hmcl.util.io.IOUtils; import org.jackhuang.hmcl.util.io.Unzipper; import org.jackhuang.hmcl.util.platform.Bits; import org.jackhuang.hmcl.util.platform.*; -import org.jackhuang.hmcl.util.versioning.VersionNumber; +import org.jackhuang.hmcl.util.versioning.GameVersionNumber; import java.io.*; import java.net.InetSocketAddress; @@ -230,7 +230,7 @@ public class DefaultLauncher extends Launcher { Path tempNativeFolder = null; if ((OperatingSystem.CURRENT_OS == OperatingSystem.LINUX || OperatingSystem.CURRENT_OS == OperatingSystem.OSX) && !StringUtils.isASCII(nativeFolderPath) - && gameVersion.isPresent() && VersionNumber.compare(gameVersion.get(), "1.19") < 0) { + && gameVersion.isPresent() && GameVersionNumber.compare(gameVersion.get(), "1.19") < 0) { tempNativeFolder = Paths.get("/", "tmp", "hmcl-natives-" + UUID.randomUUID()); nativeFolderPath = tempNativeFolder + File.pathSeparator + nativeFolderPath; } @@ -259,7 +259,7 @@ public class DefaultLauncher extends Launcher { if (StringUtils.isNotBlank(options.getServerIp())) { String[] args = options.getServerIp().split(":"); - if (VersionNumber.compare(gameVersion.orElse("0.0"), "1.20") < 0) { + if (GameVersionNumber.asGameVersion(gameVersion).compareTo("1.20") < 0) { res.add("--server"); res.add(args[0]); res.add("--port"); @@ -357,7 +357,7 @@ public class DefaultLauncher extends Launcher { } private boolean isUsingLog4j() { - return VersionNumber.compare(repository.getGameVersion(version).orElse("1.7"), "1.7") >= 0; + return GameVersionNumber.compare(repository.getGameVersion(version).orElse("1.7"), "1.7") >= 0; } public File getLog4jConfigurationFile() { @@ -367,7 +367,7 @@ public class DefaultLauncher extends Launcher { public void extractLog4jConfigurationFile() throws IOException { File targetFile = getLog4jConfigurationFile(); InputStream source; - if (VersionNumber.compare(repository.getGameVersion(version).orElse("0.0"), "1.12") < 0) { + if (GameVersionNumber.asGameVersion(repository.getGameVersion(version)).compareTo("1.12") < 0) { source = DefaultLauncher.class.getResourceAsStream("/assets/game/log4j2-1.7.xml"); } else { source = DefaultLauncher.class.getResourceAsStream("/assets/game/log4j2-1.12.xml"); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/RemoteModRepository.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/RemoteModRepository.java index a45f8618a..3dc48fde3 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/RemoteModRepository.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/RemoteModRepository.java @@ -119,28 +119,4 @@ public interface RemoteModRepository { return subcategories; } } - - String[] DEFAULT_GAME_VERSIONS = new String[]{ - "1.20.4", "1.20.3", "1.20.2", "1.20.1", "1.20", - "1.19.4", "1.19.3", "1.19.2", "1.19.1", "1.19", - "1.18.2", "1.18.1", "1.18", - "1.17.1", "1.17", - "1.16.5", "1.16.4", "1.16.3", "1.16.2", "1.16.1", "1.16", - "1.15.2", "1.15.1", "1.15", - "1.14.4", "1.14.3", "1.14.2", "1.14.1", "1.14", - "1.13.2", "1.13.1", "1.13", - "1.12.2", "1.12.1", "1.12", - "1.11.2", "1.11.1", "1.11", - "1.10.2", "1.10.1", "1.10", - "1.9.4", "1.9.3", "1.9.2", "1.9.1", "1.9", - "1.8.9", "1.8.8", "1.8.7", "1.8.6", "1.8.5", "1.8.4", "1.8.3", "1.8.2", "1.8.1", "1.8", - "1.7.10", "1.7.9", "1.7.8", "1.7.7", "1.7.6", "1.7.5", "1.7.4", "1.7.3", "1.7.2", - "1.6.4", "1.6.2", "1.6.1", - "1.5.2", "1.5.1", - "1.4.7", "1.4.6", "1.4.5", "1.4.4", "1.4.2", - "1.3.2", "1.3.1", - "1.2.5", "1.2.4", "1.2.3", "1.2.2", "1.2.1", - "1.1", - "1.0" - }; } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/versioning/GameVersionNumber.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/versioning/GameVersionNumber.java new file mode 100644 index 000000000..65564db57 --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/versioning/GameVersionNumber.java @@ -0,0 +1,616 @@ +package org.jackhuang.hmcl.util.versioning; + +import org.jetbrains.annotations.NotNull; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public abstract class GameVersionNumber implements Comparable { + + public static String[] getDefaultGameVersions() { + return Versions.DEFAULT_GAME_VERSIONS; + } + + public static GameVersionNumber asGameVersion(String version) { + try { + if (!version.isEmpty()) { + char ch = version.charAt(0); + switch (ch) { + case 'r': + return Old.parsePreClassic(version); + case 'a': + case 'b': + case 'c': + return Old.parseAlphaBetaClassic(version); + case 'i': + return Old.parseInfdev(version); + } + + if (version.equals("0.0")) { + return Release.ZERO; + } + + if (version.startsWith("1.")) { + return Release.parse(version); + } + + if (version.length() == 6 && version.charAt(2) == 'w') { + return Snapshot.parse(version); + } + } + } catch (IllegalArgumentException ignore) { + } + + Special special = Versions.SPECIALS.get(version); + if (special == null) { + special = new Special(version); + } + return special; + } + + public static GameVersionNumber asGameVersion(Optional version) { + return version.isPresent() ? asGameVersion(version.get()) : unknown(); + } + + public static GameVersionNumber unknown() { + return Release.ZERO; + } + + public static int compare(String version1, String version2) { + return asGameVersion(version1).compareTo(asGameVersion(version2)); + } + + public static VersionRange between(String minimum, String maximum) { + return VersionRange.between(asGameVersion(minimum), asGameVersion(maximum)); + } + + public static VersionRange atLeast(String minimum) { + return VersionRange.atLeast(asGameVersion(minimum)); + } + + public static VersionRange atMost(String maximum) { + return VersionRange.atMost(asGameVersion(maximum)); + } + + final String value; + + GameVersionNumber(String value) { + this.value = value; + } + + enum Type { + PRE_CLASSIC, CLASSIC, INFDEV, ALPHA, BETA, NEW + } + + abstract Type getType(); + + abstract int compareToImpl(@NotNull GameVersionNumber other); + + public int compareTo(@NotNull String other) { + return this.compareTo(asGameVersion(other)); + } + + @Override + public int compareTo(@NotNull GameVersionNumber other) { + if (this.getType() != other.getType()) { + return Integer.compare(this.getType().ordinal(), other.getType().ordinal()); + } + + return compareToImpl(other); + } + + @Override + public String toString() { + return value; + } + + static final class Old extends GameVersionNumber { + + private static final Pattern PATTERN = Pattern.compile("[abc](?[0-9]+)\\.(?[0-9]+)(\\.(?[0-9]+))?([^0-9]*(?[0-9]+).*)?"); + + static Old parsePreClassic(String value) { + int version; + try { + version = Integer.parseInt(value.substring("rd-".length())); + } catch (NumberFormatException e) { + throw new IllegalArgumentException(e); + } + return new Old(value, Type.PRE_CLASSIC, version, 0, 0, 0); + } + + static Old parseAlphaBetaClassic(String value) { + Matcher matcher = PATTERN.matcher(value); + if (!matcher.matches()) { + throw new IllegalArgumentException(value); + } + + Type type; + switch (value.charAt(0)) { + case 'a': + type = Type.ALPHA; + break; + case 'b': + type = Type.BETA; + break; + case 'c': + type = Type.CLASSIC; + break; + default: + throw new AssertionError(value); + } + + int major = Integer.parseInt(matcher.group("major")); + int minor = Integer.parseInt(matcher.group("minor")); + + String patchString = matcher.group("patch"); + int patch = patchString != null ? Integer.parseInt(patchString) : 0; + + String additionalString = matcher.group("additional"); + int additional = additionalString != null ? Integer.parseInt(additionalString) : 0; + + return new Old(value, type, major, minor, patch, additional); + } + + static Old parseInfdev(String value) { + String version = value.substring("inf-".length()); + int major; + int patch; + + try { + major = Integer.parseInt(version); + patch = 0; + } catch (NumberFormatException e) { + int idx = version.indexOf('-'); + if (idx >= 0) { + try { + major = Integer.parseInt(version.substring(0, idx)); + patch = Integer.parseInt(version.substring(idx + 1)); + } catch (NumberFormatException ignore) { + throw new IllegalArgumentException(value); + } + } else { + throw new IllegalArgumentException(value); + } + } + + return new Old(value, Type.INFDEV, major, 0, patch, 0); + } + + + final Type type; + final int major; + final int minor; + final int patch; + final int additional; + + private Old(String value, Type type, int major, int minor, int patch, int additional) { + super(value); + this.type = type; + this.major = major; + this.minor = minor; + this.patch = patch; + this.additional = additional; + } + + @Override + Type getType() { + return type; + } + + @Override + int compareToImpl(@NotNull GameVersionNumber other) { + Old that = (Old) other; + int c = Integer.compare(this.major, that.major); + if (c != 0) { + return c; + } + + c = Integer.compare(this.minor, that.minor); + if (c != 0) { + return c; + } + + c = Integer.compare(this.patch, that.patch); + if (c != 0) { + return c; + } + + return Integer.compare(this.additional, that.additional); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Old other = (Old) o; + return major == other.major && minor == other.minor && patch == other.patch && additional == other.additional && type == other.type; + } + + @Override + public int hashCode() { + return Objects.hash(type, major, minor, patch, additional); + } + } + + static final class Release extends GameVersionNumber { + + private static final Pattern PATTERN = Pattern.compile("1\\.(?[0-9]+)(\\.(?[0-9]+))?((?(-[a-zA-Z]+| Pre-Release ))(?[0-9]+))?"); + + static final int TYPE_GA = Integer.MAX_VALUE; + + static final int TYPE_UNKNOWN = 0; + static final int TYPE_EXP = 1; + static final int TYPE_PRE = 2; + static final int TYPE_RC = 3; + + static final Release ZERO = new Release("0.0", 0, 0, 0, TYPE_GA, 0); + + static Release parse(String value) { + Matcher matcher = PATTERN.matcher(value); + if (!matcher.matches()) { + throw new IllegalArgumentException(value); + } + + int minor = Integer.parseInt(matcher.group("minor")); + + String patchString = matcher.group("patch"); + int patch = patchString != null ? Integer.parseInt(patchString) : 0; + + String eaTypeString = matcher.group("eaType"); + int eaType; + if (eaTypeString == null) { + eaType = TYPE_GA; + } else if ("-pre".equals(eaTypeString) || " Pre-Release ".equals(eaTypeString)) { + eaType = TYPE_PRE; + } else if ("-rc".equals(eaTypeString)) { + eaType = TYPE_RC; + } else if ("-exp".equals(eaTypeString)) { + eaType = TYPE_EXP; + } else { + eaType = TYPE_UNKNOWN; + } + + String eaVersionString = matcher.group("eaVersion"); + int eaVersion = eaVersionString == null ? 0 : Integer.parseInt(eaVersionString); + + return new Release(value, 1, minor, patch, eaType, eaVersion); + } + + private final int major; + private final int minor; + private final int patch; + + private final int eaType; + private final int eaVersion; + + Release(String value, int major, int minor, int patch, int eaType, int eaVersion) { + super(value); + this.major = major; + this.minor = minor; + this.patch = patch; + this.eaType = eaType; + this.eaVersion = eaVersion; + } + + @Override + Type getType() { + return Type.NEW; + } + + int compareToRelease(Release other) { + int c = Integer.compare(this.major, other.major); + if (c != 0) { + return c; + } + + c = Integer.compare(this.minor, other.minor); + if (c != 0) { + return c; + } + + c = Integer.compare(this.patch, other.patch); + if (c != 0) { + return c; + } + + c = Integer.compare(this.eaType, other.eaType); + if (c != 0) { + return c; + } + + return Integer.compare(this.eaVersion, other.eaVersion); + } + + int compareToSnapshot(Snapshot other) { + int idx = Arrays.binarySearch(Versions.SNAPSHOT_INTS, other.intValue); + if (idx >= 0) { + return this.compareToRelease(Versions.SNAPSHOT_PREV[idx]) <= 0 ? -1 : 1; + } + + idx = -(idx + 1); + if (idx == Versions.SNAPSHOT_INTS.length) { + return -1; + } + + return this.compareToRelease(Versions.SNAPSHOT_PREV[idx]) <= 0 ? -1 : 1; + } + + @Override + int compareToImpl(@NotNull GameVersionNumber other) { + if (other instanceof Release) { + return compareToRelease((Release) other); + } + + if (other instanceof Snapshot) { + return compareToSnapshot((Snapshot) other); + } + + if (other instanceof Special) { + return -((Special) other).compareToReleaseOrSnapshot(this); + } + + throw new AssertionError(other.getClass()); + } + + @Override + public int hashCode() { + return Objects.hash(major, minor, patch, eaType, eaVersion); + } + + @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 == other.eaVersion; + } + } + + static final class Snapshot extends GameVersionNumber { + static Snapshot parse(String value) { + if (value.length() != 6 || value.charAt(2) != 'w') { + throw new IllegalArgumentException(value); + } + + int year; + int week; + try { + year = Integer.parseInt(value.substring(0, 2)); + week = Integer.parseInt(value.substring(3, 5)); + } catch (NumberFormatException e) { + throw new IllegalArgumentException(value); + } + + char suffix = value.charAt(5); + if ((suffix < 'a' || suffix > 'z') && suffix != '~') { + throw new IllegalArgumentException(value); + } + + return new Snapshot(value, year, week, suffix); + } + + static int toInt(int year, int week, char suffix) { + return (year << 16) | (week << 8) | suffix; + } + + final int intValue; + + Snapshot(String value, int year, int week, char suffix) { + super(value); + this.intValue = toInt(year, week, suffix); + } + + @Override + Type getType() { + return Type.NEW; + } + + @Override + int compareToImpl(@NotNull GameVersionNumber other) { + if (other instanceof Release) { + return -((Release) other).compareToSnapshot(this); + } + + if (other instanceof Snapshot) { + return Integer.compare(this.intValue, ((Snapshot) other).intValue); + } + + if (other instanceof Special) { + return -((Special) other).compareToReleaseOrSnapshot(this); + } + + throw new AssertionError(other.getClass()); + } + + @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; + } + + @Override + public int hashCode() { + return intValue; + } + } + + static final class Special extends GameVersionNumber { + private VersionNumber versionNumber; + + private GameVersionNumber prev; + + Special(String value) { + super(value); + } + + @Override + Type getType() { + return Type.NEW; + } + + boolean isUnknown() { + return prev == null; + } + + VersionNumber asVersionNumber() { + if (versionNumber != null) { + return versionNumber; + } + + return versionNumber = VersionNumber.asVersion(value); + } + + GameVersionNumber getPrevNormalVersion() { + GameVersionNumber v = prev; + while (v instanceof Special) { + v = ((Special) v).prev; + } + + if (v == null) { + throw new AssertionError("version: " + value); + } + + return v; + } + + int compareToReleaseOrSnapshot(GameVersionNumber other) { + if (isUnknown()) { + return 1; + } + + if (getPrevNormalVersion().compareTo(other) >= 0) { + return 1; + } + + return -1; + } + + int compareToSpecial(Special other) { + if (this.isUnknown()) { + return other.isUnknown() ? this.asVersionNumber().compareTo(other.asVersionNumber()) : 1; + } + + if (other.isUnknown()) { + return -1; + } + + if (this.value.equals(other.value)) { + return 0; + } + + int c = this.getPrevNormalVersion().compareTo(other.getPrevNormalVersion()); + if (c != 0) { + return c; + } + + GameVersionNumber v = prev; + while (v instanceof Special) { + if (v == other) { + return 1; + } + + v = ((Special) v).prev; + } + + return -1; + } + + @Override + int compareToImpl(@NotNull GameVersionNumber o) { + if (o instanceof Release) { + return compareToReleaseOrSnapshot(o); + } + + if (o instanceof Snapshot) { + return compareToReleaseOrSnapshot(o); + } + + if (o instanceof Special) { + return compareToSpecial((Special) o); + } + + throw new AssertionError(o.getClass()); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + @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); + } + } + + static final class Versions { + static final HashMap SPECIALS = new HashMap<>(); + static final String[] DEFAULT_GAME_VERSIONS; + + static final int[] SNAPSHOT_INTS; + static final Release[] SNAPSHOT_PREV; + + static { + ArrayDeque defaultGameVersions = new ArrayDeque<>(64); + + List snapshots = new ArrayList<>(1024); + List snapshotPrev = new ArrayList<>(1024); + + // Convert it to dynamic resource after the website is repaired? + try (BufferedReader reader = new BufferedReader(new InputStreamReader(GameVersionNumber.class.getResourceAsStream("/assets/game/versions.txt"), StandardCharsets.US_ASCII))) { + Release currentRelease = null; + GameVersionNumber prev = null; + + for (String line; (line = reader.readLine()) != null; ) { + if (line.isEmpty()) + continue; + + GameVersionNumber version = GameVersionNumber.asGameVersion(line); + + if (currentRelease == null) + currentRelease = (Release) version; + + if (version instanceof Snapshot) { + Snapshot snapshot = (Snapshot) version; + snapshots.add(snapshot); + snapshotPrev.add(currentRelease); + } else if (version instanceof Release) { + currentRelease = (Release) version; + + if (currentRelease.eaType == Release.TYPE_GA) { + defaultGameVersions.addFirst(currentRelease.value); + } + } else if (version instanceof Special) { + Special special = (Special) version; + special.prev = prev; + SPECIALS.put(special.value, special); + } else + throw new AssertionError("version: " + version); + + prev = version; + } + } catch (IOException e) { + throw new AssertionError(e); + } + + DEFAULT_GAME_VERSIONS = defaultGameVersions.toArray(new String[0]); + + SNAPSHOT_INTS = new int[snapshots.size()]; + for (int i = 0; i < snapshots.size(); i++) { + SNAPSHOT_INTS[i] = snapshots.get(i).intValue; + } + + SNAPSHOT_PREV = snapshotPrev.toArray(new Release[SNAPSHOT_INTS.length]); + } + } +} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/versioning/VersionNumber.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/versioning/VersionNumber.java index 164602fba..034412550 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/versioning/VersionNumber.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/versioning/VersionNumber.java @@ -83,6 +83,18 @@ public final class VersionNumber implements Comparable { return true; } + public static VersionRange between(String minimum, String maximum) { + return VersionRange.between(asVersion(minimum), asVersion(maximum)); + } + + public static VersionRange atLeast(String minimum) { + return VersionRange.atLeast(asVersion(minimum)); + } + + public static VersionRange atMost(String maximum) { + return VersionRange.atMost(asVersion(maximum)); + } + private interface Item { int LONG_ITEM = 0; int BIGINTEGER_ITEM = 1; @@ -475,14 +487,6 @@ public final class VersionNumber implements Comparable { return canonical; } - public VersionNumber min(VersionNumber that) { - return this.compareTo(that) <= 0 ? this : that; - } - - public VersionNumber max(VersionNumber that) { - return this.compareTo(that) >= 0 ? this : that; - } - @Override public boolean equals(Object o) { return o instanceof VersionNumber && canonical.equals(((VersionNumber) o).canonical); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/versioning/VersionRange.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/versioning/VersionRange.java index c8b628724..c0d6cd191 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/versioning/VersionRange.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/versioning/VersionRange.java @@ -2,58 +2,50 @@ package org.jackhuang.hmcl.util.versioning; import java.util.Objects; -public final class VersionRange { - private static final VersionRange EMPTY = new VersionRange(null, null); - private static final VersionRange ALL = new VersionRange(null, null); +/** + * @author Glavo + */ +@SuppressWarnings("unchecked") +public final class VersionRange> { + private static final VersionRange EMPTY = new VersionRange<>(null, null); + private static final VersionRange ALL = new VersionRange<>(null, null); - public static VersionRange empty() { - return EMPTY; + public static > VersionRange empty() { + return (VersionRange) EMPTY; } - public static VersionRange all() { - return ALL; + public static > VersionRange all() { + return (VersionRange) ALL; } - public static VersionRange between(String minimum, String maximum) { - return between(VersionNumber.asVersion(minimum), VersionNumber.asVersion(maximum)); - } - - public static VersionRange between(VersionNumber minimum, VersionNumber maximum) { + public static > VersionRange between(T minimum, T maximum) { assert minimum.compareTo(maximum) <= 0; - return new VersionRange(minimum, maximum); + return new VersionRange<>(minimum, maximum); } - public static VersionRange atLeast(String minimum) { - return atLeast(VersionNumber.asVersion(minimum)); - } - - public static VersionRange atLeast(VersionNumber minimum) { + public static > VersionRange atLeast(T minimum) { assert minimum != null; - return new VersionRange(minimum, null); + return new VersionRange<>(minimum, null); } - public static VersionRange atMost(String maximum) { - return atMost(VersionNumber.asVersion(maximum)); - } - - public static VersionRange atMost(VersionNumber maximum) { + public static > VersionRange atMost(T maximum) { assert maximum != null; - return new VersionRange(null, maximum); + return new VersionRange<>(null, maximum); } - private final VersionNumber minimum; - private final VersionNumber maximum; + private final T minimum; + private final T maximum; - private VersionRange(VersionNumber minimum, VersionNumber maximum) { + private VersionRange(T minimum, T maximum) { this.minimum = minimum; this.maximum = maximum; } - public VersionNumber getMinimum() { + public T getMinimum() { return minimum; } - public VersionNumber getMaximum() { + public T getMaximum() { return maximum; } @@ -65,12 +57,7 @@ public final class VersionRange { return !isEmpty() && minimum == null && maximum == null; } - public boolean contains(String versionNumber) { - if (versionNumber == null) return false; - return contains(VersionNumber.asVersion(versionNumber)); - } - - public boolean contains(VersionNumber versionNumber) { + public boolean contains(T versionNumber) { if (versionNumber == null) return false; if (isEmpty()) return false; if (isAll()) return true; @@ -78,7 +65,7 @@ public final class VersionRange { return (minimum == null || minimum.compareTo(versionNumber) <= 0) && (maximum == null || maximum.compareTo(versionNumber) >= 0); } - public boolean isOverlappedBy(final VersionRange that) { + public boolean isOverlappedBy(final VersionRange that) { if (this.isEmpty() || that.isEmpty()) return false; @@ -94,32 +81,32 @@ public final class VersionRange { return that.contains(minimum) || that.contains(maximum) || (that.minimum != null && contains(that.minimum)); } - public VersionRange intersectionWith(VersionRange that) { + public VersionRange intersectionWith(VersionRange that) { if (this.isAll()) return that; if (that.isAll()) return this; if (!isOverlappedBy(that)) - return EMPTY; + return empty(); - VersionNumber newMinimum; + T newMinimum; if (this.minimum == null) newMinimum = that.minimum; else if (that.minimum == null) newMinimum = this.minimum; else - newMinimum = this.minimum.max(that.minimum); + newMinimum = this.minimum.compareTo(that.minimum) >= 0 ? this.minimum : that.minimum; - VersionNumber newMaximum; + T newMaximum; if (this.maximum == null) newMaximum = that.maximum; else if (that.maximum == null) newMaximum = this.maximum; else - newMaximum = this.maximum.min(that.maximum); + newMaximum = this.maximum.compareTo(that.maximum) <= 0 ? this.maximum : that.maximum; - return new VersionRange(newMinimum, newMaximum); + return new VersionRange<>(newMinimum, newMaximum); } @Override @@ -139,7 +126,7 @@ public final class VersionRange { if (!(obj instanceof VersionRange)) return false; - VersionRange that = (VersionRange) obj; + VersionRange that = (VersionRange) obj; return this.isEmpty() == that.isEmpty() && this.isAll() == that.isAll() && Objects.equals(this.minimum, that.minimum) diff --git a/HMCLCore/src/main/resources/assets/game/versions.txt b/HMCLCore/src/main/resources/assets/game/versions.txt new file mode 100644 index 000000000..273408a1a --- /dev/null +++ b/HMCLCore/src/main/resources/assets/game/versions.txt @@ -0,0 +1,738 @@ +1.0 +11w47a +11w48a +11w49a +11w50a +12w01a +1.1 +12w03a +12w04a +12w05a +12w05b +12w06a +12w07a +12w07b +12w08a +1.2 +1.2.1 +1.2.2 +1.2.3 +1.2.4 +1.2.5 +12w15a +12w16a +12w17a +12w18a +12w19a +12w21a +12w21b +12w22a +12w23a +12w23b +12w24a +12w25a +12w26a +12w27a +12w30a +12w30b +12w30c +12w30d +12w30e +1.3 +1.3.1 +1.3.2 +12w32a +12w34a +12w34b +12w36a +12w37a +12w38a +12w38b +12w39a +12w39b +12w40a +12w40b +12w41a +12w41b +12w42a +12w42b +1.4 +1.4.1 +1.4.2 +1.4.3 +1.4.4 +12w49a +12w50a +12w50b +1.4.5 +1.4.6 +1.4.7 +13w01a +13w01b +13w02a +13w02b +13w03a +13w04a +13w05a +13w05b +13w06a +13w07a +13w09a +13w09b +13w09c +13w10a +13w10b +1.5 +13w11a +13w12~ +1.5.1 +2.0 +1.5.2 +13w16a +13w16b +13w17a +13w18a +13w18b +13w18c +13w19a +13w21a +13w21b +13w22a +13w23a +13w23b +13w24a +13w24b +13w25a +13w25b +13w25c +13w26a +1.6 +1.6.1 +1.6.2 +1.6.3 +1.6.4 +13w36a +13w36b +13w37a +13w37b +13w38a +13w38b +13w38c +13w39a +13w39b +13w41a +13w41b +13w42a +13w42b +13w43a +1.7 +1.7.1 +1.7.2 +13w47a +13w47b +13w47c +13w47d +13w47e +13w48a +13w48b +13w49a +1.7.3 +1.7.4 +1.7.5 +1.7.6-pre1 +1.7.6-pre2 +1.7.6 +1.7.7 +1.7.8 +1.7.9 +1.7.10-pre1 +1.7.10-pre2 +1.7.10-pre3 +1.7.10-pre4 +1.7.10 +14w02a +14w02b +14w02c +14w03a +14w03b +14w04a +14w04b +14w05a +14w05b +14w06a +14w06b +14w07a +14w08a +14w10a +14w10b +14w10c +14w11a +14w11b +14w17a +14w18a +14w18b +14w19a +14w20a +14w20b +14w21a +14w21b +14w25a +14w25b +14w26a +14w26b +14w26c +14w27a +14w27b +14w28a +14w28b +14w29a +14w29b +14w30a +14w30b +14w30c +14w31a +14w32a +14w32b +14w32c +14w32d +14w33a +14w33b +14w33c +14w34a +14w34b +14w34c +14w34d +1.8-pre1 +1.8-pre2 +1.8-pre3 +1.8 +1.8.1-pre1 +1.8.1-pre2 +1.8.1-pre3 +1.8.1-pre4 +1.8.1-pre5 +1.8.1 +1.8.2-pre1 +1.8.2-pre2 +1.8.2-pre3 +1.8.2-pre4 +1.8.2-pre5 +1.8.2-pre6 +1.8.2-pre7 +1.8.2 +1.8.3 +15w14a +1.8.4 +1.8.5 +1.8.6 +1.8.7 +1.8.8 +1.8.9 +15w31a +15w31b +15w31c +15w32a +15w32b +15w32c +15w33a +15w33b +15w33c +15w34a +15w34b +15w34c +15w34d +15w35a +15w35b +15w35c +15w35d +15w35e +15w36a +15w36b +15w36c +15w36d +15w37a +15w38a +15w38b +15w39a +15w39b +15w39c +15w40a +15w40b +15w41a +15w41b +15w42a +15w43a +15w43b +15w43c +15w44a +15w44b +15w45a +15w46a +15w47a +15w47b +15w47c +15w49a +15w49b +15w50a +15w51a +15w51b +16w02a +16w03a +16w04a +16w05a +16w05b +16w06a +16w07a +16w07b +1.9-pre1 +1.9-pre2 +1.9-pre3 +1.9-pre4 +1.9 +1.9.1-pre1 +1.9.1-pre2 +1.9.1-pre3 +1.9.1 +1.9.2 +1.RV-Pre1 +16w14a +16w15a +16w15b +1.9.3-pre1 +1.9.3-pre2 +1.9.3-pre3 +1.9.3 +1.9.4 +16w20a +16w21a +16w21b +1.10-pre1 +1.10-pre2 +1.10 +1.10.1 +1.10.2 +16w32a +16w32b +16w33a +16w35a +16w36a +16w38a +16w39a +16w39b +16w39c +16w40a +16w41a +16w42a +16w43a +16w44a +1.11-pre1 +1.11 +16w50a +1.11.1 +1.11.2 +17w06a +17w13a +17w13b +17w14a +17w15a +17w16a +17w16b +17w17a +17w17b +17w18a +17w18b +1.12-pre1 +1.12-pre2 +1.12-pre3 +1.12-pre4 +1.12-pre5 +1.12-pre6 +1.12-pre7 +1.12 +17w31a +1.12.1-pre1 +1.12.1 +1.12.2-pre1 +1.12.2-pre2 +1.12.2 +17w43a +17w43b +17w45a +17w45b +17w46a +17w47a +17w47b +17w48a +17w49a +17w49b +17w50a +18w01a +18w02a +18w03a +18w03b +18w05a +18w06a +18w07a +18w07b +18w07c +18w08a +18w08b +18w09a +18w10a +18w10b +18w10c +18w10d +18w11a +18w14a +18w14b +18w15a +18w16a +18w19a +18w19b +18w20a +18w20b +18w20c +18w21a +18w21b +18w22a +18w22b +18w22c +1.13-pre1 +1.13-pre2 +1.13-pre3 +1.13-pre4 +1.13-pre5 +1.13-pre6 +1.13-pre7 +1.13-pre8 +1.13-pre9 +1.13-pre10 +1.13 +18w30a +18w30b +18w31a +18w32a +18w33a +1.13.1-pre1 +1.13.1-pre2 +1.13.1 +1.13.2-pre1 +1.13.2-pre2 +1.13.2 +18w43a +18w43b +18w43c +18w44a +18w45a +18w46a +18w47a +18w47b +18w48a +18w48b +18w49a +18w50a +19w02a +19w03a +19w03b +19w03c +19w04a +19w04b +19w05a +19w06a +19w07a +19w08a +19w08b +19w09a +19w11a +19w11b +19w12a +19w12b +19w13a +19w13b +3D Shareware v1.34 +19w14a +19w14b +1.14 Pre-Release 1 +1.14 Pre-Release 2 +1.14 Pre-Release 3 +1.14 Pre-Release 4 +1.14 Pre-Release 5 +1.14 +1.14.1 Pre-Release 1 +1.14.1 Pre-Release 2 +1.14.1 +1.14.2 Pre-Release 1 +1.14.2 Pre-Release 2 +1.14.2 Pre-Release 3 +1.14.2 Pre-Release 4 +1.14.2 +1.14.3-pre1 +1.14.3-pre2 +1.14.3-pre3 +1.14.3-pre4 +1.14.3 +1.14.4-pre1 +1.14.4-pre2 +1.14.4-pre3 +1.14.4-pre4 +1.14.4-pre5 +1.14.4-pre6 +1.14.4-pre7 +1.14.4 +19w34a +19w35a +19w36a +19w37a +19w38a +19w38b +19w39a +19w40a +19w41a +19w42a +19w44a +19w45a +19w45b +19w46a +19w46b +1.15-pre1 +1.15-pre2 +1.15-pre3 +1.15-pre4 +1.15-pre5 +1.15-pre6 +1.15-pre7 +1.15 +1.15.1-pre1 +1.15.1 +1.15.2-pre1 +1.15.2-pre2 +1.15.2 +20w06a +20w07a +20w08a +20w09a +20w10a +20w11a +20w12a +20w13a +20w13b +20w14infinite +20w14a +20w15a +20w16a +20w17a +20w18a +20w19a +20w20a +20w20b +20w21a +20w22a +1.16-pre1 +1.16-pre2 +1.16-pre3 +1.16-pre4 +1.16-pre5 +1.16-pre6 +1.16-pre7 +1.16-pre8 +1.16-rc1 +1.16 +1.16.1 +20w27a +20w28a +20w29a +20w30a +1.16.2-pre1 +1.16.2-pre2 +1.16.2-pre3 +1.16.2-rc1 +1.16.2-rc2 +1.16.2 +1.16.3-rc1 +1.16.3 +1.16.4-pre1 +1.16.4-pre2 +1.16.4-rc1 +1.16.4 +1.16.5-rc1 +1.16.5 +20w45a +20w46a +20w48a +20w49a +20w51a +21w03a +21w05a +21w05b +21w06a +21w07a +21w08a +21w08b +21w10a +21w11a +21w13a +21w14a +21w15a +21w16a +21w17a +21w18a +21w19a +21w20a +1.17-pre1 +1.17-pre2 +1.17-pre3 +1.17-pre4 +1.17-pre5 +1.17-rc1 +1.17-rc2 +1.17 +1.17.1-pre1 +1.17.1-pre2 +1.17.1-pre3 +1.17.1-rc1 +1.17.1-rc2 +1.17.1 +21w37a +21w38a +21w39a +21w40a +21w41a +21w42a +21w43a +21w44a +1.18-pre1 +1.18-pre2 +1.18-pre3 +1.18-pre4 +1.18-pre5 +1.18-pre6 +1.18-pre7 +1.18-pre8 +1.18-rc1 +1.18-rc2 +1.18-rc3 +1.18-rc4 +1.18 +1.18.1-pre1 +1.18.1-rc1 +1.18.1-rc2 +1.18.1-rc3 +1.18.1 +22w03a +22w05a +22w06a +22w07a +1.18.2-pre1 +1.18.2-pre2 +1.18.2-pre3 +1.18.2-rc1 +1.18.2 +22w13oneblockatatime +22w11a +22w12a +22w13a +22w14a +22w15a +22w16a +22w16b +22w17a +22w18a +22w19a +1.19-pre1 +1.19-pre2 +1.19-pre3 +1.19-pre4 +1.19-pre5 +1.19-rc1 +1.19-rc2 +1.19 +22w24a +1.19.1-pre1 +1.19.1-pre2 +1.19.1-pre3 +1.19.1-pre4 +1.19.1-pre5 +1.19.1-pre6 +1.19.1-rc1 +1.19.1-rc2 +1.19.1-rc3 +1.19.1 +1.19.2-rc1 +1.19.2-rc2 +1.19.2 +22w42a +22w43a +22w44a +22w45a +22w46a +1.19.3-pre1 +1.19.3-pre2 +1.19.3-pre3 +1.19.3-rc1 +1.19.3-rc2 +1.19.3-rc3 +1.19.3 +23w03a +23w04a +23w05a +23w06a +23w07a +1.19.4-pre1 +1.19.4-pre2 +1.19.4-pre3 +1.19.4-pre4 +1.19.4-rc1 +1.19.4-rc2 +1.19.4-rc3 +1.19.4 +23w12a +23w13a +23w13a_or_b +23w14a +23w16a +23w17a +23w18a +1.20-pre1 +1.20-pre2 +1.20-pre3 +1.20-pre4 +1.20-pre5 +1.20-pre6 +1.20-pre7 +1.20-rc1 +1.20 +1.20.1-rc1 +1.20.1 +23w31a +23w32a +23w33a +23w35a +1.20.2-pre1 +1.20.2-pre2 +1.20.2-pre3 +1.20.2-pre4 +1.20.2-rc1 +1.20.2-rc2 +1.20.2 +23w40a +23w41a +23w42a +23w43a +23w43b +23w44a +23w45a +23w46a +1.20.3-pre1 +1.20.3-pre2 +1.20.3-pre3 +1.20.3-pre4 +1.20.3-rc1 +1.20.3 +1.20.4-rc1 +1.20.4 +23w51a +23w51b +24w03a +24w03b +24w04a +24w05a diff --git a/HMCLCore/src/test/java/org/jackhuang/hmcl/game/JavaVersionConstraintTest.java b/HMCLCore/src/test/java/org/jackhuang/hmcl/game/JavaVersionConstraintTest.java index 6bc3ce585..ddc1ddfe2 100644 --- a/HMCLCore/src/test/java/org/jackhuang/hmcl/game/JavaVersionConstraintTest.java +++ b/HMCLCore/src/test/java/org/jackhuang/hmcl/game/JavaVersionConstraintTest.java @@ -17,8 +17,8 @@ */ package org.jackhuang.hmcl.game; +import org.jackhuang.hmcl.util.versioning.GameVersionNumber; import org.jackhuang.hmcl.util.versioning.VersionNumber; -import org.jackhuang.hmcl.util.versioning.VersionRange; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; @@ -28,10 +28,10 @@ public class JavaVersionConstraintTest { @Test public void vanillaJava16() { JavaVersionConstraint.VersionRanges range = JavaVersionConstraint.findSuitableJavaVersionRange( - VersionNumber.asVersion("1.17"), + GameVersionNumber.asGameVersion("1.17"), null ); - assertEquals(VersionRange.atLeast("16"), range.getMandatory()); + assertEquals(VersionNumber.atLeast("16"), range.getMandatory()); } } diff --git a/HMCLCore/src/test/java/org/jackhuang/hmcl/util/versioning/GameVersionNumberTest.java b/HMCLCore/src/test/java/org/jackhuang/hmcl/util/versioning/GameVersionNumberTest.java new file mode 100644 index 000000000..509c40f31 --- /dev/null +++ b/HMCLCore/src/test/java/org/jackhuang/hmcl/util/versioning/GameVersionNumberTest.java @@ -0,0 +1,218 @@ +package org.jackhuang.hmcl.util.versioning; + +import org.junit.jupiter.api.Test; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.*; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * @author Glavo + */ +public class GameVersionNumberTest { + + @Test + public void testSortVersions() throws IOException { + List versions = new ArrayList<>(); + + try (BufferedReader reader = new BufferedReader(new InputStreamReader(GameVersionNumber.class.getResourceAsStream("/assets/game/versions.txt"), StandardCharsets.UTF_8))) { + for (String line; (line = reader.readLine()) != null && !line.isEmpty(); ) { + versions.add(line); + } + } + + List copied = new ArrayList<>(versions); + Collections.shuffle(copied, new Random(0)); + copied.sort(Comparator.comparing(GameVersionNumber::asGameVersion)); + + assertIterableEquals(versions, copied); + } + + private static String errorMessage(String version1, String version2) { + return String.format("version1=%s, version2=%s", version1, version2); + } + + private static void assertGameVersionEquals(String version) { + assertGameVersionEquals(version, version); + } + + private static void assertGameVersionEquals(String version1, String version2) { + assertEquals(0, GameVersionNumber.asGameVersion(version1).compareTo(version2), errorMessage(version1, version2)); + } + + private static void assertLessThan(String version1, String version2) { + assertTrue(GameVersionNumber.asGameVersion(version1).compareTo(version2) < 0, errorMessage(version1, version2)); + } + + private static void assertOrder(String... versions) { + for (int i = 0; i < versions.length - 1; i++) { + GameVersionNumber version1 = GameVersionNumber.asGameVersion(versions[i]); + + //noinspection EqualsWithItself + assertEquals(0, version1.compareTo(version1), "version=" + versions[i]); + + for (int j = i + 1; j < versions.length; j++) { + GameVersionNumber version2 = GameVersionNumber.asGameVersion(versions[j]); + + assertEquals(-1, version1.compareTo(version2), String.format("version1=%s, version2=%s", versions[i], versions[j])); + assertEquals(1, version2.compareTo(version1), String.format("version1=%s, version2=%s", versions[i], versions[j])); + } + } + + assertGameVersionEquals(versions[versions.length - 1]); + } + + @Test + public void testParseOld() { + { + GameVersionNumber version = GameVersionNumber.asGameVersion("b1.0"); + assertInstanceOf(GameVersionNumber.Old.class, version); + GameVersionNumber.Old old = (GameVersionNumber.Old) version; + assertEquals(GameVersionNumber.Type.BETA, old.type); + assertEquals(1, old.major); + assertEquals(0, old.minor); + assertEquals(0, old.patch); + assertEquals(0, old.additional); + } + + { + GameVersionNumber version = GameVersionNumber.asGameVersion("b1.0_01"); + assertInstanceOf(GameVersionNumber.Old.class, version); + GameVersionNumber.Old old = (GameVersionNumber.Old) version; + assertEquals(GameVersionNumber.Type.BETA, old.type); + assertEquals(1, old.major); + assertEquals(0, old.minor); + assertEquals(0, old.patch); + assertEquals(1, old.additional); + } + } + + @Test + public void testCompareRelease() { + assertGameVersionEquals("0.0"); + assertGameVersionEquals("1.100"); + assertGameVersionEquals("1.100.1"); + assertGameVersionEquals("1.100.1-pre1"); + assertGameVersionEquals("1.100.1-pre1", "1.100.1 Pre-Release 1"); + + assertOrder( + "0.0", + "1.0", + "1.99", + "1.99.1-unknown1", + "1.99.1-pre1", + "1.99.1 Pre-Release 2", + "1.99.1-rc1", + "1.99.1", + "1.100", + "1.100.1" + ); + } + + @Test + public void testCompareSnapshot() { + assertOrder( + "90w01a", + "90w01b", + "90w01e", + "90w01~", + "90w02a" + ); + } + + @Test + public void testCompareMix() { + assertOrder( + "rd-132211", + "rd-161348", + "rd-20090515", + "c0.0.11a", + "c0.0.13a", + "c0.0.13a_03", + "c0.30_01c", + "inf-20100330-1", + "inf-20100330-2", + "inf-20100618", + "a1.0.4", + "a1.0.17_02", + "a1.0.17_04", + "a1.1.0", + "b1.0", + "b1.0_01", + "b1.1_02", + "b1.2", + "b1.8.1", + "0.0", + "1.0", + "11w47a", + "1.1", + "1.5.1", + "2.0", + "1.5.2", + "1.9.2", + "1.RV-Pre1", + "16w14a", + "1.9.3-pre1", + "1.13.2", + "19w13b", + "3D Shareware v1.34", + "19w14a", + "1.14 Pre-Release 1", + "1.14", + "1.15.2", + "20w06a", + "20w14infinite", + "20w22a", + "1.16-pre1", + "1.16", + "1.18.2", + "22w13oneblockatatime", + "22w11a", + "1.19-pre1", + "1.19.4", + "23w13a", + "23w13a_or_b", + "23w14a", + "1.20", + + "Unknown", + "100.0" + ); + } + + @Test + public void testCompareUnknown() { + assertOrder( + "23w35a", + "1.20.2-pre1", + "1.20.2-rc1", + "1.20.2", + "23w35b", // fictional version number + "23w40a" + ); + + assertOrder( + "1.20.4", + "24w04a", + "1.100" // fictional version number + ); + + assertOrder( + "1.19.4", + "23w18a", // fictional version number + "1.19.5", + "1.20" + ); + + assertOrder( + "1.0", + "10w47a", // fictional version number + "11w47a", + "1.1" + ); + } +} diff --git a/HMCLCore/src/test/java/org/jackhuang/hmcl/util/versioning/VersionRangeTest.java b/HMCLCore/src/test/java/org/jackhuang/hmcl/util/versioning/VersionRangeTest.java index 0f8ae788d..fcec6a1de 100644 --- a/HMCLCore/src/test/java/org/jackhuang/hmcl/util/versioning/VersionRangeTest.java +++ b/HMCLCore/src/test/java/org/jackhuang/hmcl/util/versioning/VersionRangeTest.java @@ -9,43 +9,46 @@ public class VersionRangeTest { @Test public void testContains() { - assertTrue(between("10", "20").contains("10")); - assertTrue(between("10", "20").contains("15")); - assertTrue(between("10", "20").contains("20")); - assertFalse(between("10", "20").contains("5")); - assertFalse(between("10", "20").contains("25")); + VersionRange empty = VersionRange.empty(); + VersionRange all = all(); - assertTrue(between("10", "10").contains("10")); - assertFalse(between("10", "10").contains("5")); - assertFalse(between("10", "10").contains("15")); + assertTrue(VersionNumber.between("10", "20").contains(VersionNumber.asVersion("10"))); + assertTrue(VersionNumber.between("10", "20").contains(VersionNumber.asVersion("15"))); + assertTrue(VersionNumber.between("10", "20").contains(VersionNumber.asVersion("20"))); + assertFalse(VersionNumber.between("10", "20").contains(VersionNumber.asVersion("5"))); + assertFalse(VersionNumber.between("10", "20").contains(VersionNumber.asVersion("25"))); - assertTrue(atLeast("10").contains("10")); - assertTrue(atLeast("10").contains("20")); - assertFalse(atLeast("10").contains("5")); + assertTrue(VersionNumber.between("10", "10").contains(VersionNumber.asVersion("10"))); + assertFalse(VersionNumber.between("10", "10").contains(VersionNumber.asVersion("5"))); + assertFalse(VersionNumber.between("10", "10").contains(VersionNumber.asVersion("15"))); - assertTrue(atMost("10").contains("10")); - assertTrue(atMost("10").contains("5")); - assertFalse(atMost("10").contains("20")); + assertTrue(VersionNumber.atLeast("10").contains(VersionNumber.asVersion("10"))); + assertTrue(VersionNumber.atLeast("10").contains(VersionNumber.asVersion("20"))); + assertFalse(VersionNumber.atLeast("10").contains(VersionNumber.asVersion("5"))); - assertFalse(empty().contains("0")); - assertFalse(empty().contains("10")); + assertTrue(VersionNumber.atMost("10").contains(VersionNumber.asVersion("10"))); + assertTrue(VersionNumber.atMost("10").contains(VersionNumber.asVersion("5"))); + assertFalse(VersionNumber.atMost("10").contains(VersionNumber.asVersion("20"))); - assertTrue(all().contains("0")); - assertTrue(all().contains("10")); + assertFalse(empty.contains(VersionNumber.asVersion("0"))); + assertFalse(empty.contains(VersionNumber.asVersion("10"))); - assertFalse(all().contains((String) null)); - assertFalse(empty().contains((String) null)); - assertFalse(between("0", "10").contains((String) null)); - assertFalse(atLeast("10").contains((String) null)); - assertFalse(atMost("10").contains((String) null)); - assertFalse(all().contains((VersionNumber) null)); - assertFalse(empty().contains((VersionNumber) null)); - assertFalse(between("0", "10").contains((VersionNumber) null)); - assertFalse(atLeast("10").contains((VersionNumber) null)); - assertFalse(atMost("10").contains((VersionNumber) null)); + assertTrue(all.contains(VersionNumber.asVersion("0"))); + assertTrue(all.contains(VersionNumber.asVersion("10"))); + + assertFalse(all.contains(null)); + assertFalse(empty.contains( null)); + assertFalse(VersionNumber.between("0", "10").contains(null)); + assertFalse(VersionNumber.atLeast("10").contains(null)); + assertFalse(VersionNumber.atMost("10").contains(null)); + assertFalse(all.contains(null)); + assertFalse(empty.contains(null)); + assertFalse(VersionNumber.between("0", "10").contains(null)); + assertFalse(VersionNumber.atLeast("10").contains(null)); + assertFalse(VersionNumber.atMost("10").contains(null)); } - private static void assertIsOverlappedBy(boolean value, VersionRange range1, VersionRange range2) { + private static void assertIsOverlappedBy(boolean value, VersionRange range1, VersionRange range2) { assertEquals(value, range1.isOverlappedBy(range2)); assertEquals(value, range2.isOverlappedBy(range1)); } @@ -56,38 +59,38 @@ public class VersionRangeTest { assertIsOverlappedBy(false, all(), empty()); assertIsOverlappedBy(false, empty(), empty()); - assertIsOverlappedBy(true, all(), between("10", "20")); - assertIsOverlappedBy(true, all(), atLeast("10")); - assertIsOverlappedBy(true, all(), atMost("10")); + assertIsOverlappedBy(true, all(), VersionNumber.between("10", "20")); + assertIsOverlappedBy(true, all(), VersionNumber.atLeast("10")); + assertIsOverlappedBy(true, all(), VersionNumber.atMost("10")); - assertIsOverlappedBy(false, empty(), between("10", "20")); - assertIsOverlappedBy(false, empty(), atLeast("10")); - assertIsOverlappedBy(false, empty(), atMost("10")); + assertIsOverlappedBy(false, empty(), VersionNumber.between("10", "20")); + assertIsOverlappedBy(false, empty(), VersionNumber.atLeast("10")); + assertIsOverlappedBy(false, empty(), VersionNumber.atMost("10")); - assertIsOverlappedBy(true, between("10", "20"), between("10", "20")); - assertIsOverlappedBy(true, between("10", "20"), between("5", "20")); - assertIsOverlappedBy(true, between("10", "20"), between("5", "15")); - assertIsOverlappedBy(true, between("10", "20"), between("5", "10")); - assertIsOverlappedBy(false, between("10", "20"), between("5", "5")); - assertIsOverlappedBy(true, between("10", "20"), between("10", "30")); - assertIsOverlappedBy(true, between("10", "20"), between("15", "30")); - assertIsOverlappedBy(true, between("10", "20"), between("20", "30")); - assertIsOverlappedBy(false, between("10", "20"), between("21", "30")); - assertIsOverlappedBy(true, between("10", "20"), atLeast("5")); - assertIsOverlappedBy(true, between("10", "20"), atLeast("10")); - assertIsOverlappedBy(true, between("10", "20"), atLeast("15")); - assertIsOverlappedBy(true, between("10", "20"), atLeast("20")); - assertIsOverlappedBy(false, between("10", "20"), atLeast("25")); + assertIsOverlappedBy(true, VersionNumber.between("10", "20"), VersionNumber.between("10", "20")); + assertIsOverlappedBy(true, VersionNumber.between("10", "20"), VersionNumber.between("5", "20")); + assertIsOverlappedBy(true, VersionNumber.between("10", "20"), VersionNumber.between("5", "15")); + assertIsOverlappedBy(true, VersionNumber.between("10", "20"), VersionNumber.between("5", "10")); + assertIsOverlappedBy(false, VersionNumber.between("10", "20"), VersionNumber.between("5", "5")); + assertIsOverlappedBy(true, VersionNumber.between("10", "20"), VersionNumber.between("10", "30")); + assertIsOverlappedBy(true, VersionNumber.between("10", "20"), VersionNumber.between("15", "30")); + assertIsOverlappedBy(true, VersionNumber.between("10", "20"), VersionNumber.between("20", "30")); + assertIsOverlappedBy(false, VersionNumber.between("10", "20"), VersionNumber.between("21", "30")); + assertIsOverlappedBy(true, VersionNumber.between("10", "20"), VersionNumber.atLeast("5")); + assertIsOverlappedBy(true, VersionNumber.between("10", "20"), VersionNumber.atLeast("10")); + assertIsOverlappedBy(true, VersionNumber.between("10", "20"), VersionNumber.atLeast("15")); + assertIsOverlappedBy(true, VersionNumber.between("10", "20"), VersionNumber.atLeast("20")); + assertIsOverlappedBy(false, VersionNumber.between("10", "20"), VersionNumber.atLeast("25")); - assertIsOverlappedBy(true, atLeast("10"), atLeast("10")); - assertIsOverlappedBy(true, atLeast("10"), atLeast("20")); - assertIsOverlappedBy(true, atLeast("10"), atLeast("5")); - assertIsOverlappedBy(true, atLeast("10"), atMost("10")); - assertIsOverlappedBy(true, atLeast("10"), atMost("20")); - assertIsOverlappedBy(false, atLeast("10"), atMost("5")); + assertIsOverlappedBy(true, VersionNumber.atLeast("10"), VersionNumber.atLeast("10")); + assertIsOverlappedBy(true, VersionNumber.atLeast("10"), VersionNumber.atLeast("20")); + assertIsOverlappedBy(true, VersionNumber.atLeast("10"), VersionNumber.atLeast("5")); + assertIsOverlappedBy(true, VersionNumber.atLeast("10"), VersionNumber.atMost("10")); + assertIsOverlappedBy(true, VersionNumber.atLeast("10"), VersionNumber.atMost("20")); + assertIsOverlappedBy(false, VersionNumber.atLeast("10"), VersionNumber.atMost("5")); } - private static void assertIntersectionWith(VersionRange range1, VersionRange range2, VersionRange result) { + private static void assertIntersectionWith(VersionRange range1, VersionRange range2, VersionRange result) { assertEquals(result, range1.intersectionWith(range2)); assertEquals(result, range2.intersectionWith(range1)); } @@ -96,35 +99,35 @@ public class VersionRangeTest { public void testIntersectionWith() { assertIntersectionWith(all(), all(), all()); assertIntersectionWith(all(), empty(), empty()); - assertIntersectionWith(all(), between("10", "20"), between("10", "20")); - assertIntersectionWith(all(), atLeast("10"), atLeast("10")); - assertIntersectionWith(all(), atMost("10"), atMost("10")); + assertIntersectionWith(all(), VersionNumber.between("10", "20"), VersionNumber.between("10", "20")); + assertIntersectionWith(all(), VersionNumber.atLeast("10"), VersionNumber.atLeast("10")); + assertIntersectionWith(all(), VersionNumber.atMost("10"), VersionNumber.atMost("10")); assertIntersectionWith(empty(), empty(), empty()); - assertIntersectionWith(empty(), between("10", "20"), empty()); - assertIntersectionWith(empty(), atLeast("10"), empty()); - assertIntersectionWith(empty(), atMost("10"), empty()); + assertIntersectionWith(empty(), VersionNumber.between("10", "20"), empty()); + assertIntersectionWith(empty(), VersionNumber.atLeast("10"), empty()); + assertIntersectionWith(empty(), VersionNumber.atMost("10"), empty()); - assertIntersectionWith(between("10", "20"), between("10", "20"), between("10", "20")); - assertIntersectionWith(between("10", "20"), between("5", "20"), between("10", "20")); - assertIntersectionWith(between("10", "20"), between("10", "25"), between("10", "20")); - assertIntersectionWith(between("10", "20"), between("5", "25"), between("10", "20")); - assertIntersectionWith(between("10", "20"), between("15", "20"), between("15", "20")); - assertIntersectionWith(between("10", "20"), between("10", "15"), between("10", "15")); - assertIntersectionWith(between("10", "20"), between("14", "16"), between("14", "16")); - assertIntersectionWith(between("10", "20"), atLeast("5"), between("10", "20")); - assertIntersectionWith(between("10", "20"), atLeast("10"), between("10", "20")); - assertIntersectionWith(between("10", "20"), atLeast("15"), between("15", "20")); - assertIntersectionWith(between("10", "20"), atLeast("20"), between("20", "20")); - assertIntersectionWith(between("10", "20"), atLeast("25"), empty()); - assertIntersectionWith(between("10", "20"), atMost("25"), between("10", "20")); - assertIntersectionWith(between("10", "20"), atMost("20"), between("10", "20")); - assertIntersectionWith(between("10", "20"), atMost("15"), between("10", "15")); - assertIntersectionWith(between("10", "20"), atMost("10"), between("10", "10")); - assertIntersectionWith(between("10", "20"), atMost("5"), empty()); + assertIntersectionWith(VersionNumber.between("10", "20"), VersionNumber.between("10", "20"), VersionNumber.between("10", "20")); + assertIntersectionWith(VersionNumber.between("10", "20"), VersionNumber.between("5", "20"), VersionNumber.between("10", "20")); + assertIntersectionWith(VersionNumber.between("10", "20"), VersionNumber.between("10", "25"), VersionNumber.between("10", "20")); + assertIntersectionWith(VersionNumber.between("10", "20"), VersionNumber.between("5", "25"), VersionNumber.between("10", "20")); + assertIntersectionWith(VersionNumber.between("10", "20"), VersionNumber.between("15", "20"), VersionNumber.between("15", "20")); + assertIntersectionWith(VersionNumber.between("10", "20"), VersionNumber.between("10", "15"), VersionNumber.between("10", "15")); + assertIntersectionWith(VersionNumber.between("10", "20"), VersionNumber.between("14", "16"), VersionNumber.between("14", "16")); + assertIntersectionWith(VersionNumber.between("10", "20"), VersionNumber.atLeast("5"), VersionNumber.between("10", "20")); + assertIntersectionWith(VersionNumber.between("10", "20"), VersionNumber.atLeast("10"), VersionNumber.between("10", "20")); + assertIntersectionWith(VersionNumber.between("10", "20"), VersionNumber.atLeast("15"), VersionNumber.between("15", "20")); + assertIntersectionWith(VersionNumber.between("10", "20"), VersionNumber.atLeast("20"), VersionNumber.between("20", "20")); + assertIntersectionWith(VersionNumber.between("10", "20"), VersionNumber.atLeast("25"), empty()); + assertIntersectionWith(VersionNumber.between("10", "20"), VersionNumber.atMost("25"), VersionNumber.between("10", "20")); + assertIntersectionWith(VersionNumber.between("10", "20"), VersionNumber.atMost("20"), VersionNumber.between("10", "20")); + assertIntersectionWith(VersionNumber.between("10", "20"), VersionNumber.atMost("15"), VersionNumber.between("10", "15")); + assertIntersectionWith(VersionNumber.between("10", "20"), VersionNumber.atMost("10"), VersionNumber.between("10", "10")); + assertIntersectionWith(VersionNumber.between("10", "20"), VersionNumber.atMost("5"), empty()); - assertIntersectionWith(atLeast("10"), atMost("10"), between("10", "10")); - assertIntersectionWith(atLeast("10"), atMost("20"), between("10", "20")); - assertIntersectionWith(atLeast("10"), atMost("5"), empty()); + assertIntersectionWith(VersionNumber.atLeast("10"), VersionNumber.atMost("10"), VersionNumber.between("10", "10")); + assertIntersectionWith(VersionNumber.atLeast("10"), VersionNumber.atMost("20"), VersionNumber.between("10", "20")); + assertIntersectionWith(VersionNumber.atLeast("10"), VersionNumber.atMost("5"), empty()); } }