mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-09-19 08:46:09 -04:00
fix(launch): cannot launch far old versions on macOS.
This commit is contained in:
parent
a4f22671c6
commit
f70ec8a090
@ -30,9 +30,10 @@ import org.jackhuang.hmcl.util.Logging;
|
|||||||
import org.jackhuang.hmcl.util.gson.JsonUtils;
|
import org.jackhuang.hmcl.util.gson.JsonUtils;
|
||||||
import org.jackhuang.hmcl.util.io.FileUtils;
|
import org.jackhuang.hmcl.util.io.FileUtils;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -47,7 +48,7 @@ public final class GameAssetDownloadTask extends Task<Void> {
|
|||||||
private final AbstractDependencyManager dependencyManager;
|
private final AbstractDependencyManager dependencyManager;
|
||||||
private final Version version;
|
private final Version version;
|
||||||
private final AssetIndexInfo assetIndexInfo;
|
private final AssetIndexInfo assetIndexInfo;
|
||||||
private final File assetIndexFile;
|
private final Path assetIndexFile;
|
||||||
private final boolean integrityCheck;
|
private final boolean integrityCheck;
|
||||||
private final List<Task<?>> dependents = new LinkedList<>();
|
private final List<Task<?>> dependents = new LinkedList<>();
|
||||||
private final List<Task<?>> dependencies = new LinkedList<>();
|
private final List<Task<?>> dependencies = new LinkedList<>();
|
||||||
@ -93,18 +94,18 @@ public final class GameAssetDownloadTask extends Task<Void> {
|
|||||||
if (isCancelled())
|
if (isCancelled())
|
||||||
throw new InterruptedException();
|
throw new InterruptedException();
|
||||||
|
|
||||||
File file = dependencyManager.getGameRepository().getAssetObject(version.getId(), assetIndexInfo.getId(), assetObject);
|
Path file = dependencyManager.getGameRepository().getAssetObject(version.getId(), assetIndexInfo.getId(), assetObject);
|
||||||
boolean download = !file.isFile();
|
boolean download = !Files.isRegularFile(file);
|
||||||
try {
|
try {
|
||||||
if (!download && integrityCheck && !assetObject.validateChecksum(file.toPath(), true))
|
if (!download && integrityCheck && !assetObject.validateChecksum(file, true))
|
||||||
download = true;
|
download = true;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Logging.LOG.log(Level.WARNING, "Unable to calc hash value of file " + file.toPath(), e);
|
Logging.LOG.log(Level.WARNING, "Unable to calc hash value of file " + file, e);
|
||||||
}
|
}
|
||||||
if (download) {
|
if (download) {
|
||||||
List<URL> urls = dependencyManager.getDownloadProvider().getAssetObjectCandidates(assetObject.getLocation());
|
List<URL> urls = dependencyManager.getDownloadProvider().getAssetObjectCandidates(assetObject.getLocation());
|
||||||
|
|
||||||
FileDownloadTask task = new FileDownloadTask(urls, file, new FileDownloadTask.IntegrityCheck("SHA-1", assetObject.getHash()));
|
FileDownloadTask task = new FileDownloadTask(urls, file.toFile(), new FileDownloadTask.IntegrityCheck("SHA-1", assetObject.getHash()));
|
||||||
task.setName(assetObject.getHash());
|
task.setName(assetObject.getHash());
|
||||||
task.setCandidate(dependencyManager.getCacheRepository().getCommonDirectory()
|
task.setCandidate(dependencyManager.getCacheRepository().getCommonDirectory()
|
||||||
.resolve("assets").resolve("objects").resolve(assetObject.getLocation()));
|
.resolve("assets").resolve("objects").resolve(assetObject.getLocation()));
|
||||||
@ -112,7 +113,7 @@ public final class GameAssetDownloadTask extends Task<Void> {
|
|||||||
task.setCaching(true);
|
task.setCaching(true);
|
||||||
dependencies.add(task.withCounter("hmcl.install.assets"));
|
dependencies.add(task.withCounter("hmcl.install.assets"));
|
||||||
} else {
|
} else {
|
||||||
dependencyManager.getCacheRepository().tryCacheFile(file.toPath(), CacheRepository.SHA1, assetObject.getHash());
|
dependencyManager.getCacheRepository().tryCacheFile(file, CacheRepository.SHA1, assetObject.getHash());
|
||||||
}
|
}
|
||||||
|
|
||||||
updateProgress(++progress, index.getObjects().size());
|
updateProgress(++progress, index.getObjects().size());
|
||||||
|
@ -30,8 +30,9 @@ import org.jackhuang.hmcl.util.StringUtils;
|
|||||||
import org.jackhuang.hmcl.util.gson.JsonUtils;
|
import org.jackhuang.hmcl.util.gson.JsonUtils;
|
||||||
import org.jackhuang.hmcl.util.io.FileUtils;
|
import org.jackhuang.hmcl.util.io.FileUtils;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@ -71,14 +72,14 @@ public final class GameAssetIndexDownloadTask extends Task<Void> {
|
|||||||
@Override
|
@Override
|
||||||
public void execute() {
|
public void execute() {
|
||||||
AssetIndexInfo assetIndexInfo = version.getAssetIndex();
|
AssetIndexInfo assetIndexInfo = version.getAssetIndex();
|
||||||
File assetIndexFile = dependencyManager.getGameRepository().getIndexFile(version.getId(), assetIndexInfo.getId());
|
Path assetIndexFile = dependencyManager.getGameRepository().getIndexFile(version.getId(), assetIndexInfo.getId());
|
||||||
boolean verifyHashCode = StringUtils.isNotBlank(assetIndexInfo.getSha1()) && assetIndexInfo.getUrl().contains(assetIndexInfo.getSha1());
|
boolean verifyHashCode = StringUtils.isNotBlank(assetIndexInfo.getSha1()) && assetIndexInfo.getUrl().contains(assetIndexInfo.getSha1());
|
||||||
|
|
||||||
if (assetIndexFile.exists() && !forceDownloading) {
|
if (Files.exists(assetIndexFile) && !forceDownloading) {
|
||||||
// verify correctness of file content
|
// verify correctness of file content
|
||||||
if (verifyHashCode) {
|
if (verifyHashCode) {
|
||||||
try {
|
try {
|
||||||
String actualSum = Hex.encodeHex(DigestUtils.digest("SHA-1", assetIndexFile.toPath()));
|
String actualSum = Hex.encodeHex(DigestUtils.digest("SHA-1", assetIndexFile));
|
||||||
if (actualSum.equalsIgnoreCase(assetIndexInfo.getSha1()))
|
if (actualSum.equalsIgnoreCase(assetIndexInfo.getSha1()))
|
||||||
return;
|
return;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@ -98,7 +99,7 @@ public final class GameAssetIndexDownloadTask extends Task<Void> {
|
|||||||
// And Mojang will modify this file anytime. So assetIndex.hash might be outdated.
|
// And Mojang will modify this file anytime. So assetIndex.hash might be outdated.
|
||||||
FileDownloadTask task = new FileDownloadTask(
|
FileDownloadTask task = new FileDownloadTask(
|
||||||
dependencyManager.getDownloadProvider().injectURLWithCandidates(assetIndexInfo.getUrl()),
|
dependencyManager.getDownloadProvider().injectURLWithCandidates(assetIndexInfo.getUrl()),
|
||||||
assetIndexFile,
|
assetIndexFile.toFile(),
|
||||||
verifyHashCode ? new FileDownloadTask.IntegrityCheck("SHA-1", assetIndexInfo.getSha1()) : null
|
verifyHashCode ? new FileDownloadTask.IntegrityCheck("SHA-1", assetIndexInfo.getSha1()) : null
|
||||||
);
|
);
|
||||||
task.setCacheRepository(dependencyManager.getCacheRepository());
|
task.setCacheRepository(dependencyManager.getCacheRepository());
|
||||||
|
@ -382,7 +382,7 @@ public class DefaultGameRepository implements GameRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public File getActualAssetDirectory(String version, String assetId) {
|
public Path getActualAssetDirectory(String version, String assetId) {
|
||||||
try {
|
try {
|
||||||
return reconstructAssets(version, assetId);
|
return reconstructAssets(version, assetId);
|
||||||
} catch (IOException | JsonParseException e) {
|
} catch (IOException | JsonParseException e) {
|
||||||
@ -392,14 +392,16 @@ public class DefaultGameRepository implements GameRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public File getAssetDirectory(String version, String assetId) {
|
public Path getAssetDirectory(String version, String assetId) {
|
||||||
return new File(getBaseDirectory(), "assets");
|
return getBaseDirectory().toPath().resolve("assets");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public File getAssetObject(String version, String assetId, String name) throws IOException {
|
public Optional<Path> getAssetObject(String version, String assetId, String name) throws IOException {
|
||||||
try {
|
try {
|
||||||
return getAssetObject(version, assetId, getAssetIndex(version, assetId).getObjects().get(name));
|
AssetObject assetObject = getAssetIndex(version, assetId).getObjects().get(name);
|
||||||
|
if (assetObject == null) return Optional.empty();
|
||||||
|
return Optional.of(getAssetObject(version, assetId, assetObject));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw e;
|
throw e;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -408,30 +410,30 @@ public class DefaultGameRepository implements GameRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public File getAssetObject(String version, String assetId, AssetObject obj) {
|
public Path getAssetObject(String version, String assetId, AssetObject obj) {
|
||||||
return getAssetObject(version, getAssetDirectory(version, assetId), obj);
|
return getAssetObject(version, getAssetDirectory(version, assetId), obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
public File getAssetObject(String version, File assetDir, AssetObject obj) {
|
public Path getAssetObject(String version, Path assetDir, AssetObject obj) {
|
||||||
return new File(assetDir, "objects/" + obj.getLocation());
|
return assetDir.resolve("objects").resolve(obj.getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public File getIndexFile(String version, String assetId) {
|
public Path getIndexFile(String version, String assetId) {
|
||||||
return new File(getAssetDirectory(version, assetId), "indexes/" + assetId + ".json");
|
return getAssetDirectory(version, assetId).resolve("indexes").resolve(assetId + ".json");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public File getLoggingObject(String version, String assetId, LoggingInfo loggingInfo) {
|
public Path getLoggingObject(String version, String assetId, LoggingInfo loggingInfo) {
|
||||||
return new File(getAssetDirectory(version, assetId), "log_configs/" + loggingInfo.getFile().getId());
|
return getAssetDirectory(version, assetId).resolve("log_configs").resolve(loggingInfo.getFile().getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected File reconstructAssets(String version, String assetId) throws IOException, JsonParseException {
|
protected Path reconstructAssets(String version, String assetId) throws IOException, JsonParseException {
|
||||||
File assetsDir = getAssetDirectory(version, assetId);
|
Path assetsDir = getAssetDirectory(version, assetId);
|
||||||
File indexFile = getIndexFile(version, assetId);
|
Path indexFile = getIndexFile(version, assetId);
|
||||||
File virtualRoot = new File(new File(assetsDir, "virtual"), assetId);
|
Path virtualRoot = assetsDir.resolve("virtual").resolve(assetId);
|
||||||
|
|
||||||
if (!indexFile.isFile())
|
if (!Files.isRegularFile(indexFile))
|
||||||
return assetsDir;
|
return assetsDir;
|
||||||
|
|
||||||
String assetIndexContent = FileUtils.readText(indexFile);
|
String assetIndexContent = FileUtils.readText(indexFile);
|
||||||
@ -444,11 +446,11 @@ public class DefaultGameRepository implements GameRepository {
|
|||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
int tot = index.getObjects().entrySet().size();
|
int tot = index.getObjects().entrySet().size();
|
||||||
for (Map.Entry<String, AssetObject> entry : index.getObjects().entrySet()) {
|
for (Map.Entry<String, AssetObject> entry : index.getObjects().entrySet()) {
|
||||||
File target = new File(virtualRoot, entry.getKey());
|
Path target = virtualRoot.resolve(entry.getKey());
|
||||||
File original = getAssetObject(version, assetsDir, entry.getValue());
|
Path original = getAssetObject(version, assetsDir, entry.getValue());
|
||||||
if (original.exists()) {
|
if (Files.exists(original)) {
|
||||||
cnt++;
|
cnt++;
|
||||||
if (!target.isFile())
|
if (!Files.isRegularFile(target))
|
||||||
FileUtils.copyFile(original, target);
|
FileUtils.copyFile(original, target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ import org.jackhuang.hmcl.util.platform.Platform;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -190,7 +191,7 @@ public interface GameRepository extends VersionProvider {
|
|||||||
* @param assetId the asset id, you can find it in {@link AssetIndexInfo#getId()} {@link Version#getAssetIndex()}
|
* @param assetId the asset id, you can find it in {@link AssetIndexInfo#getId()} {@link Version#getAssetIndex()}
|
||||||
* @return the actual asset directory
|
* @return the actual asset directory
|
||||||
*/
|
*/
|
||||||
File getActualAssetDirectory(String version, String assetId);
|
Path getActualAssetDirectory(String version, String assetId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the asset directory according to the asset id.
|
* Get the asset directory according to the asset id.
|
||||||
@ -199,7 +200,7 @@ public interface GameRepository extends VersionProvider {
|
|||||||
* @param assetId the asset id, you can find it in {@link AssetIndexInfo#getId()} {@link Version#getAssetIndex()}
|
* @param assetId the asset id, you can find it in {@link AssetIndexInfo#getId()} {@link Version#getAssetIndex()}
|
||||||
* @return the asset directory
|
* @return the asset directory
|
||||||
*/
|
*/
|
||||||
File getAssetDirectory(String version, String assetId);
|
Path getAssetDirectory(String version, String assetId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the file that given asset object refers to
|
* Get the file that given asset object refers to
|
||||||
@ -210,7 +211,7 @@ public interface GameRepository extends VersionProvider {
|
|||||||
* @throws java.io.IOException if I/O operation fails.
|
* @throws java.io.IOException if I/O operation fails.
|
||||||
* @return the file that given asset object refers to
|
* @return the file that given asset object refers to
|
||||||
*/
|
*/
|
||||||
File getAssetObject(String version, String assetId, String name) throws IOException;
|
Optional<Path> getAssetObject(String version, String assetId, String name) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the file that given asset object refers to
|
* Get the file that given asset object refers to
|
||||||
@ -220,7 +221,7 @@ public interface GameRepository extends VersionProvider {
|
|||||||
* @param obj the asset object, you can find it in {@link AssetIndex#getObjects()}
|
* @param obj the asset object, you can find it in {@link AssetIndex#getObjects()}
|
||||||
* @return the file that given asset object refers to
|
* @return the file that given asset object refers to
|
||||||
*/
|
*/
|
||||||
File getAssetObject(String version, String assetId, AssetObject obj);
|
Path getAssetObject(String version, String assetId, AssetObject obj);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get asset index that assetId represents
|
* Get asset index that assetId represents
|
||||||
@ -237,7 +238,7 @@ public interface GameRepository extends VersionProvider {
|
|||||||
* @param version the id of specific version that is relevant to {@code assetId}
|
* @param version the id of specific version that is relevant to {@code assetId}
|
||||||
* @param assetId the asset id, you can find it in {@link AssetIndexInfo#getId()} {@link Version#getAssetIndex()}
|
* @param assetId the asset id, you can find it in {@link AssetIndexInfo#getId()} {@link Version#getAssetIndex()}
|
||||||
*/
|
*/
|
||||||
File getIndexFile(String version, String assetId);
|
Path getIndexFile(String version, String assetId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get logging object
|
* Get logging object
|
||||||
@ -247,7 +248,7 @@ public interface GameRepository extends VersionProvider {
|
|||||||
* @param loggingInfo the logging info
|
* @param loggingInfo the logging info
|
||||||
* @return the file that loggingInfo refers to
|
* @return the file that loggingInfo refers to
|
||||||
*/
|
*/
|
||||||
File getLoggingObject(String version, String assetId, LoggingInfo loggingInfo);
|
Path getLoggingObject(String version, String assetId, LoggingInfo loggingInfo);
|
||||||
|
|
||||||
default List<String> getClasspath(Version version) {
|
default List<String> getClasspath(Version version) {
|
||||||
List<String> classpath = new ArrayList<>();
|
List<String> classpath = new ArrayList<>();
|
||||||
|
@ -44,6 +44,7 @@ import java.net.Proxy;
|
|||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
@ -120,7 +121,10 @@ public class DefaultLauncher extends Launcher {
|
|||||||
|
|
||||||
if (OperatingSystem.CURRENT_OS == OperatingSystem.OSX) {
|
if (OperatingSystem.CURRENT_OS == OperatingSystem.OSX) {
|
||||||
res.addDefault("-Xdock:name=", "Minecraft " + version.getId());
|
res.addDefault("-Xdock:name=", "Minecraft " + version.getId());
|
||||||
res.addDefault("-Xdock:icon=", repository.getAssetObject(version.getId(), version.getAssetIndex().getId(), "icons/minecraft.icns").getAbsolutePath());
|
repository.getAssetObject(version.getId(), version.getAssetIndex().getId(), "icons/minecraft.icns")
|
||||||
|
.ifPresent(minecraftIcns -> {
|
||||||
|
res.addDefault("-Xdock:icon=", minecraftIcns.toAbsolutePath().toString());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OperatingSystem.CURRENT_OS != OperatingSystem.WINDOWS)
|
if (OperatingSystem.CURRENT_OS != OperatingSystem.WINDOWS)
|
||||||
@ -201,12 +205,12 @@ public class DefaultLauncher extends Launcher {
|
|||||||
classpath.add(jar.getAbsolutePath());
|
classpath.add(jar.getAbsolutePath());
|
||||||
|
|
||||||
// Provided Minecraft arguments
|
// Provided Minecraft arguments
|
||||||
File gameAssets = repository.getActualAssetDirectory(version.getId(), version.getAssetIndex().getId());
|
Path gameAssets = repository.getActualAssetDirectory(version.getId(), version.getAssetIndex().getId());
|
||||||
Map<String, String> configuration = getConfigurations();
|
Map<String, String> configuration = getConfigurations();
|
||||||
configuration.put("${classpath}", String.join(OperatingSystem.PATH_SEPARATOR, classpath));
|
configuration.put("${classpath}", String.join(OperatingSystem.PATH_SEPARATOR, classpath));
|
||||||
configuration.put("${natives_directory}", nativeFolder.getAbsolutePath());
|
configuration.put("${natives_directory}", nativeFolder.getAbsolutePath());
|
||||||
configuration.put("${game_assets}", gameAssets.getAbsolutePath());
|
configuration.put("${game_assets}", gameAssets.toAbsolutePath().toString());
|
||||||
configuration.put("${assets_root}", gameAssets.getAbsolutePath());
|
configuration.put("${assets_root}", gameAssets.toAbsolutePath().toString());
|
||||||
|
|
||||||
res.addAll(Arguments.parseArguments(version.getArguments().map(Arguments::getJvm).orElseGet(this::getDefaultJVMArguments), configuration));
|
res.addAll(Arguments.parseArguments(version.getArguments().map(Arguments::getJvm).orElseGet(this::getDefaultJVMArguments), configuration));
|
||||||
if (authInfo.getArguments() != null && authInfo.getArguments().getJvm() != null && !authInfo.getArguments().getJvm().isEmpty())
|
if (authInfo.getArguments() != null && authInfo.getArguments().getJvm() != null && !authInfo.getArguments().getJvm().isEmpty())
|
||||||
|
Loading…
x
Reference in New Issue
Block a user