Fix OptiFine installation
This commit is contained in:
@@ -35,11 +35,10 @@ import org.jackhuang.hmcl.util.io.FileUtils;
|
|||||||
import org.jackhuang.hmcl.util.platform.CommandBuilder;
|
import org.jackhuang.hmcl.util.platform.CommandBuilder;
|
||||||
import org.jackhuang.hmcl.util.platform.JavaVersion;
|
import org.jackhuang.hmcl.util.platform.JavaVersion;
|
||||||
import org.jackhuang.hmcl.util.platform.OperatingSystem;
|
import org.jackhuang.hmcl.util.platform.OperatingSystem;
|
||||||
|
import org.jackhuang.hmcl.util.platform.SystemUtils;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.nio.file.FileSystem;
|
import java.nio.file.FileSystem;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
@@ -241,13 +240,7 @@ public class ForgeNewInstallTask extends Task<Version> {
|
|||||||
command.addAll(args);
|
command.addAll(args);
|
||||||
|
|
||||||
LOG.info("Executing external processor " + processor.getJar().toString() + ", command line: " + new CommandBuilder().addAll(command).toString());
|
LOG.info("Executing external processor " + processor.getJar().toString() + ", command line: " + new CommandBuilder().addAll(command).toString());
|
||||||
Process process = new ProcessBuilder(command).start();
|
int exitCode = SystemUtils.callExternalProcess(command);
|
||||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
|
|
||||||
for (String line; (line = reader.readLine()) != null;) {
|
|
||||||
System.out.println(line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int exitCode = process.waitFor();
|
|
||||||
if (exitCode != 0)
|
if (exitCode != 0)
|
||||||
throw new IllegalStateException("Game processor exited abnormally");
|
throw new IllegalStateException("Game processor exited abnormally");
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
|||||||
import org.jackhuang.hmcl.download.LibraryAnalyzer;
|
import org.jackhuang.hmcl.download.LibraryAnalyzer;
|
||||||
import org.jackhuang.hmcl.download.VersionMismatchException;
|
import org.jackhuang.hmcl.download.VersionMismatchException;
|
||||||
import org.jackhuang.hmcl.game.Arguments;
|
import org.jackhuang.hmcl.game.Arguments;
|
||||||
|
import org.jackhuang.hmcl.game.DefaultGameRepository;
|
||||||
import org.jackhuang.hmcl.game.GameVersion;
|
import org.jackhuang.hmcl.game.GameVersion;
|
||||||
import org.jackhuang.hmcl.game.LibrariesDownloadInfo;
|
import org.jackhuang.hmcl.game.LibrariesDownloadInfo;
|
||||||
import org.jackhuang.hmcl.game.Library;
|
import org.jackhuang.hmcl.game.Library;
|
||||||
@@ -31,6 +32,8 @@ import org.jackhuang.hmcl.task.Task;
|
|||||||
import org.jackhuang.hmcl.util.io.CompressingUtils;
|
import org.jackhuang.hmcl.util.io.CompressingUtils;
|
||||||
import org.jackhuang.hmcl.util.io.FileUtils;
|
import org.jackhuang.hmcl.util.io.FileUtils;
|
||||||
import org.jackhuang.hmcl.util.io.NetworkUtils;
|
import org.jackhuang.hmcl.util.io.NetworkUtils;
|
||||||
|
import org.jackhuang.hmcl.util.platform.JavaVersion;
|
||||||
|
import org.jackhuang.hmcl.util.platform.SystemUtils;
|
||||||
import org.jenkinsci.constant_pool_scanner.ConstantPool;
|
import org.jenkinsci.constant_pool_scanner.ConstantPool;
|
||||||
import org.jenkinsci.constant_pool_scanner.ConstantPoolScanner;
|
import org.jenkinsci.constant_pool_scanner.ConstantPoolScanner;
|
||||||
import org.jenkinsci.constant_pool_scanner.ConstantType;
|
import org.jenkinsci.constant_pool_scanner.ConstantType;
|
||||||
@@ -42,7 +45,6 @@ import java.nio.file.FileSystem;
|
|||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -57,15 +59,17 @@ import static org.jackhuang.hmcl.util.Lang.getOrDefault;
|
|||||||
*/
|
*/
|
||||||
public final class OptiFineInstallTask extends Task<Version> {
|
public final class OptiFineInstallTask extends Task<Version> {
|
||||||
|
|
||||||
|
private final DefaultGameRepository gameRepository;
|
||||||
private final DefaultDependencyManager dependencyManager;
|
private final DefaultDependencyManager dependencyManager;
|
||||||
private final Version version;
|
private final Version version;
|
||||||
private final OptiFineRemoteVersion remote;
|
private final OptiFineRemoteVersion remote;
|
||||||
private final Path installer;
|
private final Path installer;
|
||||||
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<>();
|
||||||
private final File dest;
|
private Path dest;
|
||||||
|
|
||||||
private final Library optiFineLibrary;
|
private final Library optiFineLibrary;
|
||||||
|
private final Library optiFineInstallerLibrary;
|
||||||
|
|
||||||
public OptiFineInstallTask(DefaultDependencyManager dependencyManager, Version version, OptiFineRemoteVersion remoteVersion) {
|
public OptiFineInstallTask(DefaultDependencyManager dependencyManager, Version version, OptiFineRemoteVersion remoteVersion) {
|
||||||
this(dependencyManager, version, remoteVersion, null);
|
this(dependencyManager, version, remoteVersion, null);
|
||||||
@@ -73,20 +77,21 @@ public final class OptiFineInstallTask extends Task<Version> {
|
|||||||
|
|
||||||
public OptiFineInstallTask(DefaultDependencyManager dependencyManager, Version version, OptiFineRemoteVersion remoteVersion, Path installer) {
|
public OptiFineInstallTask(DefaultDependencyManager dependencyManager, Version version, OptiFineRemoteVersion remoteVersion, Path installer) {
|
||||||
this.dependencyManager = dependencyManager;
|
this.dependencyManager = dependencyManager;
|
||||||
|
this.gameRepository = dependencyManager.getGameRepository();
|
||||||
this.version = version;
|
this.version = version;
|
||||||
this.remote = remoteVersion;
|
this.remote = remoteVersion;
|
||||||
this.installer = installer;
|
this.installer = installer;
|
||||||
|
|
||||||
String mavenVersion = remote.getGameVersion() + "_" + remote.getSelfVersion();
|
String mavenVersion = remote.getGameVersion() + "_" + remote.getSelfVersion();
|
||||||
|
|
||||||
optiFineLibrary = new Library(
|
optiFineLibrary = new Library("optifine", "OptiFine", mavenVersion);
|
||||||
"optifine", "OptiFine", mavenVersion, null, null,
|
|
||||||
|
optiFineInstallerLibrary = new Library(
|
||||||
|
"optifine", "OptiFine", mavenVersion, "installer", null,
|
||||||
new LibrariesDownloadInfo(new LibraryDownloadInfo(
|
new LibrariesDownloadInfo(new LibraryDownloadInfo(
|
||||||
"optifine/OptiFine/" + mavenVersion + "/OptiFine-" + mavenVersion + ".jar",
|
"optifine/OptiFine/" + mavenVersion + "/OptiFine-" + mavenVersion + "-installer.jar",
|
||||||
remote.getUrl()))
|
remote.getUrl()))
|
||||||
);
|
);
|
||||||
|
|
||||||
dest = dependencyManager.getGameRepository().getLibraryFile(version, optiFineLibrary);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -96,18 +101,14 @@ public final class OptiFineInstallTask extends Task<Version> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void preExecute() throws Exception {
|
public void preExecute() throws Exception {
|
||||||
if (!Arrays.asList("net.minecraft.client.main.Main",
|
dest = Files.createTempFile("optifine-installer", ".jar");
|
||||||
"net.minecraft.launchwrapper.Launch")
|
|
||||||
.contains(version.resolve(dependencyManager.getGameRepository()).getMainClass()))
|
|
||||||
throw new UnsupportedOptiFineInstallationException();
|
|
||||||
|
|
||||||
|
|
||||||
if (installer == null) {
|
if (installer == null) {
|
||||||
dependents.add(new FileDownloadTask(NetworkUtils.toURL(remote.getUrl()), dest)
|
dependents.add(new FileDownloadTask(NetworkUtils.toURL(remote.getUrl()), dest.toFile())
|
||||||
.setCacheRepository(dependencyManager.getCacheRepository())
|
.setCacheRepository(dependencyManager.getCacheRepository())
|
||||||
.setCaching(true));
|
.setCaching(true));
|
||||||
} else {
|
} else {
|
||||||
FileUtils.copyFile(installer, dest.toPath());
|
FileUtils.copyFile(installer, dest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,13 +128,31 @@ public final class OptiFineInstallTask extends Task<Version> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute() throws IOException {
|
public void execute() throws Exception {
|
||||||
List<Library> libraries = new LinkedList<>();
|
List<Library> libraries = new LinkedList<>();
|
||||||
libraries.add(optiFineLibrary);
|
libraries.add(optiFineLibrary);
|
||||||
|
|
||||||
|
FileUtils.copyFile(dest, gameRepository.getLibraryFile(version, optiFineInstallerLibrary).toPath());
|
||||||
|
|
||||||
// Install launch wrapper modified by OptiFine
|
// Install launch wrapper modified by OptiFine
|
||||||
boolean hasLaunchWrapper = false;
|
boolean hasLaunchWrapper = false;
|
||||||
try (FileSystem fs = CompressingUtils.createReadOnlyZipFileSystem(dest.toPath())) {
|
try (FileSystem fs = CompressingUtils.createReadOnlyZipFileSystem(dest)) {
|
||||||
|
if (Files.exists(fs.getPath("optifine/Patcher.class"))) {
|
||||||
|
int exitCode = SystemUtils.callExternalProcess(
|
||||||
|
JavaVersion.fromCurrentEnvironment().getBinary().toString(),
|
||||||
|
"-cp",
|
||||||
|
dest.toString(),
|
||||||
|
"optifine.Patcher",
|
||||||
|
gameRepository.getVersionJar(version).getAbsolutePath(),
|
||||||
|
dest.toString(),
|
||||||
|
gameRepository.getLibraryFile(version, optiFineLibrary).toString()
|
||||||
|
);
|
||||||
|
if (exitCode != 0)
|
||||||
|
throw new IllegalStateException("OptiFine patcher failed");
|
||||||
|
} else {
|
||||||
|
FileUtils.copyFile(dest, gameRepository.getLibraryFile(version, optiFineLibrary).toPath());
|
||||||
|
}
|
||||||
|
|
||||||
Path launchWrapperVersionText = fs.getPath("launchwrapper-of.txt");
|
Path launchWrapperVersionText = fs.getPath("launchwrapper-of.txt");
|
||||||
if (Files.exists(launchWrapperVersionText)) {
|
if (Files.exists(launchWrapperVersionText)) {
|
||||||
String launchWrapperVersion = FileUtils.readText(launchWrapperVersionText).trim();
|
String launchWrapperVersion = FileUtils.readText(launchWrapperVersionText).trim();
|
||||||
@@ -142,24 +161,24 @@ public final class OptiFineInstallTask extends Task<Version> {
|
|||||||
Library launchWrapper = new Library("optifine", "launchwrapper-of", launchWrapperVersion);
|
Library launchWrapper = new Library("optifine", "launchwrapper-of", launchWrapperVersion);
|
||||||
|
|
||||||
if (Files.exists(launchWrapperJar)) {
|
if (Files.exists(launchWrapperJar)) {
|
||||||
File launchWrapperFile = dependencyManager.getGameRepository().getLibraryFile(version, launchWrapper);
|
File launchWrapperFile = gameRepository.getLibraryFile(version, launchWrapper);
|
||||||
FileUtils.makeDirectory(launchWrapperFile.getAbsoluteFile().getParentFile());
|
FileUtils.makeDirectory(launchWrapperFile.getAbsoluteFile().getParentFile());
|
||||||
FileUtils.copyFile(launchWrapperJar, launchWrapperFile.toPath());
|
FileUtils.copyFile(launchWrapperJar, launchWrapperFile.toPath());
|
||||||
|
|
||||||
hasLaunchWrapper = true;
|
hasLaunchWrapper = true;
|
||||||
libraries.add(0, launchWrapper);
|
libraries.add(launchWrapper);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasLaunchWrapper) {
|
if (!hasLaunchWrapper) {
|
||||||
libraries.add(0, new Library("net.minecraft", "launchwrapper", "1.12"));
|
libraries.add(new Library("net.minecraft", "launchwrapper", "1.12"));
|
||||||
}
|
}
|
||||||
|
|
||||||
setResult(new Version(
|
setResult(new Version(
|
||||||
LibraryAnalyzer.LibraryType.OPTIFINE.getPatchId(),
|
LibraryAnalyzer.LibraryType.OPTIFINE.getPatchId(),
|
||||||
remote.getSelfVersion(),
|
remote.getSelfVersion(),
|
||||||
90000,
|
10000,
|
||||||
new Arguments().addGameArguments("--tweakClass", "optifine.OptiFineTweaker"),
|
new Arguments().addGameArguments("--tweakClass", "optifine.OptiFineTweaker"),
|
||||||
"net.minecraft.launchwrapper.Launch",
|
"net.minecraft.launchwrapper.Launch",
|
||||||
libraries
|
libraries
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.jackhuang.hmcl.util;
|
package org.jackhuang.hmcl.util;
|
||||||
|
|
||||||
|
import org.jackhuang.hmcl.util.function.ExceptionalRunnable;
|
||||||
import org.jackhuang.hmcl.util.function.ExceptionalSupplier;
|
import org.jackhuang.hmcl.util.function.ExceptionalSupplier;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@@ -57,6 +58,15 @@ public final class Lang {
|
|||||||
return Collections.unmodifiableList(Arrays.asList(elements));
|
return Collections.unmodifiableList(Arrays.asList(elements));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean test(ExceptionalRunnable<?> r) {
|
||||||
|
try {
|
||||||
|
r.run();
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static <E extends Exception> boolean test(ExceptionalSupplier<Boolean, E> r) {
|
public static <E extends Exception> boolean test(ExceptionalSupplier<Boolean, E> r) {
|
||||||
try {
|
try {
|
||||||
return r.get();
|
return r.get();
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Hello Minecraft! Launcher
|
||||||
|
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.jackhuang.hmcl.util.platform;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public final class SystemUtils {
|
||||||
|
private SystemUtils() {}
|
||||||
|
|
||||||
|
public static int callExternalProcess(String... command) throws IOException, InterruptedException {
|
||||||
|
return callExternalProcess(Arrays.asList(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int callExternalProcess(List<String> command) throws IOException, InterruptedException {
|
||||||
|
Process process = new ProcessBuilder(command).start();
|
||||||
|
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
|
||||||
|
for (String line; (line = reader.readLine()) != null;) {
|
||||||
|
System.out.println(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return process.waitFor();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user