make the injector more reliable

This commit is contained in:
ThatGamerBlue
2021-04-21 00:25:08 +01:00
parent e9f4e3ab58
commit 3e8318e18a
16 changed files with 168 additions and 83 deletions

View File

@@ -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<JavaExec>("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
}

View File

@@ -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<File> vanillaFileOption =
parser.accepts("vanilla", "Vanilla OSRS gamepack file")
.withRequiredArg().ofType(File.class);
ArgumentAcceptingOptionSpec<String> oprsVerOption =
parser.accepts("version", "OpenOSRS version")
.withRequiredArg().ofType(String.class);
ArgumentAcceptingOptionSpec<File> outFileOption =
parser.accepts("output", "Output file, jar if outmode is jar, folder if outmode is files")
.withRequiredArg().ofType(File.class);
ArgumentAcceptingOptionSpec<OutputMode> 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);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, Noodleeater <noodleeater4@gmail.com>
* Copyright (c) 2021, ThatGamerBlue <thatgamerblue@gmail.com>
* 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
}

View File

@@ -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
*

View File

@@ -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

View File

@@ -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);

View File

@@ -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();
}

View File

@@ -126,7 +126,7 @@ tasks {
}
compileJava {
dependsOn("packInjectedClient")
// dependsOn("packInjectedClient")
}
processResources {
@@ -155,9 +155,11 @@ tasks {
register<Copy>("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<BootstrapTask> {

View File

@@ -72,6 +72,7 @@ import org.apache.commons.io.FileUtils;
@SuppressWarnings("deprecation")
public class ClientLoader implements Supplier<Applet>
{
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<Applet>
// 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);
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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();

View File

@@ -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);

View File

@@ -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();