Skip to content

Commit 193c663

Browse files
committed
Replace LaunchWrapper on first run
1 parent 76537d1 commit 193c663

File tree

3 files changed

+125
-4
lines changed

3 files changed

+125
-4
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package org.dimdev.utils;
2+
3+
import net.minecraft.launchwrapper.Launch;
4+
import net.minecraftforge.common.ForgeVersion;
5+
6+
import java.io.File;
7+
import java.io.IOException;
8+
import java.net.URISyntaxException;
9+
import java.net.URL;
10+
11+
public class ProfileFinder {
12+
private static File getMinecraftJarFile() {
13+
try {
14+
URL url = Launch.classLoader.getResource("net/minecraft/client/main/Main.class");
15+
if (url.getProtocol().equals("jar")) url = new URL(url.getFile().substring(0, url.getFile().indexOf('!')));
16+
return new File(url.toURI());
17+
} catch (IOException | URISyntaxException e) {
18+
throw new RuntimeException(e);
19+
}
20+
}
21+
22+
public static File getCurrentMinecraftProfileFile() {
23+
File minecraftJarFile = getMinecraftJarFile();
24+
File profileFile = new File(minecraftJarFile.getParentFile(), minecraftJarFile.getParentFile().getName() + ".json");
25+
return profileFile.exists() ? profileFile : null;
26+
}
27+
28+
public static File getCurrentForgeProfileFile() {
29+
File versionsDir = getMinecraftJarFile().getParentFile().getParentFile();
30+
String versionId = ForgeVersion.mcVersion + "-" + ForgeVersion.MOD_ID + ForgeVersion.mcVersion + "-" + ForgeVersion.getVersion();
31+
File profileFile = new File(versionsDir, versionId + File.separatorChar + versionId + ".json");
32+
System.out.println(profileFile);
33+
return profileFile.exists() ? profileFile : null;
34+
}
35+
36+
public static File getGameDir() {
37+
return getMinecraftJarFile().getParentFile().getParentFile().getParentFile();
38+
}
39+
}

src/main/java/org/dimdev/vanillafix/VanillaFixLoadingPlugin.java

Lines changed: 86 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,31 @@
33
import net.minecraft.launchwrapper.Launch;
44
import net.minecraftforge.common.ForgeVersion;
55
import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin;
6+
import org.apache.commons.io.FileUtils;
7+
import org.apache.commons.io.IOUtils;
8+
import org.apache.commons.lang3.StringUtils;
69
import org.apache.logging.log4j.LogManager;
710
import org.apache.logging.log4j.Logger;
11+
import org.dimdev.utils.ProfileFinder;
812
import org.dimdev.utils.SSLUtils;
913
import org.dimdev.vanillafix.crashes.DeobfuscatingRewritePolicy;
1014
import org.dimdev.vanillafix.crashes.StacktraceDeobfuscator;
1115
import org.spongepowered.asm.launch.MixinBootstrap;
1216
import org.spongepowered.asm.mixin.Mixins;
1317

1418
import javax.annotation.Nullable;
15-
import java.io.File;
16-
import java.io.IOException;
17-
import java.io.InputStream;
19+
import java.io.*;
20+
import java.lang.management.ManagementFactory;
21+
import java.lang.reflect.Method;
22+
import java.nio.file.Files;
1823
import java.security.KeyStore;
1924
import java.security.KeyStoreException;
2025
import java.security.NoSuchAlgorithmException;
2126
import java.security.cert.CertificateException;
2227
import java.util.Map;
2328

2429
@IFMLLoadingPlugin.MCVersion(ForgeVersion.mcVersion)
25-
@IFMLLoadingPlugin.SortingIndex(-100000)
30+
@IFMLLoadingPlugin.SortingIndex(Integer.MIN_VALUE + 10000)
2631
public class VanillaFixLoadingPlugin implements IFMLLoadingPlugin {
2732
private static final Logger log = LogManager.getLogger();
2833
private static final String MCP_VERSION = "20180618-1.12"; // TODO: Use version for current Minecraft version!
@@ -51,6 +56,55 @@ public static void initialize() {
5156
config = new LoadingConfig();
5257
config.init(new File(Launch.minecraftHome, "config/vanillafix.cfg"));
5358

59+
// Replace LaunchWrapper with our fork (https://github.com/DimensionalDevelopment/LegacyLauncher)
60+
try {
61+
// Copy launchwrapper-2.0.jar library
62+
File launchWrapperTargetFile = new File(ProfileFinder.getGameDir(), "libraries/net/minecraft/launchwrapper/2.0/launchwrapper-2.0.jar");
63+
if (!launchWrapperTargetFile.exists()) {
64+
launchWrapperTargetFile.getParentFile().mkdirs();
65+
// jar_ is workaround for https://github.com/johnrengelman/shadow/issues/276
66+
try (InputStream is = VanillaFixLoadingPlugin.class.getResourceAsStream("/launchwrapper-2.0.jar_");
67+
OutputStream os = new FileOutputStream(launchWrapperTargetFile)) {
68+
IOUtils.copy(is, os);
69+
}
70+
}
71+
72+
// Replace launchwrapper in profile json
73+
File profileFile = ProfileFinder.getCurrentForgeProfileFile();
74+
log.info("Replacing LaunchWrapper in: " + profileFile);
75+
String profileString = new String(Files.readAllBytes(profileFile.toPath()));
76+
// TODO: Deserialize profile json instead for more flexibility
77+
String newProfileString = StringUtils.replace(profileString,
78+
"net.minecraft:launchwrapper:1.12",
79+
"net.minecraft:launchwrapper:2.0"
80+
);
81+
if (!newProfileString.equals(profileString)) {
82+
Files.write(profileFile.toPath(), newProfileString.getBytes());
83+
84+
// Restart minecraft and minecraft launcher with same arguments
85+
File libraryPath = new File(System.getProperty("java.library.path"));
86+
File newLibraryPath = Files.createTempDirectory("natives").toFile();
87+
FileUtils.copyDirectory(libraryPath, newLibraryPath);
88+
89+
final String command = makeNewCommandLine(newLibraryPath.getAbsolutePath());
90+
91+
log.info("Restarting Minecraft with command: " + command);
92+
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
93+
try {
94+
Runtime.getRuntime().exec(command);
95+
} catch (IOException e) {
96+
throw new RuntimeException(e);
97+
}
98+
}));
99+
// TODO: kill vanilla launcher process too, it caches the json and undoes the changes
100+
Method shutdownMethod = Class.forName("java.lang.Shutdown").getDeclaredMethod("exit", int.class);
101+
shutdownMethod.setAccessible(true);
102+
shutdownMethod.invoke(null, 0);
103+
}
104+
} catch (Throwable t) {
105+
log.error("Failed replacing LaunchWrapper in profile json", t);
106+
}
107+
54108
// Trust the "IdenTrust DST Root CA X3" certificate (used by Let's Encrypt, which is used by paste.dimdev.org)
55109
// TODO: Trust two other certificates, use same alias: https://bugs.openjdk.java.net/browse/JDK-8161008
56110
try (InputStream keyStoreInputStream = VanillaFixLoadingPlugin.class.getResourceAsStream("/dst_root_ca_x3.jks")) {
@@ -84,6 +138,34 @@ public static void initialize() {
84138
DeobfuscatingRewritePolicy.install();
85139
}
86140

141+
private static String makeNewCommandLine(String newLibraryPath) {
142+
StringBuilder command = new StringBuilder();
143+
144+
// Java command
145+
command.append(System.getProperty("java.home"))
146+
.append(File.separatorChar).append("bin")
147+
.append(File.separatorChar).append("javaw");
148+
149+
// JVM args
150+
for (String arg : ManagementFactory.getRuntimeMXBean().getInputArguments()) {
151+
if (arg.startsWith("-Djava.library.path=")) {
152+
arg = "-Djava.library.path=" + newLibraryPath;
153+
}
154+
command.append(" ").append(arg);
155+
}
156+
157+
// Classpath
158+
command.append(" -cp ").append(StringUtils.replace(ManagementFactory.getRuntimeMXBean().getClassPath(),
159+
"1.12" + File.separatorChar + "launchwrapper-1.12.jar",
160+
"2.0" + File.separatorChar + "launchwrapper-2.0.jar"
161+
));
162+
163+
// Command args
164+
command.append(" ").append(System.getProperty("sun.java.command"));
165+
166+
return command.toString();
167+
}
168+
87169
@Override public String[] getASMTransformerClass() {
88170
return new String[0];
89171
}
20.5 KB
Binary file not shown.

0 commit comments

Comments
 (0)