From 041c59daec89937e932a316b990fccf55ca7b774 Mon Sep 17 00:00:00 2001 From: Lassebq Date: Tue, 20 Aug 2024 08:19:40 +0300 Subject: [PATCH] Asset index-based sound download. WIP Fabric tweak. WIP resource overrides --- README.md | 18 +++-- .../launchwrapper/LaunchConfig.java | 1 - .../launchwrapper/inject/Inject.java | 1 + .../loader/ClassLoaderURLHandler.java | 55 ++++++++++++++ .../loader/LaunchClassLoader.java | 38 ++++++++-- .../launchwrapper/protocol/AssetRequests.java | 74 +++++++++++++++++++ .../protocol/AssetURLConnection.java | 74 +++++++++++++++++++ .../protocol/LegacyURLStreamHandler.java | 15 ++-- .../protocol/ResourceIndexURLConnection.java | 30 -------- .../protocol/SaveLevelURLConnection.java | 1 + .../tweak/FabricLoaderTweak.java | 39 ++++++++++ .../launchwrapper/tweak/LegacyTweak.java | 55 +++++--------- .../mcphackers/launchwrapper/tweak/Tweak.java | 20 +++-- .../launchwrapper/tweak/VanillaTweak.java | 4 +- 14 files changed, 331 insertions(+), 94 deletions(-) create mode 100644 src/main/java/org/mcphackers/launchwrapper/loader/ClassLoaderURLHandler.java create mode 100644 src/main/java/org/mcphackers/launchwrapper/protocol/AssetRequests.java create mode 100644 src/main/java/org/mcphackers/launchwrapper/protocol/AssetURLConnection.java delete mode 100644 src/main/java/org/mcphackers/launchwrapper/protocol/ResourceIndexURLConnection.java create mode 100644 src/main/java/org/mcphackers/launchwrapper/tweak/FabricLoaderTweak.java diff --git a/README.md b/README.md index 7fdd6d9..9f4cb80 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,10 @@ LaunchWrapper is bundled in [BetterJSONs](https://github.com/MCPHackers/BetterJS ## Features - Strips game window from Java **AWT** (**Abstract Window Toolkit**) and lets the game use internal **LWJGL** frame - BitDepthFix for versions before Beta 1.8 +- LaunchWrapper works with Risugami's Modloader so long as you're using Java 8 - Allows changing assets directory in 1.6 snapshots (the game didn't have a parameter to do that yet) - Allows changing game directory in versions before 1.6 -- Replaces mouse input code with **LWJGL** calls +- Replaces mouse input code with **LWJGL** calls (Fixes any mouse input issues in classic, indev and infdev) - Fixes TimSort crash when using Java 8+ - Adds ability to customize built-in **LWJGL** frame - Changing display title @@ -45,7 +46,7 @@ Arguments are formatted the same way as in Mojang launch wrapper.
For example: `--username DemoUser --width 1280 --height 720 --title "Minecraft Demo" --demo` Arguments may be as follows: -- `awtFrame` - disable LWJGL frame patch and use AWT +- `awtFrame` - disable LWJGL frame patch and use AWT (Not recommended) - `isom` - Launch IsomPreviewApplet - `forceVsync` - Launch the game with VSync enabled - `forceResizable` - Early Indev and Classic don't properly update viewport, so the wrapper disables frame resizing. To enable it anyway use this argument @@ -55,11 +56,14 @@ Arguments may be as follows: - **pre-b1.9-pre4** - flip bottom textures and crop to 64x32 - **pre-1.8** - crop to 64x32 - **default** - do nothing with requested skin -- `resourcesProxyPort` - Betacraft proxy port for sound resources -- `serverSHA1` - Compare minecraft_server.jar in .minecraft/server against this hash -- `serverURL` - URL to download the server from if the hash is mismatched or the jar is missing -- `icon` - List of paths of icon PNGs separated by `;` +- `assetsDir` - Will be used by LaunchWrapper to locate custom index.json +- `assetIndex` - Name of the `assetsDir`/indexes/index.json without .json extension which will be used - `title` - The display title -- `applet` - Makes the game think you're running an applet (Which removes quit button for example) +- `icon` - List of paths of icon PNGs separated by `;` +- `applet` - Makes the game think you're running an applet which: + - Removes quit button in versions between Beta 1.0 and release 1.5.2 + - Changes mouse input code in classic - `oneSixFlag` - Toggles notice about the release of 1.6 in 1.5.2 +- `serverSHA1` - Compare minecraft_server.jar in .minecraft/server against this hash +- `serverURL` - URL to download the server from if the hash is mismatched or the jar is missing - \+ any [Minecraft launch arguments](https://wiki.vg/Launching_the_game#Game_Arguments) or applet parameters diff --git a/src/main/java/org/mcphackers/launchwrapper/LaunchConfig.java b/src/main/java/org/mcphackers/launchwrapper/LaunchConfig.java index d856a4e..6181731 100644 --- a/src/main/java/org/mcphackers/launchwrapper/LaunchConfig.java +++ b/src/main/java/org/mcphackers/launchwrapper/LaunchConfig.java @@ -51,7 +51,6 @@ public class LaunchConfig { public LaunchParameterSwitch forceVsync = new LaunchParameterSwitch("forceVsync", false, true); public LaunchParameterSwitch forceResizable = new LaunchParameterSwitch("forceResizable", false, true); public LaunchParameterEnum skinProxy = new LaunchParameterEnum("skinProxy", SkinType.DEFAULT, true); - public LaunchParameterNumber resourcesProxyPort = new LaunchParameterNumber("resourcesProxyPort", null, true); public LaunchParameterString serverURL = new LaunchParameterString("serverURL", null, true); public LaunchParameterString serverSHA1 = new LaunchParameterString("serverSHA1", null, true); public LaunchParameterFileList icon = new LaunchParameterFileList("icon", null, true); diff --git a/src/main/java/org/mcphackers/launchwrapper/inject/Inject.java b/src/main/java/org/mcphackers/launchwrapper/inject/Inject.java index 35dc2e6..9e51eb5 100644 --- a/src/main/java/org/mcphackers/launchwrapper/inject/Inject.java +++ b/src/main/java/org/mcphackers/launchwrapper/inject/Inject.java @@ -63,6 +63,7 @@ public static File saveLevel(int index, String levelName) { } } lvlNames[index] = levelName; + // Since minecraft doesn't have a delete button on levels, just save a new one with this name and it'll get deleted if(levelName.equals("---")) { level.delete(); level = null; diff --git a/src/main/java/org/mcphackers/launchwrapper/loader/ClassLoaderURLHandler.java b/src/main/java/org/mcphackers/launchwrapper/loader/ClassLoaderURLHandler.java new file mode 100644 index 0000000..3162a37 --- /dev/null +++ b/src/main/java/org/mcphackers/launchwrapper/loader/ClassLoaderURLHandler.java @@ -0,0 +1,55 @@ +package org.mcphackers.launchwrapper.loader; + +import static org.objectweb.asm.ClassWriter.COMPUTE_FRAMES; +import static org.objectweb.asm.ClassWriter.COMPUTE_MAXS; + +import java.io.ByteArrayInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLStreamHandler; + +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.tree.ClassNode; + +public class ClassLoaderURLHandler extends URLStreamHandler { + + private LaunchClassLoader classLoader; + + public ClassLoaderURLHandler(LaunchClassLoader classLoader) { + this.classLoader = classLoader; + } + + class ClassLoaderURLConnection extends URLConnection { + + protected ClassLoaderURLConnection(URL url) { + super(url); + } + + @Override + public void connect() throws IOException { + } + + @Override + public InputStream getInputStream() throws IOException { + String path = url.getPath(); + ClassNode node = classLoader.overridenClasses.get(path); + if(node == null) { + throw new FileNotFoundException(); + } + ClassWriter writer = new SafeClassWriter(classLoader, COMPUTE_MAXS | COMPUTE_FRAMES); + node.accept(writer); + byte[] classData = writer.toByteArray(); + return new ByteArrayInputStream(classData); + } + + } + + @Override + protected URLConnection openConnection(URL url) throws IOException { + return new ClassLoaderURLConnection(url); + } + +} diff --git a/src/main/java/org/mcphackers/launchwrapper/loader/LaunchClassLoader.java b/src/main/java/org/mcphackers/launchwrapper/loader/LaunchClassLoader.java index b0259d0..23e8803 100644 --- a/src/main/java/org/mcphackers/launchwrapper/loader/LaunchClassLoader.java +++ b/src/main/java/org/mcphackers/launchwrapper/loader/LaunchClassLoader.java @@ -35,7 +35,8 @@ public class LaunchClassLoader extends URLClassLoader implements ClassNodeSource private ClassLoaderTweak tweak; private Map> exceptions = new HashMap>(); /** Keys should contain dots */ - private Map overridenClasses = new HashMap(); + Map overridenClasses = new HashMap(); + Map overridenResources = new HashMap(); //TODO /** Keys should contain slashes */ private Map classNodeCache = new HashMap(); private File debugOutput; @@ -60,15 +61,35 @@ public void addURL(URL url) { } public URL findResource(String name) { - URL url = super.findResource(name); + URL url = getOverridenResourceURL(name); if(url != null) { return url; } - return parent.getResource(name); + url = super.findResource(name); + return url == null ? parent.getResource(name) : url; } public URL getResource(String name) { - return super.getResource(name); + URL url = getOverridenResourceURL(name); + if(url != null) { + return url; + } + url = super.getResource(name); + return url == null ? parent.getResource(name) : url; + } + + private URL getOverridenResourceURL(String name) { + if(overridenResources.get(name) != null) { + //TODO + } + try { + if(overridenClasses.get(classNameFromResource(name)) != null) { + URL url = new URL("jar", "", -1, classNameFromResource(name), new ClassLoaderURLHandler(this)); + return url; + } + } catch (MalformedURLException e) { + } + return null; } public Enumeration findResources(String name) throws IOException { @@ -150,7 +171,7 @@ private void saveDebugClass(ClassNode node) { cls.getParentFile().mkdirs(); // TraceClassVisitor trace = new TraceClassVisitor(new PrintWriter(new File(debugOutput, node.name + ".dump"))); // node.accept(trace); - ClassWriter writer = new SafeClassWriter(this, COMPUTE_MAXS); + ClassWriter writer = new SafeClassWriter(this, COMPUTE_MAXS | COMPUTE_FRAMES); node.accept(writer); byte[] classData = writer.toByteArray(); FileOutputStream fos = new FileOutputStream(cls); @@ -230,6 +251,13 @@ private static String classResourceName(String name) { return name.replace('.', '/') + ".class"; } + private static String classNameFromResource(String resource) { + if(resource.endsWith(".class")) { + return resource.substring(resource.length() - 7); + } + return resource; + } + private InputStream getClassAsStream(String name) { String className = classResourceName(name); InputStream is = super.getResourceAsStream(className); diff --git a/src/main/java/org/mcphackers/launchwrapper/protocol/AssetRequests.java b/src/main/java/org/mcphackers/launchwrapper/protocol/AssetRequests.java new file mode 100644 index 0000000..7599bd2 --- /dev/null +++ b/src/main/java/org/mcphackers/launchwrapper/protocol/AssetRequests.java @@ -0,0 +1,74 @@ +package org.mcphackers.launchwrapper.protocol; + +import java.io.File; +import java.io.FileInputStream; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import org.json.JSONObject; +import org.mcphackers.launchwrapper.util.Util; + +public class AssetRequests { + public class AssetObject { + public File file; + public String path; + public String hash; + public long size; + + public AssetObject(File f, String name, String sha1, long s) { + file = f; + path = name; + hash = sha1; + size = s; + } + } + + private Map mappedAssets = new HashMap(); + + public AssetRequests(File assetsDir, String index) { + if(index == null || assetsDir == null) { + return; + } + try { + String inputString = new String(Util.readStream(new FileInputStream(new File(assetsDir, "indexes/" + index + ".json")))); + + JSONObject objects = new JSONObject(inputString).getJSONObject("objects"); + for(String s : objects.keySet()) { + JSONObject entry = objects.optJSONObject(s); + if(entry == null) { + continue; + } + String hash = entry.optString("hash"); + long size = entry.optLong("size"); + if(hash == null) { + System.out.println("[LaunchWrapper] Invalid resource: " + s); + continue; + } + File object = new File(assetsDir, "objects/" + hash.substring(0, 2) + "/" + hash); + if(!object.exists() || object.length() != size) { + System.out.println("[LaunchWrapper] Invalid resource: " + s); + continue; + } + // A little slow and probably pointless + // String sha1 = Util.getSHA1(new FileInputStream(new File(assetsDir, "objects/" + hash.substring(0, 2) + "/" + hash))); + // if(!sha1.equals(hash)) { + // continue; + // } + AssetObject obj = new AssetObject(object, s, hash, size); + mappedAssets.put(s, obj); + + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public AssetObject get(String key) { + return mappedAssets.get(key); + } + + public Collection list() { + return mappedAssets.values(); + } +} diff --git a/src/main/java/org/mcphackers/launchwrapper/protocol/AssetURLConnection.java b/src/main/java/org/mcphackers/launchwrapper/protocol/AssetURLConnection.java new file mode 100644 index 0000000..2d1df65 --- /dev/null +++ b/src/main/java/org/mcphackers/launchwrapper/protocol/AssetURLConnection.java @@ -0,0 +1,74 @@ +package org.mcphackers.launchwrapper.protocol; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.PipedInputStream; +import java.io.PipedOutputStream; +import java.io.PrintWriter; +import java.net.URL; +import java.net.URLConnection; + +import org.mcphackers.launchwrapper.protocol.AssetRequests.AssetObject; + +public class AssetURLConnection extends URLConnection { + private AssetRequests assets; + + public AssetURLConnection(URL url, AssetRequests assets) { + super(url); + this.assets = assets; + } + + @SuppressWarnings("resource") + private InputStream getIndex(boolean xml) throws IOException { + PipedInputStream in = new PipedInputStream(); + PrintWriter out = new PrintWriter(new PipedOutputStream(in), true); + + new Thread(() -> { + if(xml) { + out.write(""); + out.write(""); + } + for(AssetObject asset : assets.list()) { + // path,size,last_updated_timestamp(unused) + if(xml) { + out.write(""); + out.write(""); + out.write(asset.path); + out.write(""); + out.write(""); + out.write(Long.toString(asset.size)); + out.write(""); + out.write(""); + } else { + out.write(asset.path + ',' + asset.size + ",0\n"); + } + } + if(xml) { + out.write(""); + } + out.close(); + }).start(); + return in; + } + + @Override + public InputStream getInputStream() throws IOException { + String key = url.getPath().replaceAll("%20", " ").substring(1); + key = key.substring(key.indexOf('/') + 1); + if(key.isEmpty()) { + boolean xml = url.getPath().startsWith("/MinecraftResources/"); + return getIndex(xml); + } + AssetObject object = assets.get(key); + if(object != null) { + return new FileInputStream(object.file); + } + throw new FileNotFoundException(); + } + + @Override + public void connect() throws IOException { + } +} diff --git a/src/main/java/org/mcphackers/launchwrapper/protocol/LegacyURLStreamHandler.java b/src/main/java/org/mcphackers/launchwrapper/protocol/LegacyURLStreamHandler.java index b29cf9a..553ae55 100644 --- a/src/main/java/org/mcphackers/launchwrapper/protocol/LegacyURLStreamHandler.java +++ b/src/main/java/org/mcphackers/launchwrapper/protocol/LegacyURLStreamHandler.java @@ -5,15 +5,16 @@ import java.net.URLConnection; import org.mcphackers.launchwrapper.Launch; +import org.mcphackers.launchwrapper.LaunchConfig; public class LegacyURLStreamHandler extends URLStreamHandlerProxy { - private SkinType skins; - private int port; + private LaunchConfig config; + private AssetRequests assets; - public LegacyURLStreamHandler(SkinType skins, int port) { - this.skins = skins; - this.port = port; + public LegacyURLStreamHandler(LaunchConfig config) { + this.config = config; + this.assets = new AssetRequests(config.assetsDir.get(), config.assetIndex.get()); } @Override @@ -40,9 +41,9 @@ protected URLConnection openConnection(URL url) throws IOException { if(path.equals("/listmaps.jsp")) return new ListLevelsURLConnection(url); if(path.startsWith("/MinecraftResources/") || path.startsWith("/resources/")) - return new ResourceIndexURLConnection(url, port); + return new AssetURLConnection(url, assets); if(path.startsWith("/MinecraftSkins/") || path.startsWith("/skin/") || path.startsWith("/MinecraftCloaks/") || path.startsWith("/cloak/")) - return new SkinURLConnection(url, skins); + return new SkinURLConnection(url, config.skinProxy.get()); if(host.equals("assets.minecraft.net") && path.equals("/1_6_has_been_released.flag")) if(Launch.getConfig().oneSixFlag.get()) return new BasicResponseURLConnection(url, "https://web.archive.org/web/20130702232237if_/https://mojang.com/2013/07/minecraft-the-horse-update/"); diff --git a/src/main/java/org/mcphackers/launchwrapper/protocol/ResourceIndexURLConnection.java b/src/main/java/org/mcphackers/launchwrapper/protocol/ResourceIndexURLConnection.java deleted file mode 100644 index 24b4177..0000000 --- a/src/main/java/org/mcphackers/launchwrapper/protocol/ResourceIndexURLConnection.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.mcphackers.launchwrapper.protocol; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.net.URLConnection; - -import org.mcphackers.launchwrapper.util.Util; - -public class ResourceIndexURLConnection extends URLConnection { - int port = -1; - - public ResourceIndexURLConnection(URL url, int port) { - super(url); - this.port = port; - } - - @Override - public void connect() throws IOException { - } - - @Override - public InputStream getInputStream() throws IOException { - return Util.replaceHost(url, "betacraft.uk", getPort()).openStream(); - } - - protected int getPort() { - return port; - } -} diff --git a/src/main/java/org/mcphackers/launchwrapper/protocol/SaveLevelURLConnection.java b/src/main/java/org/mcphackers/launchwrapper/protocol/SaveLevelURLConnection.java index 57a646c..686c99e 100644 --- a/src/main/java/org/mcphackers/launchwrapper/protocol/SaveLevelURLConnection.java +++ b/src/main/java/org/mcphackers/launchwrapper/protocol/SaveLevelURLConnection.java @@ -67,6 +67,7 @@ public InputStream getInputStream() throws IOException { levelNamesStream.close(); } lvlNames[levelId] = levelName; + // Since minecraft doesn't have a delete button on levels, just save a new one with this name and it'll get deleted if(levelName.equals("---")) { level.delete(); lvlNames[levelId] = EMPTY_LEVEL; diff --git a/src/main/java/org/mcphackers/launchwrapper/tweak/FabricLoaderTweak.java b/src/main/java/org/mcphackers/launchwrapper/tweak/FabricLoaderTweak.java new file mode 100644 index 0000000..3d9ebf6 --- /dev/null +++ b/src/main/java/org/mcphackers/launchwrapper/tweak/FabricLoaderTweak.java @@ -0,0 +1,39 @@ +package org.mcphackers.launchwrapper.tweak; + +import org.mcphackers.launchwrapper.LaunchConfig; +import org.mcphackers.launchwrapper.LaunchTarget; +import org.mcphackers.launchwrapper.MainLaunchTarget; + +public class FabricLoaderTweak extends Tweak { + + public static final String FABRIC_KNOT_CLIENT = "net/fabricmc/loader/impl/launch/knot/KnotClient"; + protected Tweak baseTweak; + + public FabricLoaderTweak(Tweak baseTweak, LaunchConfig launch) { + super(baseTweak.source, launch); + this.baseTweak = baseTweak; + } + + @Override + public boolean transform() { + if(!baseTweak.transform()) { + return false; + } + // TODO + return true; + } + + @Override + public ClassLoaderTweak getLoaderTweak() { + return baseTweak.getLoaderTweak(); + } + + @Override + public LaunchTarget getLaunchTarget() { + baseTweak.getLaunchTarget(); // discard target, but run any pre-launch tweaks from base tweak + MainLaunchTarget main = new MainLaunchTarget(FABRIC_KNOT_CLIENT); + main.args = new String[] {launch.username.get(), launch.session.get()}; + return main; + } + +} diff --git a/src/main/java/org/mcphackers/launchwrapper/tweak/LegacyTweak.java b/src/main/java/org/mcphackers/launchwrapper/tweak/LegacyTweak.java index b3f4f67..5c43b5d 100644 --- a/src/main/java/org/mcphackers/launchwrapper/tweak/LegacyTweak.java +++ b/src/main/java/org/mcphackers/launchwrapper/tweak/LegacyTweak.java @@ -149,8 +149,8 @@ public LaunchTarget getLaunchTarget() { } downloadServer(); enableLegacyMergeSort(); - URLStreamHandlerProxy.setURLStreamHandler("http", new LegacyURLStreamHandler(skinType, port)); - URLStreamHandlerProxy.setURLStreamHandler("https", new LegacyURLStreamHandler(skinType, port)); + URLStreamHandlerProxy.setURLStreamHandler("http", new LegacyURLStreamHandler(launch)); + URLStreamHandlerProxy.setURLStreamHandler("https", new LegacyURLStreamHandler(launch)); MainLaunchTarget target = new MainLaunchTarget(minecraft.name); target.args = new String[] { launch.username.get(), launch.session.get() }; return target; @@ -318,10 +318,6 @@ && compareInsn(insns2[3], POP)) { } private void removeCanvas(MethodNode method) { - if(!launch.lwjglFrame.get()) { - return; - } - AbstractInsnNode insn1 = method.instructions.getFirst(); while(insn1 != null) { AbstractInsnNode[] insns = fill(insn1, 6); @@ -356,8 +352,26 @@ && compareInsn(insns[2], INVOKEVIRTUAL, "java/awt/Canvas", "getHeight", "()I")) insn1 = invoke; tweakInfo("Replaced canvas getHeight"); } + // 72: aload_0 + // 73: getfield #53 // Field parent:Ljava/awt/Canvas; + // 76: ifnonnull 89 + // 79: invokestatic #338 // Method org/lwjgl/opengl/Display.isCloseRequested:()Z + // 82: ifeq 89 + + if(compareInsn(insns[0], ALOAD) + && compareInsn(insns[1], GETFIELD, minecraft.name, null, "Ljava/awt/Canvas;") + && compareInsn(insns[2], IFNONNULL) + && compareInsn(insns[3], INVOKESTATIC, "org/lwjgl/opengl/Display", "isCloseRequested", "()Z") + && compareInsn(insns[4], IFEQ)) { + method.instructions.remove(insns[0]); + method.instructions.remove(insns[1]); + method.instructions.remove(insns[2]); + insn1 = insns[3]; + tweakInfo("Display.isCloseRequested"); + } insn1 = nextInsn(insn1); } + // TODO figure out why this is a separate loop insn1 = method.instructions.getFirst(); while(insn1 != null) { AbstractInsnNode[] insns = fill(insn1, 6); @@ -1697,35 +1711,6 @@ && compareInsn(insns2[4], PUTFIELD, minecraft.name, null, "Z")) { if(launch.skinProxy.get() != null) { skinType = launch.skinProxy.get(); } - if(launch.resourcesProxyPort.get() != null) { - port = launch.resourcesProxyPort.get(); - } else { - port = getProxyPortFromVersion(launch.version.get()); - System.out.println("[LaunchWrapper] Auto-detected proxy port: " + port); - } - } - - private int getProxyPortFromVersion(String version) { - if(version == null) { - return -1; - } - if(version.startsWith("c") && version.compareTo("c0.0.22a") > 0) { - return 11702; // 11701 is identical in terms of sound assets - } - if(version.equals("a1.0.8")) { - return 11703; // cow sounds - } - if(version.startsWith("in-") || version.startsWith("inf-") || (version.compareTo("a1.2") < 0 && version.compareTo("a1.0.0") >= 0)) { - return 11702; - } - if(version.compareTo("a1.2") >= 0 && version.compareTo("b1.9") < 0) { - return 11705; // 11706 only changes skin - } - if(version.compareTo("1.5.2") <= 0) { - return 11707; - } - - return -1; } public ClassNode getApplet() { diff --git a/src/main/java/org/mcphackers/launchwrapper/tweak/Tweak.java b/src/main/java/org/mcphackers/launchwrapper/tweak/Tweak.java index e112c22..b9f14fd 100644 --- a/src/main/java/org/mcphackers/launchwrapper/tweak/Tweak.java +++ b/src/main/java/org/mcphackers/launchwrapper/tweak/Tweak.java @@ -4,7 +4,6 @@ import java.util.Collections; import java.util.List; -import org.mcphackers.launchwrapper.Launch; import org.mcphackers.launchwrapper.LaunchConfig; import org.mcphackers.launchwrapper.LaunchTarget; import org.mcphackers.launchwrapper.loader.LaunchClassLoader; @@ -44,14 +43,21 @@ public static Tweak get(LaunchClassLoader classLoader, LaunchConfig launch) { } return tweak; } + + private static Tweak wrapTweak(ClassNodeSource source, Tweak baseTweak, LaunchConfig launch) { + if(source.getClass(FabricLoaderTweak.FABRIC_KNOT_CLIENT) != null) { + return new FabricLoaderTweak(baseTweak, launch); + } + return baseTweak; + } private static Tweak getTweak(LaunchClassLoader classLoader, LaunchConfig launch) { if(launch.tweakClass.get() != null) { try { // Instantiate custom tweak if it's present on classpath; - return (Tweak)Class.forName(launch.tweakClass.get()) + return wrapTweak(classLoader, (Tweak)Class.forName(launch.tweakClass.get()) .getConstructor(ClassNodeSource.class, LaunchConfig.class) - .newInstance(classLoader, launch); + .newInstance(classLoader, launch), launch); } catch (ClassNotFoundException e) { return null; } catch (Exception e) { @@ -60,19 +66,19 @@ private static Tweak getTweak(LaunchClassLoader classLoader, LaunchConfig launch } } if(launch.isom.get()) { - return new IsomTweak(classLoader, launch); + return wrapTweak(classLoader, new IsomTweak(classLoader, launch), launch); } if(classLoader.getClass(VanillaTweak.MAIN_CLASS) != null) { - return new VanillaTweak(classLoader, launch); + return wrapTweak(classLoader, new VanillaTweak(classLoader, launch), launch); } for(String cls : LegacyTweak.MAIN_CLASSES) { if(classLoader.getClass(cls) != null) { - return new LegacyTweak(classLoader, launch); + return wrapTweak(classLoader, new LegacyTweak(classLoader, launch), launch); } } for(String cls : LegacyTweak.MAIN_APPLETS) { if(classLoader.getClass(cls) != null) { - return new LegacyTweak(classLoader, launch); + return wrapTweak(classLoader, new LegacyTweak(classLoader, launch), launch); } } return null; // Tweak not found diff --git a/src/main/java/org/mcphackers/launchwrapper/tweak/VanillaTweak.java b/src/main/java/org/mcphackers/launchwrapper/tweak/VanillaTweak.java index a69703c..3f6fce2 100644 --- a/src/main/java/org/mcphackers/launchwrapper/tweak/VanillaTweak.java +++ b/src/main/java/org/mcphackers/launchwrapper/tweak/VanillaTweak.java @@ -193,8 +193,8 @@ && compareInsn(insns[4], LDC) } public LaunchTarget getLaunchTarget() { - URLStreamHandlerProxy.setURLStreamHandler("http", new LegacyURLStreamHandler(launch.skinProxy.get(), 11707)); - URLStreamHandlerProxy.setURLStreamHandler("https", new LegacyURLStreamHandler(launch.skinProxy.get(), 11707)); + URLStreamHandlerProxy.setURLStreamHandler("http", new LegacyURLStreamHandler(launch)); + URLStreamHandlerProxy.setURLStreamHandler("https", new LegacyURLStreamHandler(launch)); MainLaunchTarget target = new MainLaunchTarget(MAIN_CLASS); target.args = launch.getArgs(); return target;