Unlock classpath in unsafe init
This commit is contained in:
parent
968e3e22e2
commit
ffd9905d40
|
@ -1,13 +1,17 @@
|
|||
package io.gitlab.jfronny.libjf.unsafe;
|
||||
|
||||
import io.gitlab.jfronny.libjf.LibJf;
|
||||
import io.gitlab.jfronny.libjf.unsafe.inject.FabricLauncherClassUnlocker;
|
||||
import io.gitlab.jfronny.libjf.unsafe.inject.KnotClassLoaderInterfaceAccessor;
|
||||
import net.fabricmc.loader.api.LanguageAdapter;
|
||||
import net.fabricmc.loader.impl.FabricLoaderImpl;
|
||||
|
||||
public class JfLanguageAdapter implements LanguageAdapter {
|
||||
@Override
|
||||
public native <T> T create(net.fabricmc.loader.api.ModContainer mod, String value, Class<T> type);
|
||||
|
||||
static {
|
||||
FabricLoaderImpl.INSTANCE.getGameProvider().unlockClassPath(new FabricLauncherClassUnlocker(new KnotClassLoaderInterfaceAccessor(Thread.currentThread().getContextClassLoader())));
|
||||
DynamicEntry.execute(LibJf.MOD_ID + ":preEarly", UltraEarlyInit.class, s -> s.instance().init());
|
||||
DynamicEntry.execute(LibJf.MOD_ID + ":early", UltraEarlyInit.class, s -> s.instance().init());
|
||||
LibJf.LOGGER.info("LibJF unsafe init completed");
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
package io.gitlab.jfronny.libjf.unsafe.inject;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.loader.impl.launch.FabricLauncher;
|
||||
import net.fabricmc.loader.impl.launch.MappingConfiguration;
|
||||
import net.fabricmc.loader.impl.util.UrlUtil;
|
||||
import net.fabricmc.loader.impl.util.log.Log;
|
||||
import net.fabricmc.loader.impl.util.log.LogCategory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.jar.Manifest;
|
||||
|
||||
public record FabricLauncherClassUnlocker(KnotClassLoaderInterfaceAccessor classLoader) implements FabricLauncher {
|
||||
static {
|
||||
System.err.println("[libjf-unsafe-v0] Preparing to unlock classpath via reflection");
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappingConfiguration getMappingConfiguration() {
|
||||
return invalidCall();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addToClassPath(Path path, String... allowedPrefixes) {
|
||||
Log.debug(LogCategory.KNOT, "Adding " + path + " to classpath.");
|
||||
|
||||
try {
|
||||
URL url = UrlUtil.asUrl(path);
|
||||
classLoader.getDelegate().setAllowedPrefixes(url, allowedPrefixes);
|
||||
classLoader.addURL(url);
|
||||
} catch (MalformedURLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAllowedPrefixes(Path path, String... prefixes) {
|
||||
try {
|
||||
classLoader.getDelegate().setAllowedPrefixes(UrlUtil.asUrl(path), prefixes);
|
||||
} catch (MalformedURLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnvType getEnvironmentType() {
|
||||
return invalidCall();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isClassLoaded(String name) {
|
||||
return invalidCall();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> loadIntoTarget(String name) throws ClassNotFoundException {
|
||||
return invalidCall();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getResourceAsStream(String name) {
|
||||
return invalidCall();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassLoader getTargetClassLoader() {
|
||||
return invalidCall();
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getClassByteArray(String name, boolean runTransformers) throws IOException {
|
||||
return invalidCall();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Manifest getManifest(Path originPath) {
|
||||
return invalidCall();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDevelopment() {
|
||||
return invalidCall();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEntrypoint() {
|
||||
return invalidCall();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTargetNamespace() {
|
||||
return invalidCall();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Path> getClassPath() {
|
||||
return invalidCall();
|
||||
}
|
||||
|
||||
private <T> T invalidCall() {
|
||||
throw new IllegalStateException("unlockClassPath attempted to call a method not implemented here");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package io.gitlab.jfronny.libjf.unsafe.inject;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
|
||||
public record KnotClassDelegateAccessor(Object delegate) {
|
||||
private static final Method setAllowedPrefixesMethod;
|
||||
static {
|
||||
try {
|
||||
Class<?> klazz = Class.forName("net.fabricmc.loader.impl.launch.knot.KnotClassDelegate");
|
||||
setAllowedPrefixesMethod = klazz.getDeclaredMethod("setAllowedPrefixes", URL.class, String[].class);
|
||||
setAllowedPrefixesMethod.setAccessible(true);
|
||||
} catch (ClassNotFoundException | NoSuchMethodException e) {
|
||||
throw new IllegalStateException("Could not build accessor for class delegate. This version of fabric is likely not yet supported", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setAllowedPrefixes(URL url, String... prefixes) {
|
||||
try {
|
||||
setAllowedPrefixesMethod.invoke(delegate, url, prefixes);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw new IllegalStateException("Could not invoke setAllowedPrefixes on class delegate. This version of fabric is likely not yet supported", e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package io.gitlab.jfronny.libjf.unsafe.inject;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
|
||||
public record KnotClassLoaderInterfaceAccessor(ClassLoader loader) {
|
||||
private static final Method addURLMethod;
|
||||
private static final Method getDelegateMethod;
|
||||
static {
|
||||
try {
|
||||
Class<?> klazz = Class.forName("net.fabricmc.loader.impl.launch.knot.KnotClassLoaderInterface");
|
||||
addURLMethod = klazz.getDeclaredMethod("addURL", URL.class);
|
||||
addURLMethod.setAccessible(true);
|
||||
getDelegateMethod = klazz.getDeclaredMethod("getDelegate");
|
||||
getDelegateMethod.setAccessible(true);
|
||||
} catch (ClassNotFoundException | NoSuchMethodException e) {
|
||||
throw new IllegalStateException("Could not build accessor for class loader. This version of fabric is likely not yet supported", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void addURL(URL url) {
|
||||
try {
|
||||
addURLMethod.invoke(loader, url);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw new IllegalStateException("Could not invoke addURL on class loader. This version of fabric is likely not yet supported", e);
|
||||
}
|
||||
}
|
||||
|
||||
public KnotClassDelegateAccessor getDelegate() {
|
||||
try {
|
||||
return new KnotClassDelegateAccessor(getDelegateMethod.invoke(loader));
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw new IllegalStateException("Could not invoke getDelegate on class loader. This version of fabric is likely not yet supported", e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,7 +17,7 @@
|
|||
},
|
||||
"mixins": ["libjf-unsafe-v0.mixins.json"],
|
||||
"depends": {
|
||||
"fabricloader": ">=0.12.0",
|
||||
"fabricloader": ">=0.12.12",
|
||||
"minecraft": "*",
|
||||
"libjf-base": ">=${version}"
|
||||
},
|
||||
|
|
|
@ -22,7 +22,9 @@
|
|||
"fabricloader": ">=0.12.0",
|
||||
"minecraft": "*",
|
||||
"libjf-base": ">=${version}",
|
||||
"libjf-config-v0": ">=${version}"
|
||||
"libjf-config-v0": ">=${version}",
|
||||
"fabric-lifecycle-events-v1": "*",
|
||||
"fabric-command-api-v1": "*"
|
||||
},
|
||||
"custom": {
|
||||
"modmenu": {
|
||||
|
|
Loading…
Reference in New Issue