diff --git a/build.gradle b/build.gradle index c52b0f4..270ca20 100644 --- a/build.gradle +++ b/build.gradle @@ -1,11 +1,15 @@ -apply plugin: 'java-library' +apply plugin: 'java' java.toolchain.languageVersion = JavaLanguageVersion.of(8) repositories { + maven { url = 'https://maven.minecraftforge.net/' } mavenCentral() } dependencies { + implementation 'org.apache.logging.log4j:log4j-api:2.15.0' + implementation 'org.apache.logging.log4j:log4j-core:2.15.0' implementation 'org.ow2.asm:asm-commons:9.4' + implementation 'cpw.mods:modlauncher:8.1.3' } diff --git a/src/main/java/ftbsc/lll/loader/LilleroLoader.java b/src/main/java/ftbsc/lll/loader/LilleroLoader.java new file mode 100644 index 0000000..d7b0453 --- /dev/null +++ b/src/main/java/ftbsc/lll/loader/LilleroLoader.java @@ -0,0 +1,113 @@ +package ftbsc.lll.loader; + +import cpw.mods.modlauncher.serviceapi.ILaunchPluginService; + +import ftbsc.lll.IInjector; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.MethodNode; + +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.List; +import java.util.Map; +import java.util.ServiceLoader; +import java.util.stream.Collectors; + +public class LilleroLoader implements ILaunchPluginService { + public static final Logger LOGGER = LogManager.getLogger("LilleroLoader"); + public static final String NAME = "lillero-loader"; + + private List injectors = new ArrayList<>(); + + public LilleroLoader() { + LOGGER.info("Lillero Patch Loader initialized"); + } + + @Override + public String name() { + return NAME; + } + + + // Load mods requesting patches from resources + + @Override + public void offerResource(Path resource, String name) { + LOGGER.warn(String.format("Resource offered to us: %s @ '%s'", name, resource.toString())); + } + + @Override + public void addResources(List> resources) { + LOGGER.info("Resources being added:"); + for (Map.Entry row : resources) { + LOGGER.info(String.format("> %s @ '%s'", row.getKey(), row.getValue().toString())); + try { + URL jarUrl = new URL("file:" + row.getValue().toString()); + URLClassLoader loader = new URLClassLoader(new URL[] { jarUrl }); + for (IInjector inj : ServiceLoader.load(IInjector.class, loader)) { + LOGGER.info(String.format("Registering injector %s", inj.name())); + this.injectors.add(inj); + } + } catch (MalformedURLException e) { + LOGGER.error(String.format("Malformed URL for resource %s - 'file:%s'", row.getKey(), row.getValue().toString())); + } + } + } + + + // Filter only classes we need to patch + + @Override + public EnumSet handlesClass(Type classType, final boolean isEmpty) { + throw new IllegalStateException("Outdated ModLauncher"); //mixin does it + } + + private static final EnumSet YAY = EnumSet.of(Phase.BEFORE); + private static final EnumSet NAY = EnumSet.noneOf(Phase.class); + + @Override + public EnumSet handlesClass(Type classType, final boolean isEmpty, final String reason) { + if (isEmpty) return NAY; + // TODO can I make a set of target classes to make this faster + for (IInjector inj : this.injectors) { + if (inj.targetClass().equals(classType.getClassName())) + return YAY; + } + return NAY; + } + + + // Process classes and inject methods + + @Override + public int processClassWithFlags(Phase phase, ClassNode classNode, Type classType, String reason) { + LOGGER.debug("Processing class {} in phase {} of {}", classType.getClassName(), phase.name(), reason); + List relevantInjectors = this.injectors.stream() + .filter(i -> i.targetClass().equals(classType.getClassName())) + .collect(Collectors.toList()); + boolean modified = false; + for (MethodNode method : classNode.methods) { + for (IInjector inj : relevantInjectors) { + if ( + inj.methodName().equals(method.name) && + inj.methodDesc().equals(method.desc) + ) { + LOGGER.info(String.format("Patching %s.%s with %s", classType.getClassName(), method.name, inj.name())); + inj.inject(classNode, method); // TODO catch patching exceptions + modified = true; + } + } + } + + return modified ? ComputeFlags.COMPUTE_FRAMES : ComputeFlags.NO_REWRITE; + } +} diff --git a/src/main/resources/META-INF/services/cpw.mods.modlauncher.serviceapi.ILaunchPluginService b/src/main/resources/META-INF/services/cpw.mods.modlauncher.serviceapi.ILaunchPluginService new file mode 100644 index 0000000..fa0dc41 --- /dev/null +++ b/src/main/resources/META-INF/services/cpw.mods.modlauncher.serviceapi.ILaunchPluginService @@ -0,0 +1 @@ +ftbsc.lll.loader.LilleroLoader