Skip to content

Instantly share code, notes, and snippets.

@comp500
Created January 27, 2020 16:28
Show Gist options
  • Save comp500/7b5dc81981751cbc32d9fac707dd682b to your computer and use it in GitHub Desktop.
Save comp500/7b5dc81981751cbc32d9fac707dd682b to your computer and use it in GitHub Desktop.
Cursed classloader magic (why load fabric from java when you can load fabric from fabric???)
package link.infra.borderlessmining;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.loader.api.entrypoint.PreLaunchEntrypoint;
import net.fabricmc.loader.discovery.ModResolver;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.FileSystem;
import java.util.HashMap;
public class BorderlessMining implements ClientModInitializer, PreLaunchEntrypoint {
@Override
public void onInitializeClient() {
// TODO: is anything needed here?
}
private static class AlreadyJumpedFlag {
public AlreadyJumpedFlag() {}
}
private static class FunkyClassLoader extends URLClassLoader {
public FunkyClassLoader(URL[] urls) {
super(urls, getSystemClassLoader());
}
private HashMap<String, Class<?>> cachedClasses = new HashMap<>();
// kinda quirky hack i found in the depths of stack overflow
@Override
public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
// if (!name.contains("net.fabricmc.loader") && !name.contains("org.spongepowered.asm")) {
// System.out.println(name + " delegating to parent");
// } else {
// System.out.println(name + " funky hacking");
// }
//if (!name.contains("net.fabricmc.loader") && !name.contains("org.spongepowered.asm")) return super.loadClass(name, resolve);
if (name.startsWith("java") || name.startsWith("sun") || name.startsWith("org.xml") || name.startsWith("org.w3c")) return super.loadClass(name, resolve);
Class<?> cachedClass = cachedClasses.get(name);
if (cachedClass != null) {
return cachedClass;
}
InputStream classStream = getResourceAsStream(name.replace('.', '/') + ".class");
if (classStream == null) {
return null;
}
ByteArrayOutputStream result = new ByteArrayOutputStream();
try {
byte[] buffer = new byte[1024];
int length;
while ((length = classStream.read(buffer)) != -1) {
result.write(buffer, 0, length);
}
} catch (IOException e) {
return null;
}
byte[] resultBytes = result.toByteArray();
//System.out.println(result.toString());
Class<?> newClass = defineClass(name, resultBytes,0, resultBytes.length, getClass().getProtectionDomain().getCodeSource());
if (resolve) {
resolveClass(newClass);
}
cachedClasses.put(name, newClass);
return newClass;
}
}
@Override
public void onPreLaunch() {
if ("infinity".equals(System.getProperty("bm.jumpyhax"))) {
System.out.println("Jumpy hax done!!!");
return;
}
System.setProperty("bm.jumpyhax", "infinity");
System.out.println("Jumpy hax time!!!");
// Attempt to close the current in-memory file system for jar-in-jars
try {
Field jimfs = ModResolver.class.getDeclaredField("inMemoryFs");
jimfs.setAccessible(true);
FileSystem fs = (FileSystem) jimfs.get(null);
fs.close();
} catch (NoSuchFieldException | IllegalAccessException | IOException e) {
e.printStackTrace();
}
//ClassLoader parent = BorderlessMining.class.getClassLoader();
URLClassLoader newLoader = new FunkyClassLoader(new URL[0]);
Thread.currentThread().setContextClassLoader(newLoader);
Class<?> knotClient = null;
try {
knotClient = newLoader.loadClass("net.fabricmc.loader.launch.knot.KnotClient");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
if (knotClient != null) {
try {
Method main = knotClient.getMethod("main", String[].class);
main.invoke(null, new Object[] {new String[0]});
} catch (NoSuchMethodException | IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.getTargetException().printStackTrace();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment