diff --git a/injector/injector.gradle.kts b/injector/injector.gradle.kts index d4a843ad72..7b2943edfb 100644 --- a/injector/injector.gradle.kts +++ b/injector/injector.gradle.kts @@ -28,12 +28,21 @@ dependencies { implementation(group = "org.ow2.asm", name = "asm-util", version = "8.0.1") implementation(group = "org.jetbrains", name = "annotations", version = "19.0.0") implementation(group = "com.google.guava", name = "guava", version = "23.2-jre") + implementation(group = "net.sf.jopt-simple", name = "jopt-simple", version = "5.0.1") } tasks.register("inject") { + dependsOn(":runelite-mixins:build") + dependsOn(":runescape-api:build") + dependsOn(":runescape-client:build") + + enableAssertions = true + main = "com.openosrs.injector.Injector" + val out = "${project.extra["rootPath"]}/runelite-client/build/injected/injected-client.oprs" + outputs.file(out) classpath = sourceSets["main"].runtimeClasspath - args(vanillaDep.singleFile, openosrsVersion) + args("--outmode", "jar", "--vanilla", vanillaDep.singleFile, "--version", openosrsVersion, "--output", out) outputs.upToDateWhen { false } diff --git a/injector/src/main/java/com/openosrs/injector/Injector.java b/injector/src/main/java/com/openosrs/injector/Injector.java index 95df2a568f..b6a5262d86 100644 --- a/injector/src/main/java/com/openosrs/injector/Injector.java +++ b/injector/src/main/java/com/openosrs/injector/Injector.java @@ -25,10 +25,20 @@ import com.openosrs.injector.rsapi.RSApi; import com.openosrs.injector.transformers.InjectTransformer; import com.openosrs.injector.transformers.Java8Ifier; import com.openosrs.injector.transformers.SourceChanger; -import static net.runelite.deob.util.JarUtil.load; -import static net.runelite.deob.util.JarUtil.save; import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Comparator; import java.util.Objects; +import joptsimple.ArgumentAcceptingOptionSpec; +import joptsimple.OptionParser; +import joptsimple.OptionSet; +import joptsimple.util.EnumConverter; +import net.runelite.asm.ClassFile; +import net.runelite.asm.ClassGroup; +import net.runelite.deob.util.JarUtil; +import static net.runelite.deob.util.JarUtil.load; import org.gradle.api.logging.Logger; import org.gradle.api.logging.Logging; @@ -36,22 +46,56 @@ public class Injector extends InjectData implements InjectTaskHandler { static final Logger log = Logging.getLogger(Injector.class); static Injector injector = new Injector(); - static File injectedClient = - new File("../runelite-client/src/main/resources/net/runelite/client/injected-client.oprs"); public static void main(String[] args) { - injector.vanilla = load(new File(args[0])); + OptionParser parser = new OptionParser(); + + ArgumentAcceptingOptionSpec vanillaFileOption = + parser.accepts("vanilla", "Vanilla OSRS gamepack file") + .withRequiredArg().ofType(File.class); + + ArgumentAcceptingOptionSpec oprsVerOption = + parser.accepts("version", "OpenOSRS version") + .withRequiredArg().ofType(String.class); + + ArgumentAcceptingOptionSpec outFileOption = + parser.accepts("output", "Output file, jar if outmode is jar, folder if outmode is files") + .withRequiredArg().ofType(File.class); + + ArgumentAcceptingOptionSpec outModeOption = + parser.accepts("outmode") + .withRequiredArg().ofType(OutputMode.class) + .withValuesConvertedBy(new EnumConverter<>(OutputMode.class) + { + @Override + public OutputMode convert(String value) + { + return super.convert(value.toUpperCase()); + } + }); + + OptionSet options = parser.parse(args); + String oprsVer = options.valueOf(oprsVerOption); + + injector.vanilla = load(options.valueOf(vanillaFileOption)); injector.deobfuscated = load( - new File("../runescape-client/build/libs/runescape-client-" + args[1] + ".jar")); + new File("../runescape-client/build/libs/runescape-client-" + oprsVer + ".jar")); injector.rsApi = new RSApi(Objects.requireNonNull( new File("../runescape-api/build/classes/java/main/net/runelite/rs/api/") .listFiles())); injector.mixins = load( - new File("../runelite-mixins/build/libs/runelite-mixins-" + args[1] + ".jar")); + new File("../runelite-mixins/build/libs/runelite-mixins-" + oprsVer + ".jar")); + + File oldInjected = new File("../runelite-client/src/main/resources/net/runelite/client/injected-client.oprs"); + if (oldInjected.exists()) + { + oldInjected.delete(); + } + injector.initToVanilla(); injector.injectVanilla(); - save(injector.getVanilla(), injectedClient); + save(injector.getVanilla(), options.valueOf(outFileOption), options.valueOf(outModeOption)); } public void injectVanilla() @@ -100,7 +144,7 @@ public class Injector extends InjectData implements InjectTaskHandler { final String name = injector.getName(); - log.info("[INFO] Starting {}", name); + log.lifecycle("[INFO] Starting {}", name); injector.start(); @@ -135,6 +179,52 @@ public class Injector extends InjectData implements InjectTaskHandler log.lifecycle("{} {}", name, transformer.getCompletionMsg()); } + private static void save(ClassGroup group, File output, OutputMode mode) + { + if (output.exists()) + { + try + { + Files.walk(output.toPath()).sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete); + } + catch (IOException e) + { + log.info("Failed to delete output directory contents."); + throw new RuntimeException(e); + } + } + + switch (mode) + { + case FILES: + saveFiles(group, output); + break; + case JAR: + output.getParentFile().mkdirs(); + JarUtil.save(group, output); + break; + } + } + + private static void saveFiles(ClassGroup group, File outDir) + { + try + { + outDir.mkdirs(); + + for (ClassFile cf : group.getClasses()) + { + File f = new File(outDir, cf.getName() + ".class"); + byte[] data = JarUtil.writeClass(group, cf); + Files.write(f.toPath(), data); + } + } + catch (IOException e) + { + e.printStackTrace(); + } + } + public void runChildInjector(com.openosrs.injector.injectors.Injector injector) { inject(injector); diff --git a/runelite-api/src/main/java/net/runelite/api/AbstractArchive.java b/injector/src/main/java/com/openosrs/injector/OutputMode.java similarity index 71% rename from runelite-api/src/main/java/net/runelite/api/AbstractArchive.java rename to injector/src/main/java/com/openosrs/injector/OutputMode.java index 0be27dfa46..6231b3a5b2 100644 --- a/runelite-api/src/main/java/net/runelite/api/AbstractArchive.java +++ b/injector/src/main/java/com/openosrs/injector/OutputMode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Noodleeater + * Copyright (c) 2021, ThatGamerBlue * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -22,27 +22,10 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package net.runelite.api; +package com.openosrs.injector; -/** - * Represents an archive of data, which is ordered into "groups" of "files". - */ -public interface AbstractArchive extends IndexDataBase +public enum OutputMode { - /** - * the methods bellow are usefull for reading byte data from the cache - */ - int getGroupCount(); - - byte[] getConfigData(int archiveId, int fileId); - - int[] getFileIds(int groupId); - - int[][] getFileIds(); - - byte[] getFile(int groupId, int fileId); - - int getGroupFileCount(int groupId); - - int[] getFileCounts(); + FILES, + JAR } diff --git a/runelite-api/src/main/java/net/runelite/api/Actor.java b/runelite-api/src/main/java/net/runelite/api/Actor.java index d8c297cb27..2f5e79954e 100644 --- a/runelite-api/src/main/java/net/runelite/api/Actor.java +++ b/runelite-api/src/main/java/net/runelite/api/Actor.java @@ -274,11 +274,6 @@ public interface Actor extends Renderable, Locatable */ void setSpotAnimFrame(int spotAnimFrame); - /** - * Get the number of cycles the SpotAnimation frame has been displayed for. - */ - int getSpotAnimFrameCycle(); - /** * Gets the canvas area of the current tile the actor is standing on. * @@ -372,16 +367,6 @@ public interface Actor extends Renderable, Locatable int getActionFrame(); int getActionFrameCycle(); - /* - This collection of methods gets extended debug information about the actor - - Used by dev tools - */ - - int getTurnLeftAnimation(); - - int getTurnRightAnimation(); - /** * Returns true if this NPC has died * diff --git a/runelite-api/src/main/java/net/runelite/api/Client.java b/runelite-api/src/main/java/net/runelite/api/Client.java index 94204b2383..2a7a6ca2fe 100644 --- a/runelite-api/src/main/java/net/runelite/api/Client.java +++ b/runelite-api/src/main/java/net/runelite/api/Client.java @@ -2148,27 +2148,27 @@ public interface Client extends GameEngine /** * various archives you might want to use for reading data from cache */ - AbstractArchive getSequenceDefinition_skeletonsArchive(); + IndexDataBase getSequenceDefinition_skeletonsArchive(); - AbstractArchive getSequenceDefinition_archive(); + IndexDataBase getSequenceDefinition_archive(); - AbstractArchive getSequenceDefinition_animationsArchive(); + IndexDataBase getSequenceDefinition_animationsArchive(); - AbstractArchive getNpcDefinition_archive(); + IndexDataBase getNpcDefinition_archive(); - AbstractArchive getObjectDefinition_modelsArchive(); + IndexDataBase getObjectDefinition_modelsArchive(); - AbstractArchive getObjectDefinition_archive(); + IndexDataBase getObjectDefinition_archive(); - AbstractArchive getItemDefinition_archive(); + IndexDataBase getItemDefinition_archive(); - AbstractArchive getKitDefinition_archive(); + IndexDataBase getKitDefinition_archive(); - AbstractArchive getKitDefinition_modelsArchive(); + IndexDataBase getKitDefinition_modelsArchive(); - AbstractArchive getSpotAnimationDefinition_archive(); + IndexDataBase getSpotAnimationDefinition_archive(); - AbstractArchive getSpotAnimationDefinition_modelArchive(); + IndexDataBase getSpotAnimationDefinition_modelArchive(); /** * use createBuffer to create a new byte buffer diff --git a/runelite-api/src/main/java/net/runelite/api/GameEngine.java b/runelite-api/src/main/java/net/runelite/api/GameEngine.java index 01b85ba512..2ab121a160 100644 --- a/runelite-api/src/main/java/net/runelite/api/GameEngine.java +++ b/runelite-api/src/main/java/net/runelite/api/GameEngine.java @@ -24,7 +24,6 @@ */ package net.runelite.api; -import net.runelite.api.hooks.DrawCallbacks; import java.awt.Canvas; /** @@ -53,8 +52,6 @@ public interface GameEngine */ boolean isClientThread(); - DrawCallbacks getDrawCallbacks(); - void resizeCanvas(); void setReplaceCanvasNextFrame(boolean replace); diff --git a/runelite-api/src/main/java/net/runelite/api/IndexDataBase.java b/runelite-api/src/main/java/net/runelite/api/IndexDataBase.java index 3c2e5db0b8..2a6f761b1e 100644 --- a/runelite-api/src/main/java/net/runelite/api/IndexDataBase.java +++ b/runelite-api/src/main/java/net/runelite/api/IndexDataBase.java @@ -38,4 +38,20 @@ public interface IndexDataBase * Get the child file ids for a given group */ int[] getFileIds(int group); + + /* + * the methods bellow are usefull for reading byte data from the cache + */ + + int getGroupCount(); + + byte[] getConfigData(int archiveId, int fileId); + + int[][] getFileIds(); + + byte[] getFile(int groupId, int fileId); + + int getGroupFileCount(int groupId); + + int[] getFileCounts(); } diff --git a/runelite-client/runelite-client.gradle.kts b/runelite-client/runelite-client.gradle.kts index 7cb1c17fa1..d5ec3e7412 100644 --- a/runelite-client/runelite-client.gradle.kts +++ b/runelite-client/runelite-client.gradle.kts @@ -126,7 +126,7 @@ tasks { } compileJava { - dependsOn("packInjectedClient") + // dependsOn("packInjectedClient") } processResources { @@ -155,9 +155,11 @@ tasks { register("packInjectedClient") { dependsOn(":injector:inject") - from("src/main/resources/") + from("build/injected/") include("**/injected-client.oprs") into("${buildDir}/resources/main") + + outputs.upToDateWhen { false } } jar { @@ -174,6 +176,10 @@ tasks { dependsOn(":runelite-script-assembler-plugin:assembleMojo") from("${buildDir}/scripts") + + dependsOn(":injector:inject") + + from("build/injected") } withType { diff --git a/runelite-client/src/main/java/net/runelite/client/rs/ClientLoader.java b/runelite-client/src/main/java/net/runelite/client/rs/ClientLoader.java index a3aa7fde29..2cee05ca92 100644 --- a/runelite-client/src/main/java/net/runelite/client/rs/ClientLoader.java +++ b/runelite-client/src/main/java/net/runelite/client/rs/ClientLoader.java @@ -72,6 +72,7 @@ import org.apache.commons.io.FileUtils; @SuppressWarnings("deprecation") public class ClientLoader implements Supplier { + private static final String INJECTED_CLIENT_NAME = "/injected-client.oprs"; private static final int NUM_ATTEMPTS = 6; private static File LOCK_FILE = new File(RuneLite.CACHE_DIR, "cache.lock"); private static File VANILLA_CACHE = new File(RuneLite.CACHE_DIR, "vanilla.cache"); @@ -132,9 +133,11 @@ public class ClientLoader implements Supplier // create the classloader for the jar while we hold the lock, and eagerly load and link all classes // in the jar. Otherwise the jar can change on disk and can break future classloads. File oprsInjected = new File(System.getProperty("user.home") + "/.openosrs/cache/injected-client.jar"); - InputStream initialStream = RuneLite.class.getResourceAsStream("injected-client.oprs"); - if (!oprsInjected.exists() || oprsInjected.length() != RuneLite.class.getResource("injected-client.oprs").getFile().length()) + InputStream initialStream = RuneLite.class.getResourceAsStream(INJECTED_CLIENT_NAME); + if (!oprsInjected.exists() || oprsInjected.length() != RuneLite.class.getResource(INJECTED_CLIENT_NAME).getFile().length()) + { FileUtils.copyInputStreamToFile(initialStream, oprsInjected); + } classLoader = createJarClassLoader(oprsInjected); } diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSNPCMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSNPCMixin.java index c90105f7e4..0c47ce539a 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSNPCMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSNPCMixin.java @@ -138,7 +138,7 @@ public abstract class RSNPCMixin implements RSNPC } int actionFrame = getActionFrame(); int poseFrame = getPoseFrame(); - int spotAnimFrame = getSpotAnimationFrame(); + int spotAnimFrame = getSpotAnimFrame(); try { // combine the frames with the frame cycle so we can access this information in the sequence methods diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSPlayerMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSPlayerMixin.java index 8bdab8f82c..2fd8f9b6a4 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSPlayerMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSPlayerMixin.java @@ -231,7 +231,7 @@ public abstract class RSPlayerMixin implements RSPlayer } int actionFrame = getActionFrame(); int poseFrame = getPoseFrame(); - int spotAnimFrame = getSpotAnimationFrame(); + int spotAnimFrame = getSpotAnimFrame(); try { // combine the frames with the frame cycle so we can access this information in the sequence methods diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSAbstractArchive.java b/runescape-api/src/main/java/net/runelite/rs/api/RSAbstractArchive.java index bddfbe6f71..1a0c8d2b68 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSAbstractArchive.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSAbstractArchive.java @@ -1,10 +1,9 @@ package net.runelite.rs.api; -import net.runelite.api.AbstractArchive; import net.runelite.api.IndexDataBase; import net.runelite.mapping.Import; -public interface RSAbstractArchive extends IndexDataBase, AbstractArchive +public interface RSAbstractArchive extends IndexDataBase { @Import("takeFile") @Override diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSActor.java b/runescape-api/src/main/java/net/runelite/rs/api/RSActor.java index 2c47403bbd..a61ced9d4f 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSActor.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSActor.java @@ -99,7 +99,7 @@ public interface RSActor extends RSRenderable, Actor void setGraphic(int id); @Import("spotAnimationFrame") - int getSpotAnimationFrame(); + int getSpotAnimFrame(); @Import("spotAnimationFrame") @Override @@ -165,11 +165,11 @@ public interface RSActor extends RSRenderable, Actor @Import("turnLeftSequence") @Override - int getTurnLeftAnimation(); + int getIdleRotateLeft(); @Import("turnRightSequence") @Override - int getTurnRightAnimation(); + int getIdleRotateRight(); @Import("walkSequence") @Override diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSAnimation.java b/runescape-api/src/main/java/net/runelite/rs/api/RSAnimation.java index 5c8d6f7684..97d5f4501d 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSAnimation.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSAnimation.java @@ -25,10 +25,9 @@ package net.runelite.rs.api; import net.runelite.api.Animation; -import net.runelite.api.Frames; import net.runelite.mapping.Import; -public interface RSAnimation extends Frames, Animation +public interface RSAnimation extends Animation { @Import("skeleton") RSSkeleton getSkeleton(); diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java b/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java index d6758ff330..f2263d79b6 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java @@ -26,7 +26,6 @@ package net.runelite.rs.api; import java.math.BigInteger; import java.util.Map; -import net.runelite.api.AbstractArchive; import net.runelite.api.Client; import net.runelite.api.SpritePixels; import net.runelite.api.World; @@ -1372,11 +1371,11 @@ public interface RSClient extends RSGameEngine, Client @Override @Import("NpcDefinition_archive") - AbstractArchive getNpcDefinition_archive(); + RSAbstractArchive getNpcDefinition_archive(); @Override @Import("ObjectDefinition_modelsArchive") - AbstractArchive getObjectDefinition_modelsArchive(); + RSAbstractArchive getObjectDefinition_modelsArchive(); @Override @Import("ObjectDefinition_archive") @@ -1388,19 +1387,19 @@ public interface RSClient extends RSGameEngine, Client @Override @Import("KitDefinition_archive") - AbstractArchive getKitDefinition_archive(); + RSAbstractArchive getKitDefinition_archive(); @Override @Import("KitDefinition_modelsArchive") - AbstractArchive getKitDefinition_modelsArchive(); + RSAbstractArchive getKitDefinition_modelsArchive(); @Override @Import("SpotAnimationDefinition_archive") - AbstractArchive getSpotAnimationDefinition_archive(); + RSAbstractArchive getSpotAnimationDefinition_archive(); @Override @Import("SpotAnimationDefinition_modelArchive") - AbstractArchive getSpotAnimationDefinition_modelArchive(); + RSAbstractArchive getSpotAnimationDefinition_modelArchive(); @Construct RSBuffer createBuffer(byte[] bytes); diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSDynamicObject.java b/runescape-api/src/main/java/net/runelite/rs/api/RSDynamicObject.java index 1c375ed3a1..b798ac6808 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSDynamicObject.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSDynamicObject.java @@ -1,10 +1,9 @@ package net.runelite.rs.api; import net.runelite.api.DynamicObject; -import net.runelite.api.Renderable; import net.runelite.mapping.Import; -public interface RSDynamicObject extends RSRenderable, DynamicObject, Renderable +public interface RSDynamicObject extends RSRenderable, DynamicObject { @Import("id") int getId();