This commit is contained in:
huanghongxun 2018-10-06 12:20:42 +08:00
parent 08be1896ee
commit 749ecfe37f
15 changed files with 440 additions and 276 deletions

View File

@ -296,7 +296,7 @@ public final class LauncherHelper {
}
// Minecraft 1.13 may crash when generating world on Java 8 earlier than 1.8.0_51
VersionNumber JAVA_8 = VersionNumber.asVersion("1.8.0.51");
VersionNumber JAVA_8 = VersionNumber.asVersion("1.8.0_51");
if (!flag && gameVersion.compareTo(VersionNumber.asVersion("1.13")) >= 0 && java.getParsedVersion() == JavaVersion.JAVA_8 && java.getVersionNumber().compareTo(JAVA_8) < 0) {
Optional<JavaVersion> java8 = JavaVersion.getJavas().stream()
.filter(javaVersion -> javaVersion.getVersionNumber().compareTo(JAVA_8) >= 0)

View File

@ -34,6 +34,7 @@ import javafx.scene.layout.StackPane;
import javafx.scene.shape.Rectangle;
import javafx.util.Duration;
import org.jackhuang.hmcl.game.HMCLGameRepository;
import org.jackhuang.hmcl.game.Version;
import org.jackhuang.hmcl.setting.Profile;
import org.jackhuang.hmcl.setting.Profiles;
import org.jackhuang.hmcl.setting.Theme;
@ -49,6 +50,7 @@ import org.jackhuang.hmcl.upgrade.UpdateHandler;
import org.jackhuang.hmcl.util.javafx.MultiStepBinding;
import org.jackhuang.hmcl.util.versioning.VersionNumber;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
@ -130,7 +132,7 @@ public final class MainPage extends StackPane implements DecoratorPage {
HMCLGameRepository repository = profile.getRepository();
List<Node> children = repository.getVersions().parallelStream()
.filter(version -> !version.isHidden())
.sorted((a, b) -> VersionNumber.COMPARATOR.compare(VersionNumber.asVersion(a.getId()), VersionNumber.asVersion(b.getId())))
.sorted(Comparator.comparing(Version::getReleaseTime).thenComparing(a -> VersionNumber.asVersion(a.getId())))
.map(version -> {
StackPane pane = new StackPane();
GameItem item = new GameItem(profile, version.getId());

View File

@ -25,9 +25,9 @@ import javafx.scene.control.Control;
import javafx.scene.control.Skin;
import javafx.scene.control.ToggleGroup;
import org.jackhuang.hmcl.event.EventBus;
import org.jackhuang.hmcl.event.RefreshedVersionsEvent;
import org.jackhuang.hmcl.event.RefreshingVersionsEvent;
import org.jackhuang.hmcl.game.HMCLGameRepository;
import org.jackhuang.hmcl.game.Version;
import org.jackhuang.hmcl.setting.Profile;
import org.jackhuang.hmcl.setting.Profiles;
import org.jackhuang.hmcl.ui.Controllers;
@ -37,6 +37,7 @@ import org.jackhuang.hmcl.ui.download.DownloadWizardProvider;
import org.jackhuang.hmcl.util.i18n.I18n;
import org.jackhuang.hmcl.util.versioning.VersionNumber;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
@ -65,7 +66,7 @@ public class GameList extends Control implements DecoratorPage {
toggleGroup.getProperties().put("ReferenceHolder", listenerHolder);
List<GameListItem> children = repository.getVersions().parallelStream()
.filter(version -> !version.isHidden())
.sorted((a, b) -> VersionNumber.COMPARATOR.compare(VersionNumber.asVersion(a.getId()), VersionNumber.asVersion(b.getId())))
.sorted(Comparator.comparing(Version::getReleaseTime).thenComparing(a -> VersionNumber.asVersion(a.getId())))
.map(version -> new GameListItem(toggleGroup, profile, version.getId()))
.collect(Collectors.toList());
JFXUtilities.runInFX(() -> {

View File

@ -11,7 +11,6 @@ import javafx.stage.FileChooser;
import org.jackhuang.hmcl.game.World;
import org.jackhuang.hmcl.ui.Controllers;
import org.jackhuang.hmcl.ui.wizard.SinglePageWizardProvider;
import org.jackhuang.hmcl.util.versioning.IntVersionNumber;
import org.jackhuang.hmcl.util.versioning.VersionNumber;
import java.io.File;
@ -67,7 +66,7 @@ public class WorldListItem extends Control {
public void manageDatapacks() {
if (world.getGameVersion() == null || // old game will not write game version to level.dat
(IntVersionNumber.isIntVersionNumber(world.getGameVersion()) // we don't parse snapshot version
(VersionNumber.isIntVersionNumber(world.getGameVersion()) // we don't parse snapshot version
&& VersionNumber.asVersion(world.getGameVersion()).compareTo(VersionNumber.asVersion("1.13")) < 0)) {
Controllers.dialog(i18n("world.datapack.1_13"));
return;

View File

@ -66,9 +66,7 @@ public final class ForgeVersionList extends VersionList<ForgeRemoteVersion> {
versions.clear();
for (Map.Entry<String, int[]> entry : root.getGameVersions().entrySet()) {
Optional<String> gameVersion = VersionNumber.parseVersion(entry.getKey());
if (!gameVersion.isPresent())
continue;
String gameVersion = VersionNumber.normalize(entry.getKey());
for (int v : entry.getValue()) {
ForgeVersion version = root.getNumber().get(v);
if (version == null)
@ -84,7 +82,7 @@ public final class ForgeVersionList extends VersionList<ForgeRemoteVersion> {
if (jar == null)
continue;
versions.put(gameVersion.get(), new ForgeRemoteVersion(
versions.put(gameVersion, new ForgeRemoteVersion(
version.getGameVersion(), version.getVersion(), jar
));
}

View File

@ -71,11 +71,10 @@ public final class LiteLoaderBMCLVersionList extends VersionList<LiteLoaderRemot
for (Map.Entry<String, LiteLoaderGameVersions> entry : root.getVersions().entrySet()) {
String gameVersion = entry.getKey();
LiteLoaderGameVersions liteLoader = entry.getValue();
Optional<String> gg = VersionNumber.parseVersion(gameVersion);
if (!gg.isPresent())
continue;
doBranch(gg.get(), gameVersion, liteLoader.getRepoitory(), liteLoader.getArtifacts(), false);
doBranch(gg.get(), gameVersion, liteLoader.getRepoitory(), liteLoader.getSnapshots(), true);
String gg = VersionNumber.normalize(gameVersion);
doBranch(gg, gameVersion, liteLoader.getRepoitory(), liteLoader.getArtifacts(), false);
doBranch(gg, gameVersion, liteLoader.getRepoitory(), liteLoader.getSnapshots(), true);
}
} finally {
lock.writeLock().unlock();

View File

@ -71,11 +71,10 @@ public final class LiteLoaderVersionList extends VersionList<LiteLoaderRemoteVer
for (Map.Entry<String, LiteLoaderGameVersions> entry : root.getVersions().entrySet()) {
String gameVersion = entry.getKey();
LiteLoaderGameVersions liteLoader = entry.getValue();
Optional<String> gg = VersionNumber.parseVersion(gameVersion);
if (!gg.isPresent())
continue;
doBranch(gg.get(), gameVersion, liteLoader.getRepoitory(), liteLoader.getArtifacts(), false);
doBranch(gg.get(), gameVersion, liteLoader.getRepoitory(), liteLoader.getSnapshots(), true);
String gg = VersionNumber.normalize(gameVersion);
doBranch(gg, gameVersion, liteLoader.getRepoitory(), liteLoader.getArtifacts(), false);
doBranch(gg, gameVersion, liteLoader.getRepoitory(), liteLoader.getSnapshots(), true);
}
} finally {
lock.writeLock().unlock();

View File

@ -70,8 +70,9 @@ public final class OptiFineBMCLVersionList extends VersionList<OptiFineRemoteVer
if (StringUtils.isBlank(element.getGameVersion()))
continue;
VersionNumber.parseVersion(element.getGameVersion())
.ifPresent(gameVersion -> versions.put(gameVersion, new OptiFineRemoteVersion(gameVersion, version, () -> mirror, isPre)));
String gameVersion = VersionNumber.normalize(element.getGameVersion());
versions.put(gameVersion, new OptiFineRemoteVersion(gameVersion, version, () -> mirror, isPre));
}
}
};

View File

@ -41,10 +41,12 @@ public final class ModManager {
File modsDirectory = new File(repository.getRunDirectory(id), "mods");
Consumer<File> puter = modFile -> Lang.ignoringException(() -> modCache.put(id, ModInfo.fromFile(modFile)));
Optional.ofNullable(modsDirectory.listFiles()).map(Arrays::stream).ifPresent(files -> files.forEach(modFile -> {
if (modFile.isDirectory() && VersionNumber.parseVersion(modFile.getName()).isPresent())
if (modFile.isDirectory() && VersionNumber.isIntVersionNumber(modFile.getName())) {
// If the folder name is game version, forge will search mod in this subdirectory
Optional.ofNullable(modFile.listFiles()).map(Arrays::stream).ifPresent(x -> x.forEach(puter));
else
} else {
puter.accept(modFile);
}
}));
}

View File

@ -70,7 +70,7 @@ public final class JavaVersion {
}
public VersionNumber getVersionNumber() {
return VersionNumber.asVersion(longVersion.replace('_', '.'));
return VersionNumber.asVersion(longVersion);
}
/**

View File

@ -1,49 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.util.versioning;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* If a version string contains '-', a {@link ComposedVersionNumber}
* will be generated.
*
* Formats like 1.7.10-OptiFine, 1.12.2-Forge
*
* @author huangyuhui
*/
public final class ComposedVersionNumber extends VersionNumber {
List<VersionNumber> composed;
public static boolean isComposedVersionNumber(String version) {
return version.contains("-");
}
ComposedVersionNumber(String version) {
composed = Arrays.stream(version.split("-"))
.map(VersionNumber::asVersion)
.collect(Collectors.toList());
}
@Override
public String toString() {
return composed.stream().map(VersionNumber::toString).collect(Collectors.joining("-"));
}
}

View File

@ -1,71 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.util.versioning;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import org.jackhuang.hmcl.util.StringUtils;
/**
* If a version string formats x.x.x.x, a {@code IntVersionNumber}
* will be generated.
*
* @author huangyuhui
*/
public final class IntVersionNumber extends VersionNumber {
final List<Integer> version;
public static boolean isIntVersionNumber(String version) {
if (version.chars().noneMatch(ch -> ch != '.' && (ch < '0' || ch > '9'))
&& !version.contains("..") && StringUtils.isNotBlank(version)) {
String[] arr = version.split("\\.");
for (String str : arr)
if (str.length() > 9)
// Numbers which are larger than 1e9 cannot be stored as integer.
return false;
return true;
} else {
return false;
}
}
IntVersionNumber(String version) {
if (!isIntVersionNumber(version))
throw new IllegalArgumentException("The version " + version + " is malformed, only dots and digits are allowed.");
List<Integer> versions = Arrays.stream(version.split("\\."))
.map(Integer::parseInt)
.collect(Collectors.toList());
while (!versions.isEmpty() && versions.get(versions.size() - 1) == 0)
versions.remove(versions.size() - 1);
this.version = versions;
}
public int get(int index) {
return version.get(index);
}
@Override
public String toString() {
return version.stream().map(Object::toString).collect(Collectors.joining("."));
}
}

View File

@ -1,46 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.util.versioning;
import java.util.Objects;
/**
* If a version string contains alphabets, a {@code StringVersionNumber}
* will be constructed.
*
* @author huangyuhui
*/
public final class StringVersionNumber extends VersionNumber {
private final String version;
StringVersionNumber(String version) {
Objects.requireNonNull(version);
this.version = version;
}
public String getVersion() {
return version;
}
@Override
public String toString() {
return version;
}
}

View File

@ -1,108 +1,339 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.util.versioning;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import org.jackhuang.hmcl.util.StringUtils;
import java.math.BigInteger;
import java.util.*;
/**
* The formatted version number represents a version string.
*
* @author huangyuhui
* Copied from org.apache.maven.artifact.versioning.ComparableVersion
* Apache License 2.0
*/
public abstract class VersionNumber implements Comparable<VersionNumber> {
public class VersionNumber implements Comparable<VersionNumber> {
public static VersionNumber asVersion(String version) {
Objects.requireNonNull(version);
if (ComposedVersionNumber.isComposedVersionNumber(version))
return new ComposedVersionNumber(version);
else if (IntVersionNumber.isIntVersionNumber(version))
return new IntVersionNumber(version);
else
return new StringVersionNumber(version);
return new VersionNumber(version);
}
public static Optional<String> parseVersion(String str) {
if (IntVersionNumber.isIntVersionNumber(str))
return Optional.of(new IntVersionNumber(str).toString());
else
return Optional.empty();
public static String normalize(String str) {
return new VersionNumber(str).getCanonical();
}
public static boolean isIntVersionNumber(String version) {
if (version.chars().noneMatch(ch -> ch != '.' && (ch < '0' || ch > '9'))
&& !version.contains("..") && StringUtils.isNotBlank(version)) {
String[] arr = version.split("\\.");
for (String str : arr)
if (str.length() > 9)
// Numbers which are larger than 1e9 cannot be stored as integer.
return false;
return true;
} else {
return false;
}
}
private String value;
private String canonical;
private ListItem items;
private interface Item {
int INTEGER_ITEM = 0;
int STRING_ITEM = 1;
int LIST_ITEM = 2;
int compareTo(Item item);
int getType();
boolean isNull();
}
/**
* Represents a numeric item in the version item list.
*/
private static class IntegerItem
implements Item {
private final BigInteger value;
public static final IntegerItem ZERO = new IntegerItem();
private IntegerItem() {
this.value = BigInteger.ZERO;
}
IntegerItem(String str) {
this.value = new BigInteger(str);
}
public int getType() {
return INTEGER_ITEM;
}
public boolean isNull() {
return BigInteger.ZERO.equals(value);
}
public int compareTo(Item item) {
if (item == null) {
return BigInteger.ZERO.equals(value) ? 0 : 1; // 1.0 == 1, 1.1 > 1
}
switch (item.getType()) {
case INTEGER_ITEM:
return value.compareTo(((IntegerItem) item).value);
case STRING_ITEM:
return 1; // 1.1 > 1-sp
case LIST_ITEM:
return 1; // 1.1 > 1-1
default:
throw new RuntimeException("invalid item: " + item.getClass());
}
}
public String toString() {
return value.toString();
}
}
/**
* Represents a string in the version item list, usually a qualifier.
*/
private static class StringItem
implements Item {
private String value;
StringItem(String value) {
this.value = value;
}
public int getType() {
return STRING_ITEM;
}
public boolean isNull() {
return value.isEmpty();
}
public int compareTo(Item item) {
if (item == null) {
// 1-string > 1
return 1;
}
switch (item.getType()) {
case INTEGER_ITEM:
return -1; // 1.any < 1.1 ?
case STRING_ITEM:
return value.compareTo(((StringItem) item).value);
case LIST_ITEM:
return -1; // 1.any < 1-1
default:
throw new RuntimeException("invalid item: " + item.getClass());
}
}
public String toString() {
return value;
}
}
/**
* Represents a version list item. This class is used both for the global item list and for sub-lists (which start
* with '-(number)' in the version specification).
*/
private static class ListItem
extends ArrayList<Item>
implements Item {
Character separator;
public ListItem() {}
public ListItem(char separator) {
this.separator = separator;
}
public int getType() {
return LIST_ITEM;
}
public boolean isNull() {
return (size() == 0);
}
void normalize() {
for (int i = size() - 1; i >= 0; i--) {
Item lastItem = get(i);
if (lastItem.isNull()) {
// remove null trailing items: 0, "", empty list
remove(i);
} else if (!(lastItem instanceof ListItem)) {
break;
}
}
}
public int compareTo(Item item) {
if (item == null) {
if (size() == 0) {
return 0; // 1-0 = 1- (normalize) = 1
}
Item first = get(0);
return first.compareTo(null);
}
switch (item.getType()) {
case INTEGER_ITEM:
return -1; // 1-1 < 1.0.x
case STRING_ITEM:
return 1; // 1-1 > 1-sp
case LIST_ITEM:
Iterator<Item> left = iterator();
Iterator<Item> right = ((ListItem) item).iterator();
while (left.hasNext() || right.hasNext()) {
Item l = left.hasNext() ? left.next() : null;
Item r = right.hasNext() ? right.next() : null;
// if this is shorter, then invert the compare and mul with -1
int result = l == null ? (r == null ? 0 : -1 * r.compareTo(l)) : l.compareTo(r);
if (result != 0) {
return result;
}
}
return 0;
default:
throw new RuntimeException("invalid item: " + item.getClass());
}
}
public String toString() {
StringBuilder buffer = new StringBuilder();
for (Item item : this) {
if (buffer.length() > 0) {
if (!(item instanceof ListItem))
buffer.append('.');
}
buffer.append(item);
}
if (separator != null)
return separator + buffer.toString();
else
return buffer.toString();
}
}
public VersionNumber(String version) {
parseVersion(version);
}
private void parseVersion(String version) {
this.value = version;
items = new ListItem();
version = version.toLowerCase(Locale.ENGLISH);
ListItem list = items;
Stack<Item> stack = new Stack<>();
stack.push(list);
boolean isDigit = false;
int startIndex = 0;
for (int i = 0; i < version.length(); i++) {
char c = version.charAt(i);
if (c == '.') {
if (i == startIndex) {
list.add(IntegerItem.ZERO);
} else {
list.add(parseItem(version.substring(startIndex, i)));
}
startIndex = i + 1;
} else if ("!\"#$%&'()*+,-/:;<=>?@[\\]^_`{|}~".indexOf(c) != -1) {
if (i == startIndex) {
list.add(IntegerItem.ZERO);
} else {
list.add(parseItem(version.substring(startIndex, i)));
}
startIndex = i + 1;
list.add(list = new ListItem(c));
stack.push(list);
} else if (Character.isDigit(c)) {
if (!isDigit && i > startIndex) {
list.add(parseItem(version.substring(startIndex, i)));
startIndex = i;
list.add(list = new ListItem());
stack.push(list);
}
isDigit = true;
} else {
if (isDigit && i > startIndex) {
list.add(parseItem(version.substring(startIndex, i)));
startIndex = i;
list.add(list = new ListItem());
stack.push(list);
}
isDigit = false;
}
}
if (version.length() > startIndex) {
list.add(parseItem(version.substring(startIndex)));
}
while (!stack.isEmpty()) {
list = (ListItem) stack.pop();
list.normalize();
}
canonical = items.toString();
}
private static Item parseItem(String buf) {
return buf.chars().allMatch(Character::isDigit) ? new IntegerItem(buf) : new StringItem(buf);
}
@Override
public int compareTo(VersionNumber o) {
return COMPARATOR.compare(this, o);
return items.compareTo(o.items);
}
@Override
public boolean equals(Object another) {
return another instanceof VersionNumber && this.toString().equals(another.toString());
public String toString() {
return value;
}
public String getCanonical() {
return canonical;
}
@Override
public boolean equals(Object o) {
return o instanceof VersionNumber && canonical.equals(((VersionNumber) o).canonical);
}
@Override
public int hashCode() {
return toString().hashCode();
return canonical.hashCode();
}
private static <T extends Comparable<T>> int compareTo(List<T> a, List<T> b) {
int i;
for (i = 0; i < a.size() && i < b.size(); ++i) {
int res = a.get(i).compareTo(b.get(i));
if (res != 0)
return res;
}
if (i < a.size()) return 1;
else if (i < b.size()) return -1;
else return 0;
}
public static final Comparator<VersionNumber> COMPARATOR = new Comparator<VersionNumber>() {
@Override
public int compare(VersionNumber a, VersionNumber b) {
if (a == null || b == null)
return 0;
else {
if (a instanceof ComposedVersionNumber) {
if (b instanceof ComposedVersionNumber)
return compareTo(((ComposedVersionNumber) a).composed, ((ComposedVersionNumber) b).composed);
else
return compare(((ComposedVersionNumber) a).composed.get(0), b);
} else if (a instanceof IntVersionNumber) {
if (b instanceof ComposedVersionNumber)
return -compare(b, a);
else if (b instanceof IntVersionNumber)
return compareTo(((IntVersionNumber) a).version, ((IntVersionNumber) b).version);
else if (b instanceof StringVersionNumber)
return a.toString().compareTo(b.toString());
} else if (a instanceof StringVersionNumber) {
if (b instanceof ComposedVersionNumber)
return -compare(b, a);
else if (b instanceof StringVersionNumber)
return a.toString().compareTo(b.toString());
else if (b instanceof IntVersionNumber)
return a.toString().compareTo(b.toString());
}
throw new IllegalArgumentException("Unrecognized VersionNumber " + a + " and " + b);
}
}
};
}

View File

@ -0,0 +1,98 @@
package org.jackhuang.hmcl.util;
import org.jackhuang.hmcl.util.versioning.VersionNumber;
import org.junit.Assert;
import org.junit.Test;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
public class VersionNumberTest {
@Test
public void testCanonical() {
VersionNumber u, v;
v = VersionNumber.asVersion("3.2.0.0");
Assert.assertEquals("3.2", v.getCanonical());
v = VersionNumber.asVersion("3.2.0.0-5");
Assert.assertEquals("3.2-5", v.getCanonical());
v = VersionNumber.asVersion("3.2.0.0-0");
Assert.assertEquals("3.2", v.getCanonical());
v = VersionNumber.asVersion("3.2--------");
Assert.assertEquals("3.2", v.getCanonical());
v = VersionNumber.asVersion("1.7.2$%%^@&snapshot-3.1.1");
Assert.assertEquals("1.7.2$%%^@&snapshot-3.1.1", v.getCanonical());
}
@Test
public void testComparator() {
VersionNumber u, v;
u = VersionNumber.asVersion("1.7.10forge1614_FTBInfinity");
v = VersionNumber.asVersion("1.12.2");
Assert.assertTrue(u.compareTo(v) < 0);
u = VersionNumber.asVersion("1.8.0_51");
v = VersionNumber.asVersion("1.8.0.51");
Assert.assertTrue(u.compareTo(v) < 0);
u = VersionNumber.asVersion("1.8.0_151");
v = VersionNumber.asVersion("1.8.0_77");
Assert.assertTrue(u.compareTo(v) > 0);
u = VersionNumber.asVersion("1.6.0_22");
v = VersionNumber.asVersion("1.8.0_11");
Assert.assertTrue(u.compareTo(v) < 0);
}
@Test
public void testSorting() {
List<String> input = Arrays.asList(
"1.10",
"1.10.2",
"1.10.2-All the Mods",
"1.10.2-AOE",
"1.10.2-AOE-1.1.5",
"1.10.2-forge2511-Age_of_Progression",
"1.10.2-forge2511-AOE-1.1.2",
"1.10.2-forge2511-ATM-E",
"1.10.2-forge2511-simple_life_2",
"1.10.2-forge2511_bxztest",
"1.10.2-forge2511_Farming_Valley",
"1.10.2-forge2511简单生活BXZ",
"1.10.2-FTB_Beyond",
"1.10.2-LiteLoader1.10.2",
"1.12.2",
"1.12.2_Modern_Skyblock-3.4.2",
"1.13.1",
"1.6.4",
"1.6.4-Forge9.11.1.1345",
"1.7.10",
"1.7.10-1614",
"1.7.10-1614-test",
"1.7.10-F1614-L",
"1.7.10-FL1614_04",
"1.7.10-Forge10.13.4.1614-1.7.10",
"1.7.10-Forge1614",
"1.7.10-Forge1614.1",
"1.7.10Agrarian_Skies_2",
"1.7.10forge1614test",
"1.7.10forge1614_ATlauncher",
"1.7.10forge1614_FTBInfinity",
"1.7.10Forge1614_FTBInfinity-2.6.0",
"1.7.10Forge1614_FTBInfinity-3.0.1",
"1.7.10forge1614_FTBInfinity_server",
"1.8",
"1.8-forge1577",
"1.8.9",
"1.8.9-forge1902",
"1.9");
input.sort(Comparator.comparing(VersionNumber::asVersion));
}
}