Fix OptiFine installation

This commit is contained in:
huanghongxun
2019-08-19 00:18:34 +08:00
parent fb24516b90
commit c5919f2719
4 changed files with 93 additions and 29 deletions

View File

@@ -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");

View File

@@ -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

View File

@@ -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();

View File

@@ -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();
}
}