Asm mixins that "work"

This commit is contained in:
ThatGamerBlue
2019-05-16 14:36:19 +01:00
parent ada157ae9d
commit c9d7fc4c23
80 changed files with 39711 additions and 1759 deletions

1
extended-mixin-processor/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
dependency-reduced-pom.xml

View File

@@ -0,0 +1,231 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>runelite-parent</artifactId>
<groupId>net.runelite</groupId>
<version>1.5.24-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>extended-mixin-processor</artifactId>
<packaging>maven-plugin</packaging>
<name>extended-mixin-processor Maven Plugin</name>
<url>https://www.runelitepl.us</url>
<prerequisites>
<maven>${maven.version}</maven>
</prerequisites>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.version>3.3.9</maven.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>${maven.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>${maven.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-artifact</artifactId>
<version>${maven.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-compat</artifactId>
<version>${maven.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.6.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-testing</groupId>
<artifactId>maven-plugin-testing-harness</artifactId>
<version>3.3.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.runelite</groupId>
<artifactId>runelite-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>net.runelite.rs</groupId>
<artifactId>runescape-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>net.runelite</groupId>
<artifactId>client-patch</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>27.1-jre</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.sigpipe/jbsdiff -->
<dependency>
<groupId>io.sigpipe</groupId>
<artifactId>jbsdiff</artifactId>
<version>1.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.javassist/javassist -->
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.24.1-GA</version>
</dependency>
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>net.lingala.zip4j</groupId>
<artifactId>zip4j</artifactId>
<version>1.3.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.ow2.asm/asm -->
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm-all</artifactId>
<version>6.0_BETA</version>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_maven-plugin_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-plugin-plugin</artifactId>
<version>3.6.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<plugin>
<artifactId>maven-invoker-plugin</artifactId>
<version>3.1.0</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-plugin-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<!-- <goalPrefix>maven-archetype-plugin</goalPrefix> -->
<skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
</configuration>
<executions>
<execution>
<id>mojo-descriptor</id>
<goals>
<goal>descriptor</goal>
</goals>
</execution>
<execution>
<id>help-goal</id>
<goals>
<goal>helpmojo</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<minimizeJar>false</minimizeJar>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,65 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixinprocessor;
public class MethodGarbageValue
{
private final String type;
private final int value;
public MethodGarbageValue(int value)
{
if(value <= Byte.MAX_VALUE && value >= Byte.MIN_VALUE)
{
type = "B";
}
else if(value <= Short.MAX_VALUE && value >= Short.MIN_VALUE)
{
type = "S";
}
else
{
type = "I";
}
this.value = value;
}
public int getValue()
{
return value;
}
public String getType()
{
return type;
}
public String toString()
{
return "MethodGarbageValue[type="+getType()+",value="+getValue()+"]";
}
}

View File

@@ -0,0 +1,281 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixinprocessor;
import com.google.common.collect.ImmutableSet;
import com.google.common.io.ByteStreams;
import com.google.common.reflect.ClassPath;
import io.sigpipe.jbsdiff.Patch;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.LoaderClassPath;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import us.runelitepl.mixinprocessor.generators.AnnotationProcessor;
import us.runelitepl.mixinprocessor.generators.PatchGenerator;
import us.runelitepl.mixinprocessor.generators.StaticGenerator;
import us.runelitepl.mixinprocessor.generators.StaticStageTwoGenerator;
import us.runelitepl.mixinprocessor.parsers.GamepackDownloader;
import us.runelitepl.mixinprocessor.parsers.HooksParser;
import us.runelitepl.mixinprocessor.transformers.AsmMethodGarbageTransformer;
import us.runelitepl.mixinprocessor.transformers.AsmMethodSignatureTransformer;
import us.runelitepl.mixinprocessor.util.JavassistUtils;
import us.runelitepl.mixinprocessor.util.RefUtils;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.project.MavenProject;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Goal which touches a timestamp file.
*/
@Mojo(name = "process-mixins", defaultPhase = LifecyclePhase.PROCESS_CLASSES, requiresDependencyResolution =
ResolutionScope.COMPILE)
public class MixinProcessorMojo
extends AbstractMojo implements Opcodes
{
private static final String PATCHES_PACKAGE = "us.runelitepl.mixins";
/**
* Location of the file.
*/
@Parameter(defaultValue = "${project.build.directory}", property = "outputDir", required = true)
private File outputDirectory;
@Parameter(defaultValue = "${project}", required = true, readonly = true)
private MavenProject project;
@Parameter(property = "process-mixins.hooks", defaultValue = "hooks.json", required = true)
private String hooks;
@Parameter(property = "process-mixins.ops", defaultValue = "gamepack.deob.jar.op.json", required = true)
private String ops;
private static MixinProcessorMojo INST;
public static ClassPool classPool;
public static HashMap<String, Long> fieldDecoders = new HashMap<>();
public static HashMap<String, String> classNames = new HashMap<>();
public static HashMap<String, String> methodNames = new HashMap<>();
public static HashMap<String, String> fieldNames = new HashMap<>();
public static HashMap<String, Boolean> isFieldTagged = new HashMap<>();
public static HashMap<String, Boolean> isMethodTagged = new HashMap<>();
public static HashMap<String, MethodGarbageValue> methodGarbageValues = new HashMap<>();
public static HashMap<String, byte[]> gamepack = new HashMap<>();
public static final int BUFFER_SIZE = 1024 * 1024 * 4;
public void execute()
throws MojoExecutionException
{
INST = this;
try
{
List runtimeClasspathElements = project.getRuntimeClasspathElements();
URL[] runtimeUrls = new URL[runtimeClasspathElements.size()];
for (int i = 0; i < runtimeClasspathElements.size(); i++)
{
String element = (String) runtimeClasspathElements.get(i);
runtimeUrls[i] = new File(element).toURI().toURL();
}
URLClassLoader classLoader = new URLClassLoader(runtimeUrls,
Thread.currentThread().getContextClassLoader());
File outputFolder = new File(project.getBuild().getOutputDirectory());
File projectDir = new File(System.getProperty("user.dir"));
File hooksFile = new File(projectDir, hooks);
File opsFile = new File(projectDir, ops);
outputFolder.mkdirs();
GamepackDownloader.downloadGamepack(gamepack);
ByteArrayOutputStream patchOutputStream = new ByteArrayOutputStream(BUFFER_SIZE); // 4mb
HooksParser.run(hooksFile, opsFile);
classPool = new ClassPool();
classPool.appendClassPath((new LoaderClassPath(classLoader)));
for (Map.Entry<String, byte[]> entry : gamepack.entrySet())
{
byte[] b1_;
try (InputStream is = getClass().getResourceAsStream("/patch/" + entry.getKey() + ".class.bs"))
{
if (is == null)
{
stderr("IS null for %s", entry.getKey());
continue;
}
b1_ = ByteStreams.toByteArray(is);
}
patchOutputStream.reset();
Patch.patch(entry.getValue(), b1_, patchOutputStream);
entry.setValue(patchOutputStream.toByteArray());
classPool.makeClass(new ByteArrayInputStream(entry.getValue()));
}
HashMap<String, byte[]> finalClasses = new HashMap<>();
ImmutableSet<ClassPath.ClassInfo> classes =
ClassPath.from(classLoader).getTopLevelClassesRecursive(PATCHES_PACKAGE);
for (ClassPath.ClassInfo clazz : classes)
{
stderr("");
stderr("Annotations: %s", clazz.getSimpleName());
CtClass ctClass = classPool.get(clazz.getName());
String className = ctClass.getSimpleName();
className = RefUtils.getObbedClassName(className);
byte[] finalCode = JavassistUtils.getClassBytecode(ctClass);
finalCode = new AnnotationProcessor(className, finalCode).run();
finalClasses.put(className, finalCode);
}
for (Map.Entry<String, byte[]> entry : finalClasses.entrySet())
{
String className = entry.getKey();
byte[] finalCode = entry.getValue();
stderr("");
stderr("Pass 1: %s", className);
finalCode = new AsmMethodSignatureTransformer(className, finalCode).transform();
finalCode = new AsmMethodGarbageTransformer(className, finalCode, finalClasses).transform();
finalClasses.put(className, finalCode);
}
stderr("");
stderr("Pass Statics");
new StaticGenerator().run(finalClasses.get(RefUtils.STATICS_STRING));
new StaticStageTwoGenerator(finalClasses).run();
for (Map.Entry<String, byte[]> entry : finalClasses.entrySet())
{
String className = entry.getKey();
if (className == null)
{
stderr("Class name null? %s", entry.getValue().length);
continue;
}
if (className.endsWith(RefUtils.STATICS_STRING))
{
continue;
}
stderr("");
stderr("Pass 2: %s", className);
byte[] finalCode = entry.getValue();
finalCode = new PatchGenerator(className, finalCode).run();
entry.setValue(finalCode);
}
deleteDir(new File(outputFolder, "us/runelitepl/mixins"));
outputFolder = new File(outputFolder, "extended-mixins");
outputFolder.mkdirs();
for (Map.Entry<String, byte[]> entry : finalClasses.entrySet())
{
if (entry.getKey().contains(RefUtils.STATICS_STRING))
{
continue;
}
Files.write(new File(outputFolder, entry.getKey() + ".class").toPath(),
entry.getValue());
}
}
catch (Exception ex)
{
ex.printStackTrace();
throw new MojoExecutionException(ex.getMessage());
}
}
public void stderr(String s, Object... format)
{
getLog().info(String.format(s, format));
}
public static void log(String s, Object... format)
{
INST.stderr(s, format);
}
static void deleteDir(File file) throws IOException
{
if (!file.exists())
{
return;
}
Files.walk(file.toPath())
.sorted(Comparator.reverseOrder())
.map(Path::toFile)
.forEach(File::delete);
}
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixinprocessor.annotations;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Append
{
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixinprocessor.annotations;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Inject
{
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixinprocessor.annotations;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Overwrite
{
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixinprocessor.annotations;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Prepend
{
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixinprocessor.annotations;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Provided
{
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixinprocessor.annotations;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Reobfuscate
{
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixinprocessor.enums;
public enum InjectionType
{
INJECT,
APPEND,
OVERWRITE,
PREPEND,
PROVIDED;
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixinprocessor.generators;
import javassist.CannotCompileException;
import javassist.CtClass;
import us.runelitepl.mixinprocessor.MixinProcessorMojo;
import us.runelitepl.mixinprocessor.parsers.FieldAnnotationParser;
import us.runelitepl.mixinprocessor.parsers.MethodAnnotationParser;
import us.runelitepl.mixinprocessor.util.JavassistUtils;
import java.io.ByteArrayInputStream;
import java.io.IOException;
public class AnnotationProcessor
{
private final String className;
private final byte[] finalCode;
public AnnotationProcessor(String className, byte[] finalCode)
{
this.className = className;
this.finalCode = finalCode;
}
public byte[] run() throws IOException, CannotCompileException, ClassNotFoundException
{
byte[] newCode = finalCode;
CtClass clazz = MixinProcessorMojo.classPool.makeClass(new ByteArrayInputStream(newCode));
new FieldAnnotationParser(clazz).run();
new MethodAnnotationParser(clazz).run();
newCode = JavassistUtils.getClassBytecode(clazz);
return newCode;
}
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixinprocessor.generators;
import us.runelitepl.mixinprocessor.transformers.AnnotationRemoverTransformer;
import us.runelitepl.mixinprocessor.transformers.AsmMethodGarbageTransformer;
import us.runelitepl.mixinprocessor.transformers.AsmMethodSignatureTransformer;
import us.runelitepl.mixinprocessor.transformers.AsmNameTransformer;
import us.runelitepl.mixinprocessor.transformers.AsmStaticUsageTransformer;
import us.runelitepl.mixinprocessor.transformers.DoNothingTransformer;
import us.runelitepl.mixinprocessor.transformers.GetFieldDecoderTransformer;
import us.runelitepl.mixinprocessor.transformers.ProvidedRemoverTransformer;
public class PatchGenerator
{
private final String className;
private final byte[] bytecode;
public PatchGenerator(String className, byte[] bytecode)
{
this.className = className;
this.bytecode = bytecode;
}
public byte[] run()
{
byte[] newCode = bytecode;
newCode = new GetFieldDecoderTransformer(className, newCode).transform();
// https://asm.ow2.io/javadoc/org/objectweb/asm/commons/Remapper.html
// https://asm.ow2.io/javadoc/org/objectweb/asm/commons/ClassRemapper.html
newCode = new AsmStaticUsageTransformer(className, newCode).transform();
newCode = new AsmNameTransformer(className, newCode).transform();
newCode = new ProvidedRemoverTransformer(className, newCode).transform();
newCode = new AnnotationRemoverTransformer(className, newCode).transform();
newCode = new DoNothingTransformer(className, newCode).transform();
return newCode;
}
}

View File

@@ -0,0 +1,110 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixinprocessor.generators;
import javassist.CannotCompileException;
import javassist.CtClass;
import javassist.NotFoundException;
import us.runelitepl.mixinprocessor.MixinProcessorMojo;
import us.runelitepl.mixinprocessor.util.JavassistUtils;
import us.runelitepl.mixinprocessor.util.RefUtils;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.MethodNode;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
public class StaticGenerator
{
public static HashMap<String, ArrayList<MethodNode>> staticMethods = new HashMap<>();
public static HashMap<String, ArrayList<FieldNode>> staticFields = new HashMap<>();
public static Set<String> modifiedClasses = new HashSet<>();
public void run(byte[] bytecode) throws NotFoundException, IOException, CannotCompileException
{
ClassReader cr = new ClassReader(bytecode);
ClassNode node = new ClassNode();
cr.accept(node, 0);
for (Object aaa : node.methods)
{
MethodNode method = (MethodNode) aaa;
String methodName = method.name;
method.desc = RefUtils.reobMethodDescriptor(method.desc);
int access = method.access;
if ((access & 8) != 8)
{
continue;
}
String reobbed = RefUtils.reobMethodName(RefUtils.STATICS_STRING, methodName, method.desc);
if(reobbed == null)
{
MixinProcessorMojo.log("Failed to reob static method: %s %s", methodName, method.desc);
throw new RuntimeException();
}
String[] split = reobbed.split(" ");
method.name = split[1];
ArrayList<MethodNode> list = staticMethods.getOrDefault(split[0], new ArrayList<>());
list.add(method);
staticMethods.put(split[0], list);
modifiedClasses.add(split[0]);
}
for (Object aaa : node.fields)
{
FieldNode field = (FieldNode) aaa;
String fieldName = field.name;
field.desc = RefUtils.reobDescriptor(field.desc);
int access = field.access;
if ((access & 8) != 8)
{
continue;
}
String reobbed = RefUtils.reobFieldName(RefUtils.STATICS_STRING, fieldName, field.desc);
if(reobbed == null)
{
MixinProcessorMojo.log("Failed to reob static field: %s %s", fieldName, field.desc);
throw new RuntimeException();
}
String[] split = reobbed.split(" ");
field.name = split[1];
ArrayList<FieldNode> list = staticFields.getOrDefault(split[0], new ArrayList<>());
list.add(field);
staticFields.put(split[0], list);
modifiedClasses.add(split[0]);
}
}
}

View File

@@ -0,0 +1,261 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixinprocessor.generators;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AnnotationNode;
import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.TypeAnnotationNode;
import us.runelitepl.mixinprocessor.MixinProcessorMojo;
import us.runelitepl.mixinprocessor.parsers.MethodReflector;
import java.util.HashMap;
import static us.runelitepl.mixinprocessor.generators.StaticGenerator.modifiedClasses;
import static us.runelitepl.mixinprocessor.generators.StaticGenerator.staticFields;
import static us.runelitepl.mixinprocessor.generators.StaticGenerator.staticMethods;
public class StaticStageTwoGenerator implements Opcodes
{
private HashMap<String, byte[]> classes;
public StaticStageTwoGenerator(HashMap<String, byte[]> classes)
{
this.classes = classes;
}
public void run()
{
for (String className : modifiedClasses)
{
byte[] targetBytecode = classes.getOrDefault(className, null);
if (targetBytecode == null)
{
//create new class
ClassWriter cw = new ClassWriter(0);
FieldVisitor fv;
MethodVisitor mv;
cw.visit(V1_6, ACC_PUBLIC, className, null, "java/lang/Object", null);
if (staticMethods.get(className) != null)
{
for (MethodNode method : staticMethods.get(className))
{
mv = cw.visitMethod(method.access, method.name, method.desc, method.signature,
(String[]) method.exceptions.toArray(new String[0]));
MethodReflector reflector = new MethodReflector(mv);
method.accept(reflector);
}
}
if (staticFields.get(className) != null)
{
for (FieldNode field : staticFields.get(className))
{
fv = cw.visitField(field.access, field.name, field.desc, field.signature, field.value);
int i;
int n;
AnnotationNode annotation;
if (field.visibleAnnotations != null)
{
i = 0;
for (n = field.visibleAnnotations.size(); i < n; ++i)
{
annotation = (AnnotationNode) field.visibleAnnotations.get(i);
annotation.accept(fv.visitAnnotation(annotation.desc, true));
}
}
if (field.invisibleAnnotations != null)
{
i = 0;
for (n = field.invisibleAnnotations.size(); i < n; ++i)
{
annotation = (AnnotationNode) field.invisibleAnnotations.get(i);
annotation.accept(fv.visitAnnotation(annotation.desc, false));
}
}
TypeAnnotationNode typeAnnotation;
if (field.visibleTypeAnnotations != null)
{
i = 0;
for (n = field.visibleTypeAnnotations.size(); i < n; ++i)
{
typeAnnotation = (TypeAnnotationNode) field.visibleTypeAnnotations.get(i);
typeAnnotation.accept(fv
.visitTypeAnnotation(typeAnnotation.typeRef, typeAnnotation.typePath,
typeAnnotation.desc, true));
}
}
if (field.invisibleTypeAnnotations != null)
{
i = 0;
for (n = field.invisibleTypeAnnotations.size(); i < n; ++i)
{
typeAnnotation = (TypeAnnotationNode) field.invisibleTypeAnnotations.get(i);
typeAnnotation.accept(fv
.visitTypeAnnotation(typeAnnotation.typeRef, typeAnnotation.typePath,
typeAnnotation.desc, false));
}
}
if (field.attrs != null)
{
i = 0;
for (n = field.attrs.size(); i < n; ++i)
{
fv.visitAttribute((Attribute) field.attrs.get(i));
}
}
fv.visitEnd();
}
}
cw.visitEnd();
targetBytecode = cw.toByteArray();
}
else
{
ClassReader cr = new ClassReader(targetBytecode);
ClassWriter cw = new ClassWriter(cr, 0);
ClassVisitor cv = new ClassVisitor(ASM6)
{
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces)
{
super.visit(version, access, name, signature, superName, interfaces);
if (staticMethods.get(className) != null)
{
for (MethodNode method : staticMethods.get(className))
{
MethodVisitor mv = visitMethod(method.access, method.name, method.desc,
method.signature, (String[]) method.exceptions.toArray(new String[0]));
MethodReflector reflector = new MethodReflector(mv);
method.accept(reflector);
}
}
if (staticFields.get(className) != null)
{
for (FieldNode field : staticFields.get(className))
{
FieldVisitor fv = visitField(field.access, field.name, field.desc, field.signature,
field.value);
int i;
int n;
AnnotationNode annotation;
if (field.visibleAnnotations != null)
{
i = 0;
for (n = field.visibleAnnotations.size(); i < n; ++i)
{
annotation = (AnnotationNode) field.visibleAnnotations.get(i);
annotation.accept(fv.visitAnnotation(annotation.desc, true));
}
}
if (field.invisibleAnnotations != null)
{
i = 0;
for (n = field.invisibleAnnotations.size(); i < n; ++i)
{
annotation = (AnnotationNode) field.invisibleAnnotations.get(i);
annotation.accept(fv.visitAnnotation(annotation.desc, false));
}
}
TypeAnnotationNode typeAnnotation;
if (field.visibleTypeAnnotations != null)
{
i = 0;
for (n = field.visibleTypeAnnotations.size(); i < n; ++i)
{
typeAnnotation = (TypeAnnotationNode) field.visibleTypeAnnotations.get(i);
typeAnnotation.accept(fv
.visitTypeAnnotation(typeAnnotation.typeRef, typeAnnotation.typePath,
typeAnnotation.desc, true));
}
}
if (field.invisibleTypeAnnotations != null)
{
i = 0;
for (n = field.invisibleTypeAnnotations.size(); i < n; ++i)
{
typeAnnotation = (TypeAnnotationNode) field.invisibleTypeAnnotations.get(i);
typeAnnotation.accept(fv
.visitTypeAnnotation(typeAnnotation.typeRef, typeAnnotation.typePath,
typeAnnotation.desc, false));
}
}
if (field.attrs != null)
{
i = 0;
for (n = field.attrs.size(); i < n; ++i)
{
fv.visitAttribute((Attribute) field.attrs.get(i));
}
}
fv.visitEnd();
}
}
}
};
cr.accept(cv, 0);
targetBytecode = cw.toByteArray();
}
classes.put(className, targetBytecode);
}
}
}

View File

@@ -0,0 +1,110 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixinprocessor.parsers;
import javassist.CtClass;
import javassist.CtField;
import us.runelitepl.mixinprocessor.annotations.Append;
import us.runelitepl.mixinprocessor.annotations.Inject;
import us.runelitepl.mixinprocessor.annotations.Overwrite;
import us.runelitepl.mixinprocessor.annotations.Prepend;
import us.runelitepl.mixinprocessor.annotations.Provided;
import us.runelitepl.mixinprocessor.annotations.Reobfuscate;
import us.runelitepl.mixinprocessor.enums.InjectionType;
import us.runelitepl.mixinprocessor.util.RefUtils;
import static us.runelitepl.mixinprocessor.MixinProcessorMojo.isFieldTagged;
public class FieldAnnotationParser
{
private CtClass clazz;
public FieldAnnotationParser(CtClass clazz)
{
this.clazz = clazz;
}
public void run() throws ClassNotFoundException
{
for (CtField field : clazz.getDeclaredFields())
{
Object[] annotations = field.getAnnotations();
InjectionType type = null;
boolean reobfuscate = false;
for (Object obj : annotations)
{
reobfuscate = obj instanceof Reobfuscate || reobfuscate;
if (obj instanceof Inject)
{
type = InjectionType.INJECT;
}
else if (obj instanceof Append)
{
type = InjectionType.APPEND;
}
else if (obj instanceof Overwrite)
{
type = InjectionType.OVERWRITE;
}
else if (obj instanceof Prepend)
{
type = InjectionType.PREPEND;
}
else if (obj instanceof Provided)
{
type = InjectionType.PROVIDED;
}
}
String fieldOwner = field.getDeclaringClass().getSimpleName();
String fieldName = field.getName();
String fieldDescriptor = RefUtils.reobDescriptor(field.getSignature());
if (type == null)
{
throw new RuntimeException(
field.getDeclaringClass().getSimpleName() + "." + field.getName() + " is unannotated" +
"!");
}
if (type != InjectionType.PROVIDED && type != InjectionType.INJECT)
{
throw new RuntimeException(
field.getDeclaringClass().getSimpleName() + "." + field.getName() + " has an invalid " +
"annotation! @" + type);
}
if (reobfuscate)
{
isFieldTagged.put(fieldOwner + " " + fieldName + " " + fieldDescriptor, true);
}
}
}
}

View File

@@ -0,0 +1,91 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixinprocessor.parsers;
import us.runelitepl.mixinprocessor.util.WebUtils;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class GamepackDownloader
{
private static final String CONFIG_URL = "http://oldschool.runescape.com/jav_config.ws";
private static String codebase;
private static String initial_jar;
public static void downloadGamepack(HashMap<String, byte[]> output) throws IOException
{
parseConfig();
byte[] gamepackJarAry = WebUtils.downloadFile(getGamepackUrl());
ZipInputStream zipInputStream = new ZipInputStream(new ByteArrayInputStream(gamepackJarAry));
byte[] buffer = new byte[2048];
ZipEntry entry;
ByteArrayOutputStream fileContent = new ByteArrayOutputStream(1024*1024*4);
while ((entry = zipInputStream.getNextEntry()) != null)
{
if (entry.getName().startsWith("META-INF"))
{
continue;
}
String key = entry.getName().replace(".class", "");
int len = 0;
while((len = zipInputStream.read(buffer)) > 0)
{
fileContent.write(buffer, 0, len);
}
output.put(key, fileContent.toByteArray());
fileContent.reset();
}
zipInputStream.close();
}
private static void parseConfig() throws IOException
{
String pageText = WebUtils.getUrlContent(CONFIG_URL);
for (String line : pageText.split("\n"))
{
if (line.startsWith("codebase="))
{
codebase = line.replace("codebase=", "");
}
else if (line.startsWith("initial_jar="))
{
initial_jar = line.replace("initial_jar=", "");
}
}
}
public static String getGamepackUrl()
{
return codebase + initial_jar;
}
}

View File

@@ -0,0 +1,144 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixinprocessor.parsers;
import us.runelitepl.mixinprocessor.MethodGarbageValue;
import us.runelitepl.mixinprocessor.MixinProcessorMojo;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Map;
public class HooksParser
{
public static void run(File hooksFile, File opsFile) throws IOException, ParseException
{
JSONParser parser = new JSONParser();
//region hooksFile
String jsonContent = String.join("\n", Files.readAllLines(hooksFile.toPath()));
JSONArray array = (JSONArray) parser.parse(jsonContent);
for (Object object : array)
{
JSONObject rootObject = (JSONObject) object;
String c_obbedName = (String) rootObject.get("name");
String c_deobbedName = (String) rootObject.get("class");
MixinProcessorMojo.classNames.put(c_deobbedName, c_obbedName);
}
int failedFields = 0;
int failedMethods = 0;
for (Object object : array)
{
JSONObject rootObject = (JSONObject) object;
JSONArray fieldArray = (JSONArray) rootObject.get("fields");
for (Object fieldObj : fieldArray)
{
JSONObject field = (JSONObject) fieldObj;
String f_deobbedName = (String) field.get("field");
String f_obbedName = (String) field.get("name");
String f_descriptor = (String) field.get("descriptor");
String f_owner = (String) field.get("owner");
long f_decoder = (long) field.getOrDefault("decoder", (long) 1);
String f_deobbedOwner = null;
if(f_deobbedName.startsWith("__"))
{
continue;
}
for (Map.Entry<String, String> entry : MixinProcessorMojo.classNames.entrySet())
{
if (entry.getValue().equals(f_owner))
{
f_deobbedOwner = entry.getKey();
break;
}
}
if (f_deobbedOwner == null)
{
failedFields++;
//stderr("Failed to find deobbed owner for field %s.%s %s", f_owner, f_obbedName, f_descriptor);
continue;
}
MixinProcessorMojo.fieldNames.put(String.format("%s %s %s", f_deobbedOwner, f_deobbedName, f_descriptor),
String.format("%s %s", f_owner, f_obbedName));
MixinProcessorMojo.fieldDecoders.put(String.format("%s %s", f_deobbedOwner, f_deobbedName),
f_decoder);
}
JSONArray methodArray = (JSONArray) rootObject.get("methods");
for (Object methodObj : methodArray)
{
JSONObject method = (JSONObject) methodObj;
String m_deobbedName = (String) method.get("method");
String m_owner = (String) method.get("owner");
String m_deobbedOwner = null;
String m_obbedName = (String) method.get("name");
String m_descriptor = (String) method.get("descriptor");
if(m_deobbedName.startsWith("__"))
{
continue;
}
for (Map.Entry<String, String> entry : MixinProcessorMojo.classNames.entrySet())
{
if (entry.getValue().equals(m_owner))
{
m_deobbedOwner = entry.getKey();
break;
}
}
if (m_deobbedOwner == null)
{
failedMethods++;
//stderr("Failed to find deobbed owner for method %s.%s %s", m_owner, m_obbedName, m_descriptor);
continue;
}
MixinProcessorMojo.methodNames.put(String.format("%s %s %s", m_deobbedOwner, m_deobbedName, m_descriptor),
String.format("%s %s", m_owner, m_obbedName));
}
}
MixinProcessorMojo.log("%d unidentified fields", failedFields);
MixinProcessorMojo.log("%d unidentified methods", failedMethods);
//endregion
//region opsFile
String opsContent = String.join("\n", Files.readAllLines(opsFile.toPath()));
JSONObject opsRoot = (JSONObject) parser.parse(opsContent);
opsRoot.forEach((key, value) ->
{
String k = (String) key;
MixinProcessorMojo.methodGarbageValues.put(k, new MethodGarbageValue(Math.toIntExact((Long) value)));
});
//endregion
}
}

View File

@@ -0,0 +1,127 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixinprocessor.parsers;
import javassist.CtClass;
import javassist.CtMethod;
import us.runelitepl.mixinprocessor.MixinProcessorMojo;
import us.runelitepl.mixinprocessor.annotations.Append;
import us.runelitepl.mixinprocessor.annotations.Inject;
import us.runelitepl.mixinprocessor.annotations.Overwrite;
import us.runelitepl.mixinprocessor.annotations.Prepend;
import us.runelitepl.mixinprocessor.annotations.Provided;
import us.runelitepl.mixinprocessor.annotations.Reobfuscate;
import us.runelitepl.mixinprocessor.enums.InjectionType;
import us.runelitepl.mixinprocessor.util.RefUtils;
import static us.runelitepl.mixinprocessor.MixinProcessorMojo.isMethodTagged;
public class MethodAnnotationParser
{
private final CtClass patch;
public MethodAnnotationParser(CtClass patch)
{
this.patch = patch;
}
public void run() throws ClassNotFoundException
{
for(CtMethod method : patch.getDeclaredMethods())
{
Object[] annotations = method.getAnnotations();
boolean reobfuscate = false;
InjectionType type = null;
for (Object obj : annotations)
{
reobfuscate = obj instanceof Reobfuscate || reobfuscate;
if (obj instanceof Inject)
{
type = InjectionType.INJECT;
}
else if (obj instanceof Append)
{
type = InjectionType.APPEND;
}
else if (obj instanceof Overwrite)
{
type = InjectionType.OVERWRITE;
}
else if (obj instanceof Prepend)
{
type = InjectionType.PREPEND;
}
else if (obj instanceof Provided)
{
type = InjectionType.PROVIDED;
}
}
if (type == null)
{
throw new RuntimeException(
method.getDeclaringClass().getSimpleName() + "." + method.getName() + " is unannotated" +
"!");
}
String methodName = method.getName();
if (type == InjectionType.PREPEND)
{
if (!methodName.startsWith("prepend$"))
{
throw new RuntimeException(
method.getDeclaringClass().getSimpleName() + "." + method.getName() + " has a @Prepend " +
"annotation without beginning with \"prepend$\"!");
}
}
else if (type == InjectionType.APPEND)
{
if (!methodName.startsWith("append$"))
{
throw new RuntimeException(
method.getDeclaringClass().getSimpleName() + "." + method.getName() + " has a @Append " +
"annotation without beginning with \"append$\"!");
}
}
if(reobfuscate)
{
MixinProcessorMojo.log("Marking: %s %s %s", method.getDeclaringClass().getSimpleName(), methodName,
RefUtils.reobMethodDescriptor(method.getSignature()));
String r = String.format("%s %s %s", method.getDeclaringClass().getSimpleName(), methodName,
RefUtils.reobMethodDescriptor(method.getSignature()));
isMethodTagged.put(r, true);
}
}
}
}

View File

@@ -0,0 +1,329 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixinprocessor.parsers;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.Handle;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.TypePath;
public class MethodReflector extends MethodVisitor
{
private MethodVisitor target;
public MethodReflector(MethodVisitor target)
{
super(Opcodes.ASM6);
this.target = target;
}
public void visitCode()
{
if (target != null)
{
target.visitCode();
}
super.visitCode();
}
public void visitEnd()
{
if (target != null)
{
target.visitEnd();
}
super.visitEnd();
}
public void visitParameter(String var1, int var2)
{
if (target != null)
{
target.visitParameter(var1, var2);
}
super.visitParameter(var1, var2);
}
public AnnotationVisitor visitAnnotationDefault()
{
if (target != null)
{
target.visitAnnotationDefault();
}
return super.visitAnnotationDefault();
}
public AnnotationVisitor visitAnnotation(String var1, boolean var2)
{
if (target != null)
{
target.visitAnnotation(var1, var2);
}
return super.visitAnnotation(var1, var2);
}
public AnnotationVisitor visitTypeAnnotation(int var1, TypePath var2, String var3, boolean var4)
{
if (target != null)
{
target.visitTypeAnnotation(var1, var2, var3, var4);
}
return super.visitTypeAnnotation(var1, var2, var3, var4);
}
public AnnotationVisitor visitParameterAnnotation(int var1, String var2, boolean var3)
{
if (target != null)
{
target.visitParameterAnnotation(var1, var2, var3);
}
return super.visitParameterAnnotation(var1, var2, var3);
}
public void visitAttribute(Attribute var1)
{
if (target != null)
{
target.visitAttribute(var1);
}
super.visitAttribute(var1);
}
public void visitFrame(int var1, int var2, Object[] var3, int var4, Object[] var5)
{
if (target != null)
{
target.visitFrame(var1, var2, var3, var4, var5);
}
super.visitFrame(var1, var2, var3, var4, var5);
}
public void visitInsn(int var1)
{
if (target != null)
{
target.visitInsn(var1);
}
super.visitInsn(var1);
}
public void visitIntInsn(int var1, int var2)
{
if (target != null)
{
target.visitIntInsn(var1, var2);
}
super.visitIntInsn(var1, var2);
}
public void visitVarInsn(int var1, int var2)
{
if (target != null)
{
target.visitVarInsn(var1, var2);
}
super.visitVarInsn(var1, var2);
}
public void visitTypeInsn(int var1, String var2)
{
if (target != null)
{
target.visitTypeInsn(var1, var2);
}
super.visitTypeInsn(var1, var2);
}
public void visitFieldInsn(int var1, String var2, String var3, String var4)
{
if (target != null)
{
target.visitFieldInsn(var1, var2, var3, var4);
}
super.visitFieldInsn(var1, var2, var3, var4);
}
/**
* @deprecated
*/
public void visitMethodInsn(int var1, String var2, String var3, String var4)
{
if (target != null)
{
target.visitMethodInsn(var1, var2, var3, var4);
}
super.visitMethodInsn(var1, var2, var3, var4);
}
public void visitMethodInsn(int var1, String var2, String var3, String var4, boolean var5)
{
if (target != null)
{
target.visitMethodInsn(var1, var2, var3, var4, var5);
}
super.visitMethodInsn(var1, var2, var3, var4, var5);
}
public void visitInvokeDynamicInsn(String var1, String var2, Handle var3, Object... var4)
{
if (target != null)
{
target.visitInvokeDynamicInsn(var1, var2, var3, var4);
}
super.visitInvokeDynamicInsn(var1, var2, var3, var4);
}
public void visitJumpInsn(int var1, Label var2)
{
if (target != null)
{
target.visitJumpInsn(var1, var2);
}
super.visitJumpInsn(var1, var2);
}
public void visitLabel(Label var1)
{
if (target != null)
{
target.visitLabel(var1);
}
super.visitLabel(var1);
}
public void visitLdcInsn(Object var1)
{
if (target != null)
{
target.visitLdcInsn(var1);
}
super.visitLdcInsn(var1);
}
public void visitIincInsn(int var1, int var2)
{
if (target != null)
{
target.visitIincInsn(var1, var2);
}
super.visitIincInsn(var1, var2);
}
public void visitTableSwitchInsn(int var1, int var2, Label var3, Label... var4)
{
if (target != null)
{
target.visitTableSwitchInsn(var1, var2, var3, var4);
}
super.visitTableSwitchInsn(var1, var2, var3, var4);
}
public void visitLookupSwitchInsn(Label var1, int[] var2, Label[] var3)
{
if (target != null)
{
target.visitLookupSwitchInsn(var1, var2, var3);
}
super.visitLookupSwitchInsn(var1, var2, var3);
}
public void visitMultiANewArrayInsn(String var1, int var2)
{
if (target != null)
{
target.visitMultiANewArrayInsn(var1, var2);
}
super.visitMultiANewArrayInsn(var1, var2);
}
public AnnotationVisitor visitInsnAnnotation(int var1, TypePath var2, String var3, boolean var4)
{
if (target != null)
{
target.visitInsnAnnotation(var1, var2, var3, var4);
}
return super.visitInsnAnnotation(var1, var2, var3, var4);
}
public void visitTryCatchBlock(Label var1, Label var2, Label var3, String var4)
{
if (target != null)
{
target.visitTryCatchBlock(var1, var2, var3, var4);
}
super.visitTryCatchBlock(var1, var2, var3, var4);
}
public AnnotationVisitor visitTryCatchAnnotation(int var1, TypePath var2, String var3, boolean var4)
{
if (target != null)
{
target.visitTryCatchAnnotation(var1, var2, var3, var4);
}
return super.visitTryCatchAnnotation(var1, var2, var3, var4);
}
public void visitLocalVariable(String var1, String var2, String var3, Label var4, Label var5, int var6)
{
if (target != null)
{
target.visitLocalVariable(var1, var2, var3, var4, var5, var6);
}
super.visitLocalVariable(var1, var2, var3, var4, var5, var6);
}
public AnnotationVisitor visitLocalVariableAnnotation(int var1, TypePath var2, Label[] var3, Label[] var4, int[] var5, String var6, boolean var7)
{
if (target != null)
{
target.visitLocalVariableAnnotation(var1, var2, var3, var4, var5, var6, var7);
}
return super.visitLocalVariableAnnotation(var1, var2, var3, var4, var5, var6, var7);
}
public void visitLineNumber(int var1, Label var2)
{
if (target != null)
{
target.visitLineNumber(var1, var2);
}
super.visitLineNumber(var1, var2);
}
public void visitMaxs(int var1, int var2)
{
if (target != null)
{
target.visitMaxs(var1, var2);
}
super.visitMaxs(var1, var2);
}
}

View File

@@ -0,0 +1,103 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixinprocessor.transformers;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
public class AnnotationRemoverTransformer extends AsmBaseTransformer
{
private final String className;
private final byte[] bytecode;
public AnnotationRemoverTransformer(String className, byte[] bytecode)
{
this.className = className;
this.bytecode = bytecode;
}
@Override
public byte[] transform()
{
ClassReader cr = new ClassReader(bytecode);
ClassWriter cw = new ClassWriter(cr, 0);
cr.accept(new ClassVisitor(Opcodes.ASM6, cw)
{
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions)
{
MethodVisitor visitor = super.visitMethod(access, name, desc, signature, exceptions);
MethodVisitor mv = new MethodVisitor(Opcodes.ASM6, visitor)
{
@Override
public AnnotationVisitor visitAnnotation(String descriptor, boolean hidden)
{
if (descriptor.equals(makeAnnotationDescriptor("Reobfuscate")))
{
return null;
}
return super.visitAnnotation(descriptor, hidden);
}
};
return mv;
}
@Override
public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value)
{
FieldVisitor visitor = super.visitField(access, name, descriptor, signature, value);
return new FieldVisitor(Opcodes.ASM6, visitor)
{
@Override
public AnnotationVisitor visitAnnotation(String descriptor, boolean hidden)
{
if (descriptor.equals(makeAnnotationDescriptor("Reobfuscate")))
{
return null;
}
if (descriptor.equals(makeAnnotationDescriptor("Provided")))
{
return null;
}
return super.visitAnnotation(descriptor, hidden);
}
};
}
}, 0);
return cw.toByteArray();
}
public static String makeAnnotationDescriptor(String s)
{
return "Lus/runelitepl/mixinprocessor/annotations/" + s + ";";
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixinprocessor.transformers;
import org.objectweb.asm.Opcodes;
import java.util.ArrayList;
public abstract class AsmBaseTransformer implements Opcodes
{
protected final ArrayList<String> validMethods = new ArrayList<>();
protected final ArrayList<String> validFields = new ArrayList<>();
protected void buildMethodList(){}
protected void buildFieldList(){}
public abstract byte[] transform();
}

View File

@@ -0,0 +1,109 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixinprocessor.transformers;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import us.runelitepl.mixinprocessor.MethodGarbageValue;
import us.runelitepl.mixinprocessor.MixinProcessorMojo;
import us.runelitepl.mixinprocessor.util.RefUtils;
import java.sql.Ref;
import java.util.HashMap;
public class AsmMethodGarbageTransformer extends AsmBaseTransformer
{
private final String className;
private final byte[] bytecode;
private HashMap<String, byte[]> classSet;
public AsmMethodGarbageTransformer(String className, byte[] bytecode, HashMap<String, byte[]> classSet)
{
this.className = className;
this.bytecode = bytecode;
this.classSet = classSet;
}
@Override
public byte[] transform()
{
ClassReader cr = new ClassReader(bytecode);
ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES);
cr.accept(new ClassVisitor(ASM6, cw)
{
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions)
{
MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
return new MethodVisitor(ASM6, mv)
{
@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf)
{
// get method owner.string(desc)
// check if method is annotated with @Reobfuscate
// brute force actual descriptor (check with shouldReobMethod(owner, name desc) )
// mv.visitLdcInsn(BIPUSH, constant);
// call super method with new descriptor
if(RefUtils.shouldReobMethod(owner, name, desc))
{
String nc = RefUtils.reobMethodName(owner, name, desc).split(" ")[0];
String nn = RefUtils.reobMethodName(owner, name, desc).split(" ")[1];
String nd = RefUtils.reobMethodDescriptor(desc);
MethodGarbageValue value;
if((value = MixinProcessorMojo.methodGarbageValues.getOrDefault(String.format("%s.%s%s",
nc, nn, nd), null)) != null)
{
switch (value.getType())
{
case "I":
super.visitLdcInsn(new Integer(value.getValue()));
break;
case "S":
super.visitIntInsn(SIPUSH, (short) value.getValue());
break;
case "B":
super.visitIntInsn(BIPUSH, (byte) value.getValue());
break;
}
}
}
super.visitMethodInsn(opcode, owner, name, desc, itf);
}
};
}
}, 0);
return cw.toByteArray();
}
}

View File

@@ -0,0 +1,107 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixinprocessor.transformers;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import us.runelitepl.mixinprocessor.MixinProcessorMojo;
import us.runelitepl.mixinprocessor.util.RefUtils;
public class AsmMethodSignatureTransformer extends AsmBaseTransformer
{
private final String className;
private final byte[] bytecode;
public AsmMethodSignatureTransformer(String className, byte[] bytecode)
{
this.className = RefUtils.deobClassName(className);
this.bytecode = bytecode;
}
@Override
public byte[] transform()
{
ClassReader cr = new ClassReader(bytecode);
ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES);
cr.accept(new ClassVisitor(ASM6, cw)
{
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String sig, String[] exceptions)
{
MethodVisitor mv = super.visitMethod(access, name, fixMethodDesc(className, name, desc), sig, exceptions);
return new MethodVisitor(ASM6, mv)
{
@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf)
{
super.visitMethodInsn(opcode, owner, name, fixMethodDesc(owner, name, desc), itf);
}
};
}
}, 0);
return cw.toByteArray();
}
private String fixMethodDesc(String className, String name, String desc)
{
if(className.startsWith(RefUtils.TYPE_PREFIX))
{
className = className.substring(RefUtils.TYPE_PREFIX.length());
}
if (RefUtils.shouldReobMethod(className, name, desc))
{
if (RefUtils.reobMethodName(className, name, desc) == null)
{
// get correct descriptor
String realDesc = null;
for (String s : RefUtils.POSSIBLE_GARBAGE_TYPES)
{
String check = RefUtils.reobMethodName(className, name, RefUtils.appendArgument(desc, s));
if (check != null)
{
realDesc = RefUtils.appendArgument(desc, s);
break;
}
}
if (realDesc == null)
{
MixinProcessorMojo.log("Failed to find actual method descriptor for %s.%s%s", className,
name, desc);
throw new RuntimeException();
}
// fixed = realDesc
MixinProcessorMojo.isMethodTagged.put(String.format("%s %s %s", className, name, realDesc), true);
return realDesc;
}
}
return desc;
}
}

View File

@@ -0,0 +1,175 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixinprocessor.transformers;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.commons.ClassRemapper;
import org.objectweb.asm.commons.Remapper;
import us.runelitepl.mixinprocessor.MixinProcessorMojo;
import us.runelitepl.mixinprocessor.util.RefUtils;
public class AsmNameTransformer extends AsmBaseTransformer
{
private String className;
private byte[] bytecode;
public AsmNameTransformer(String className, byte[] bytecode)
{
this.className = className;
this.bytecode = bytecode;
}
@Override
public byte[] transform()
{
ClassReader cr = new ClassReader(bytecode);
ClassWriter cw = new ClassWriter(cr, 0);
ClassRemapper remapper = new ClassRemapper(cw, new Remapper()
{
final String TYPE_PREFIX = "us/runelitepl/mixins/";
@Override
public String map(String internalName)
{
return super.map(internalName);
}
@Override
public String mapDesc(String descriptor)
{
return RefUtils.reobDescriptor(descriptor);
}
@Override
public String mapFieldName(String owner, String name, String descriptor)
{
String oldName = name;
String noPackage = owner.replace(TYPE_PREFIX, "");
descriptor = mapDesc(descriptor);
owner = RefUtils.reobClassName(owner);
if (RefUtils.shouldReobField(noPackage, name, descriptor))
{
name = RefUtils.reobFieldName(noPackage, name, descriptor);
if (name == null)
{
MixinProcessorMojo.log("Failed to reobfuscate field name %s.%s", noPackage, oldName);
throw new RuntimeException();
}
}
return super.mapFieldName(owner, name, descriptor);
}
@Override
public String mapInvokeDynamicMethodName(String name, String descriptor)
{
throw new UnsupportedOperationException("mapInvokeDynamicMethodName: Not implemented yet," +
"\nAsmNameTransformer#mapInvokeDynamicMethodName(" + name + ", " + descriptor + ")");
}
@Override
public String mapMethodDesc(String descriptor)
{
return RefUtils.reobMethodDescriptor(descriptor);
}
@Override
public String mapMethodName(String owner, String name, String descriptor)
{
String originalClass = owner;
if (originalClass.startsWith(TYPE_PREFIX))
{
originalClass = originalClass.substring(TYPE_PREFIX.length());
}
owner = RefUtils.reobClassName(owner);
if (name.startsWith("protect$"))
{
name = "1" + name;
}
// descriptor for reob checking is obfuscated
descriptor = mapMethodDesc(descriptor);
boolean reob = RefUtils.shouldReobMethod(originalClass, name, descriptor);
if (reob)
{
String originalName = name;
name = RefUtils.reobMethodName(originalClass, name, descriptor);
if (name == null)
{
MixinProcessorMojo.log("Failed to reobfuscate method: %s.%s%s", originalClass, originalName,
descriptor);
throw new RuntimeException();
}
}
//stderr("mapMethodName %s %s %s", owner, name, descriptor);
return super.mapMethodName(owner, name, descriptor);
}
@Override
public String mapPackageName(String name)
{
throw new UnsupportedOperationException("mapPackageName: Not implemented yet," +
"\nAsmNameTransformer#mapPackageName(" + name + ")");
}
@Override
public String mapSignature(String signature, boolean isTypeSig)
{
return super.mapSignature(signature, isTypeSig);
}
@Override
public String mapType(String internalName)
{
internalName = RefUtils.reobClassName(internalName);
return super.mapType(internalName);
}
@Override
public String[] mapTypes(String[] internalNames)
{
return super.mapTypes(internalNames);
}
@Override
public Object mapValue(Object value)
{
return super.mapValue(value);
}
});
cr.accept(remapper, 0);
return cw.toByteArray();
}
}

View File

@@ -0,0 +1,119 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixinprocessor.transformers;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import us.runelitepl.mixinprocessor.MixinProcessorMojo;
import us.runelitepl.mixinprocessor.util.RefUtils;
import static org.objectweb.asm.Opcodes.ASM6;
import static org.objectweb.asm.Opcodes.GETSTATIC;
import static org.objectweb.asm.Opcodes.INVOKESTATIC;
import static org.objectweb.asm.Opcodes.PUTSTATIC;
public class AsmStaticUsageTransformer extends AsmBaseTransformer
{
private String className;
private byte[] bytecode;
private final String TYPE_PREFIX = "us/runelitepl/mixins/";
public AsmStaticUsageTransformer(String className, byte[] bytecode)
{
this.className = className;
this.bytecode = bytecode;
}
@Override
public byte[] transform()
{
ClassReader cr = new ClassReader(bytecode);
ClassWriter cw = new ClassWriter(cr, 0);
ClassVisitor cv = new ClassVisitor(ASM6, cw)
{
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions)
{
MethodVisitor visitor = super.visitMethod(access, name, descriptor, signature, exceptions);
return new MethodVisitor(ASM6, visitor)
{
@Override
public void visitFieldInsn(int opcode, String owner, String name, String descriptor)
{
if ((opcode == GETSTATIC || opcode == PUTSTATIC) && owner.endsWith(RefUtils.STATICS_STRING))
{
String oldName = name;
String originalOwner = owner.replace(TYPE_PREFIX, "");
String temp = RefUtils.reobFieldNameDangerous(name, RefUtils.reobDescriptor(descriptor));
if (temp == null)
{
MixinProcessorMojo.log("Failed to reobfuscate class name for field %s %s %s", owner,
name, descriptor);
throw new RuntimeException();
}
owner = temp.split(" ")[0];
if (RefUtils.shouldReobField(originalOwner, name, RefUtils.reobDescriptor(descriptor)))
{
name = temp.split(" ")[1];
}
}
super.visitFieldInsn(opcode, owner, name, descriptor);
}
@Override
public void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface)
{
if(opcode == INVOKESTATIC && owner.endsWith(RefUtils.STATICS_STRING))
{
String originalOwner = owner.replace(TYPE_PREFIX, "");
String temp = RefUtils.reobMethodName(RefUtils.STATICS_STRING, name, descriptor);
if (temp == null)
{
MixinProcessorMojo.log("Failed to reobfuscate class name for method %s %s %s", owner,
name, descriptor);
throw new RuntimeException();
}
owner = temp.split(" ")[0];
if (RefUtils.shouldReobMethod(originalOwner, name, descriptor))
{
name = temp.split(" ")[1];
}
}
super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
}
};
}
};
cr.accept(cv, 0);
return cw.toByteArray();
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixinprocessor.transformers;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
public class DoNothingTransformer extends AsmBaseTransformer
{
private final String className;
private final byte[] bytecode;
public DoNothingTransformer(String className, byte[] bytecode)
{
this.className = className;
this.bytecode = bytecode;
}
@Override
public byte[] transform()
{
ClassReader cr = new ClassReader(bytecode);
ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES);
cr.accept(new ClassVisitor(ASM6, cw)
{}, 0);
return cw.toByteArray();
}
}

View File

@@ -0,0 +1,196 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixinprocessor.transformers;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import us.runelitepl.mixinprocessor.MixinProcessorMojo;
import us.runelitepl.mixinprocessor.util.RefUtils;
public class GetFieldDecoderTransformer extends AsmBaseTransformer
{
private final String className;
private final byte[] classFileBytecode;
public GetFieldDecoderTransformer(String className, byte[] bytes)
{
this.className = className;
this.classFileBytecode = bytes;
}
@Override
public void buildMethodList()
{
ClassReader cr = new ClassReader(classFileBytecode);
ClassWriter cw = new ClassWriter(cr, 0);
cr.accept(new ClassVisitor(Opcodes.ASM6, cw)
{
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature,
String[] exceptions)
{
final boolean[] valid = {true};
MethodVisitor visitor = super.visitMethod(access, name, desc, signature, exceptions);
return new MethodVisitor(Opcodes.ASM6, visitor)
{
int opcodeCount = 0;
@Override
public void visitEnd()
{
if (valid[0])
{
MixinProcessorMojo.log("Valid method: %s %s %s %s", access, name, desc, signature);
validMethods.add(access + " " + name + " " + desc + " " + signature);
}
}
@Override
public void visitVarInsn(int opcode, int var)
{
if (opcode != Opcodes.ALOAD || var != 0 || opcodeCount != 0)
{
valid[0] = false;
}
opcodeCount++;
super.visitVarInsn(opcode, var);
}
@Override
public void visitFieldInsn(int opcode, String owner, String fieldName, String signature)
{
if (opcode != Opcodes.GETFIELD || opcodeCount != 1)
{
valid[0] = false;
}
opcodeCount++;
super.visitFieldInsn(opcode, owner, fieldName, signature);
}
@Override
public void visitLdcInsn(Object o)
{
if (!(o instanceof Integer) && !(o instanceof Long))
{
valid[0] = false;
}
if (opcodeCount != 2)
{
valid[0] = false;
}
opcodeCount++;
super.visitLdcInsn(o);
}
@Override
public void visitInsn(int opcode)
{
switch (opcode)
{
case Opcodes.IMUL:
if (opcodeCount != 3)
{
valid[0] = false;
}
break;
case Opcodes.IRETURN:
if (opcodeCount != 4)
{
valid[0] = false;
}
break;
default:
valid[0] = false;
break;
}
opcodeCount++;
super.visitInsn(opcode);
}
};
}
}, 0);
}
public byte[] transform()
{
buildMethodList();
ClassReader cr = new ClassReader(classFileBytecode);
ClassWriter cw = new ClassWriter(cr, 0);
cr.accept(new ClassVisitor(Opcodes.ASM6, cw)
{
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions)
{
MethodVisitor visitor = super.visitMethod(access, name, desc, signature, exceptions);
if (!validMethods.contains(access + " " + name + " " + desc + " " + signature))
{
return visitor;
}
return new MethodVisitor(Opcodes.ASM6, visitor)
{
String target = null;
@Override
public void visitFieldInsn(int opcode, String owner, String fieldName, String signature)
{
target = fieldName;
super.visitFieldInsn(opcode, owner, fieldName, signature);
}
@Override
public void visitLdcInsn(Object o)
{
if (target != null)
{
if (o instanceof Long)
{
o = MixinProcessorMojo.fieldDecoders.getOrDefault(
RefUtils.deobClassName(className) + " " + target, 1L);
}
else
{
o = Math.toIntExact(MixinProcessorMojo.fieldDecoders.getOrDefault(RefUtils.deobClassName(className) +
" " + target,
1L));
}
}
MixinProcessorMojo.log("\tGetFieldDecoderTransformer: %s %s %s %s %s",
RefUtils.deobClassName(className), name, target, desc, o);
super.visitLdcInsn(o);
}
};
}
}, 0);
return cw.toByteArray();
}
}

View File

@@ -0,0 +1,101 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixinprocessor.transformers;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AnnotationNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode;
import us.runelitepl.mixinprocessor.MixinProcessorMojo;
public class ProvidedRemoverTransformer extends AsmBaseTransformer
{
private final String className;
private final byte[] bytecode;
public ProvidedRemoverTransformer(String className, byte[] bytecode)
{
this.className = className;
this.bytecode = bytecode;
}
public void buildMethodList()
{
ClassReader cr = new ClassReader(bytecode);
ClassNode node = new ClassNode();
cr.accept(node, 0);
for(Object obj : node.methods)
{
MethodNode method = (MethodNode) obj;
if(method == null)
{
MixinProcessorMojo.log("ProvidedRemoverTransformer: Method null?");
continue;
}
if(method.visibleAnnotations == null)
{
continue;
}
for(Object obj2 : method.visibleAnnotations)
{
AnnotationNode annot = (AnnotationNode) obj2;
if(annot.desc.equals(AnnotationRemoverTransformer.makeAnnotationDescriptor("Provided")))
{
validMethods.add(method.access + " " + method.desc + " " + method.name);
}
}
}
}
@Override
public byte[] transform()
{
buildMethodList();
ClassReader cr = new ClassReader(bytecode);
ClassWriter cw = new ClassWriter(cr, 0);
cr.accept(new ClassVisitor(Opcodes.ASM6, cw)
{
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature,
String[] exceptions)
{
if(validMethods.contains(access + " " + desc + " " + name))
{
return null;
}
return super.visitMethod(access, name, desc, signature, exceptions);
}
}, 0);
return cw.toByteArray();
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixinprocessor.util;
import javassist.CannotCompileException;
import javassist.CtClass;
import java.io.IOException;
public class JavassistUtils
{
public static byte[] getClassBytecode(CtClass clazz) throws IOException, CannotCompileException
{
clazz.stopPruning(true);
byte[] retVal = clazz.toBytecode();
clazz.defrost();
return retVal;
}
}

View File

@@ -0,0 +1,347 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixinprocessor.util;
import us.runelitepl.mixinprocessor.MixinProcessorMojo;
import java.util.Map;
public class RefUtils
{
public static final String TYPE_PREFIX = "us/runelitepl/mixins/";
public static final String STATICS_STRING = "_Statics_";
public static final String[] POSSIBLE_GARBAGE_TYPES = {"I", "B", "S"};
public static String deobClassName(String obbed)
{
for (Map.Entry<String, String> entry : MixinProcessorMojo.classNames.entrySet())
{
if (entry.getValue().equals(obbed))
{
return entry.getKey();
}
}
return obbed;
}
public static String getObbedClassName(String deob)
{
return MixinProcessorMojo.classNames.getOrDefault(deob, deob);
}
public static String reobClassName(String deobbed)
{
String old = deobbed;
if (deobbed.contains("/"))
{
deobbed = deobbed.replaceAll(TYPE_PREFIX, "");
deobbed = getObbedClassName(deobbed);
if (deobbed == null)
{
return old;
}
}
return deobbed;
}
@Deprecated
public static String reobFieldNameDangerous(String deob, String desc)
{
int i = 0;
Map.Entry<String, String> e1 = null;
for (Map.Entry<String, String> entry : MixinProcessorMojo.fieldNames.entrySet())
{
if (entry.getKey().endsWith(deob + " " + desc))
{
i++;
e1 = entry;
}
}
if (i == 1)
{
return e1.getValue();
}
return null;
}
@Deprecated
public static String reobMethodNameDangerous(String deob, String signature)
{
int i = 0;
Map.Entry<String, String> e1 = null;
for (Map.Entry<String, String> entry : MixinProcessorMojo.methodNames.entrySet())
{
if (entry.getKey().endsWith(" " + deob + " " + signature))
{
i++;
e1 = entry;
}
}
if (i == 1)
{
return e1.getValue();
}
return null;
}
public static String reobFieldName(String owner, String deob, String desc)
{
if (owner.equals(RefUtils.STATICS_STRING))
{
return reobFieldNameDangerous(deob, desc);
}
String asd = MixinProcessorMojo.fieldNames.getOrDefault(owner + " " + deob + " " + desc, null);
if (asd == null)
{
return null;
}
return asd.split(" ")[1];
}
public static String reobMethodName(String owner, String deob, String signature)
{
String prefix = "";
if(owner.startsWith(RefUtils.TYPE_PREFIX))
{
owner = owner.substring(RefUtils.TYPE_PREFIX.length());
}
if (deob.startsWith("prepend$"))
{
prefix = "prepend$";
deob = deob.substring("prepend$".length());
}
else if (deob.startsWith("append$"))
{
prefix = "append$";
deob = deob.substring("append$".length());
}
if (owner.equals(RefUtils.STATICS_STRING))
{
String retVal = reobMethodNameDangerous(deob, signature);
if (retVal == null)
{
return null;
}
String[] split = retVal.split(" ");
split[1] = prefix + split[1];
return String.join(" ", split);
}
String asd = MixinProcessorMojo.methodNames.getOrDefault(owner + " " + deob + " " + signature, null);
if (asd == null)
{
return null;
}
return prefix + asd.split(" ")[1];
}
@Deprecated
public static boolean shouldReobFieldDangerous(String deob, String desc)
{
int i = 0;
for (Map.Entry<String, Boolean> entry : MixinProcessorMojo.isFieldTagged.entrySet())
{
if (entry.getKey().endsWith(deob + " " + desc))
{
i++;
}
}
if (i == 1)
{
return true;
}
return false;
}
@Deprecated
public static boolean shouldReobMethodDangerous(String deob, String desc)
{
int i = 0;
for (Map.Entry<String, Boolean> entry : MixinProcessorMojo.isMethodTagged.entrySet())
{
if (entry.getKey().endsWith(" " + deob + " " + desc))
{
i++;
}
}
if (i == 1)
{
return true;
}
return false;
}
public static boolean shouldReobField(String owner, String deob, String desc)
{
if (owner.equals(RefUtils.STATICS_STRING))
{
return shouldReobFieldDangerous(deob, desc);
}
return MixinProcessorMojo.isFieldTagged.getOrDefault(owner + " " + deob + " " + desc, false);
}
public static boolean shouldReobMethod(String owner, String deob, String desc)
{
if(owner.startsWith(RefUtils.TYPE_PREFIX))
{
owner = owner.substring(RefUtils.TYPE_PREFIX.length());
}
if (owner.equals(RefUtils.STATICS_STRING))
{
return shouldReobMethodDangerous(deob, desc);
}
return MixinProcessorMojo.isMethodTagged.getOrDefault(owner + " " + deob + " " + desc, false);
}
public static String reobDescriptor(String descriptor)
{
if (!descriptor.startsWith("L"))
{
return descriptor;
}
if (!descriptor.contains("us/runelitepl/mixins/"))
{
return descriptor;
}
String orig = descriptor;
descriptor = descriptor.replace("us/runelitepl/mixins/", "");
descriptor = descriptor.substring(1, descriptor.length() - 1);
descriptor = getObbedClassName(descriptor);
if (descriptor == null)
{
return orig;
}
return "L" + descriptor + ";";
}
public static String reobMethodDescriptor(String descriptor)
{
int strIndex = 0;
if (descriptor.charAt(0) != '(')
{
throw new IllegalArgumentException("sig is not a method signature: " + descriptor);
}
StringBuilder deobbed = new StringBuilder(1024 * 1024);
while (strIndex < descriptor.length())
{
switch (descriptor.charAt(strIndex))
{
case '(':
case ')':
case 'I':
case 'B':
case 'J':
case 'S':
case 'D':
case 'F':
case 'C':
case 'Z':
case 'V':
case '[':
deobbed.append(descriptor.charAt(strIndex));
strIndex++;
break;
case 'L':
try
{
String sigPart = descriptor.substring(strIndex, descriptor.indexOf(";", strIndex) + 1);
String className = sigPart.substring(1, sigPart.length() - 1);
className = className.replace(TYPE_PREFIX, "");
String obbedName = MixinProcessorMojo.classNames.getOrDefault(className, null);
if (obbedName == null)
{
obbedName = className;
}
deobbed.append("L" + obbedName + ";");
strIndex += sigPart.length();
}
catch (StringIndexOutOfBoundsException ex)
{
System.err.println(
"Method signature %s is probably missing a semi-colon".replace("%s", descriptor));
throw ex;
}
break;
default:
throw new IllegalArgumentException("signature is invalid: " + descriptor);
}
}
return deobbed.toString();
}
public static String appendArgument(String desc, String append)
{
int strIndex = 0;
if (desc.charAt(0) != '(')
{
throw new IllegalArgumentException("sig is not a method signature: " + desc);
}
StringBuilder deobbed = new StringBuilder(1024 * 1024);
while (strIndex < desc.length())
{
switch (desc.charAt(strIndex))
{
case ')':
deobbed.append(append);
deobbed.append(")");
strIndex++;
break;
case '(':
case 'I':
case 'B':
case 'J':
case 'S':
case 'D':
case 'F':
case 'C':
case 'Z':
case 'V':
case '[':
deobbed.append(desc.charAt(strIndex));
strIndex++;
break;
case 'L':
try
{
String sigPart = desc.substring(strIndex, desc.indexOf(";", strIndex) + 1);
deobbed.append(sigPart);
strIndex += sigPart.length();
}
catch (StringIndexOutOfBoundsException ex)
{
System.err.println(
"Method signature %s is probably missing a semi-colon".replace("%s", desc));
throw ex;
}
break;
default:
throw new IllegalArgumentException("signature is invalid: " + desc);
}
}
return deobbed.toString();
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixinprocessor.util;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.util.stream.Collectors;
public class WebUtils
{
public static String getUrlContent(String url) throws IOException
{
String pageText;
URLConnection conn = new URL(url).openConnection();
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8)))
{
pageText = reader.lines().collect(Collectors.joining("\n"));
}
return pageText;
}
public static byte[] downloadFile(String urlText) throws IOException {
URL url = new URL(urlText);
ByteArrayOutputStream output = new ByteArrayOutputStream();
try (InputStream inputStream = url.openStream()) {
int n = 0;
byte [] buffer = new byte[ 1024 ];
while (-1 != (n = inputStream.read(buffer))) {
output.write(buffer, 0, n);
}
}
return output.toByteArray();
}
}

View File

@@ -0,0 +1,22 @@
Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,864 @@
{
"aa.aa(IILw;I)V" : -2035282490,
"aa.ab(IILjava/util/HashSet;IB)V" : 1,
"aa.ae(Lat;Ljd;IIFB)V" : 2,
"aa.ah(Ljava/util/HashSet;IIB)V" : 3,
"aa.ai(Ljd;I)Lay;" : 868142981,
"aa.aq(IIIIII)Ljava/util/List;" : 1174387475,
"aa.at(Ljd;IIB)V" : 2,
"aa.av(IILjava/util/HashSet;IB)V" : 1,
"aa.aw(Ljd;IIIIB)V" : 2,
"aa.az(IIIIB)V" : 1,
"aa.b(I)V" : -734187576,
"aa.c(IILw;[Llv;I)V" : -2131355084,
"aa.e(ILar;[Llv;Liz;Liz;I)V" : 16776959,
"aa.f(IIIILw;I)V" : 935523592,
"aa.g(IIIB)V" : 8,
"aa.h(Liz;Ljava/lang/String;Ljava/lang/String;I)Llv;" : -751125902,
"aa.h(Ljava/util/HashSet;Ljava/util/List;I)V" : 761583671,
"aa.js(Lia;S)V" : 179,
"aa.k(IILw;Lar;I)V" : -912761612,
"aa.l(Lar;[Llv;Laf;I)V" : -1342196991,
"aa.m(I)V" : -1460781870,
"aa.n(Liz;B)Z" : -3,
"aa.o(Lar;[Llv;Laf;I)V" : 1404817235,
"aa.p(Ljy;IIILw;I)V" : 451857695,
"aa.q(Ljava/util/List;I)V" : 457654499,
"aa.r(IIILjava/util/HashSet;I)V" : 866122217,
"aa.t(Ljava/util/HashSet;IIB)V" : 1,
"aa.x(Liz;Ljava/lang/String;Ljava/lang/String;I)[Llv;" : -6949303,
"aa.y(IILw;Lar;Laf;I)V" : -1385397238,
"ab.ar(Ldo;I)V" : -1176858873,
"ac.ao(ILcs;ZI)I" : 1813401528,
"ac.h(II)V" : 1006232361,
"ac.jy([Lia;IIIIIIIB)V" : -1,
"ad.hv(IIIIIIII)V" : -430708112,
"ad.it(I)V" : -983568512,
"ae.t(II)I" : 784278107,
"af.a(I)Z" : -2131769709,
"af.a(Liz;Liz;I)Z" : -1899763683,
"ag.a(Lgx;IB)V" : -1,
"ag.ai(ILcs;ZB)I" : -1,
"ag.f(III)Lif;" : -435462727,
"ag.g(IIII)Z" : 318472532,
"ag.h(IIII)[I" : -199162200,
"ag.p(I)V" : -1011260827,
"ag.x(IIS)Z" : 5119,
"ah.kc(Lia;II)Ljava/lang/String;" : -1474185799,
"aj.cg(Lgx;ZI)V" : -1515872014,
"aj.ch(Lgx;Lgx;IZB)V" : 0,
"aj.jw(Lia;III)V" : 572830405,
"aj.kk(Lia;I)Ljava/lang/String;" : -96310975,
"aj.x(Lge;II)V" : 628965387,
"ak.ki(II)V" : -1090851287,
"ak.s(Ljava/lang/String;I)Z" : -1560533677,
"an.a(Lag;B)V" : -1,
"an.at(ILcs;ZI)I" : 1073402399,
"an.g(III)Z" : 1060896560,
"an.h(III)Lif;" : -175568126,
"an.iw(Ljg;IIIS)V" : 1400,
"an.m(I)V" : 734935008,
"an.s(IIII)Z" : -1346882543,
"an.x(IIIB)[I" : 2,
"ap.a(I)V" : 75666286,
"ap.g(I)I" : 2098880503,
"ap.h(I)V" : 1211258439,
"aq.a(Lag;B)V" : -1,
"aq.g(III)Z" : 1060896560,
"aq.h(III)Lif;" : -175568126,
"aq.iu(IIIILjava/lang/String;Ljava/lang/String;III)V" : -1659892465,
"aq.s(IIII)Z" : -1346882543,
"aq.x(IIIB)[I" : 2,
"ar.a(IIIIIIIII)V" : -2059524070,
"ar.aj(ILcs;ZI)I" : 1205981872,
"ar.b(I)V" : -901714140,
"ar.e(I)V" : -478549233,
"ar.f(I)V" : 452761503,
"ar.g(II)I" : 1269863705,
"ar.h(I)V" : -1899763684,
"ar.m(I)V" : -1516729905,
"ar.n(I)V" : -58041941,
"ar.p(B)V" : 2,
"ar.q(I)V" : -1649013667,
"ar.s(III)I" : -1801980882,
"ar.s(Lbr;II)V" : 1598019254,
"ar.x(I)V" : 1645884426,
"as.a(Lgx;I)V" : -1899763684,
"as.hn(III)V" : -16711937,
"as.s(Lfs;Lgb;I)Lfa;" : 92068864,
"as.s(Lgx;I)V" : -1171328621,
"at.aw(Lfo;IIB)Lcz;" : -1,
"at.hy(III)I" : 1565568466,
"at.k(III)Z" : 600452826,
"at.o(III)Z" : 915702491,
"at.u(B)Z" : 10,
"at.y(III)Z" : -1304203093,
"av.a(Liz;Ljava/lang/String;ZI)V" : -1168992218,
"av.b(I)V" : -317778031,
"av.f(IIIIIIIIIII)Ljava/util/List;" : 1272296080,
"av.fd(I)V" : -1013343582,
"av.g(IIIIIIIII)V" : 1968023039,
"av.gn(I)V" : -1529421636,
"av.h(IIIILjava/util/HashSet;III)V" : -1503826011,
"av.lt(IIIZI)V" : 1023839648,
"av.n(III)F" : -2092073595,
"av.p(IIIII)Li;" : 54912543,
"av.x(IIIIIIIILjava/util/HashSet;Ljava/util/HashSet;IIZI)V" : -350567508,
"aw.gf(I)Z" : -25482427,
"ax.ge(IIIIS)V" : 254,
"ay.a(Lge;I)V" : 413663544,
"ay.f(II)V" : -1832203148,
"ay.fa(Lia;III)V" : -2035282490,
"ay.fb(IB)V" : -1,
"ay.s(II)Ljd;" : 256302879,
"ay.s(Lin;IIIBZI)V" : 488112187,
"az.jl(Lia;IIZI)V" : 321367859,
"az.k(IIB)Z" : 1,
"az.s(III)I" : -1587813654,
"b.s(IB)Ljy;" : 1,
"b.x(B)I" : 2,
"ba.a(IB)Lcs;" : -1,
"ba.a(II)V" : -1476367704,
"ba.m([BIIIIIIILen;[Lfk;S)V" : 3138,
"ba.q(I)Ldv;" : 270868885,
"ba.s(IIIIB)V" : -1,
"bb.a(IIILfk;I)Z" : -747978109,
"bb.hw(B)V" : 0,
"bc.a(I)J" : 1696302624,
"bc.aa(Ljava/lang/String;S)V" : 335,
"bc.ah(Lkx;B)Z" : 0,
"bc.c(Ljava/lang/String;I)V" : 582720271,
"bc.f(Lkx;ZB)Z" : 1,
"bc.g(Lgx;IB)V" : 0,
"bc.im(III)V" : 2028526097,
"bc.l(B)Z" : 2,
"bc.m(Ljava/lang/String;B)V" : 125,
"bc.o(Ljava/lang/String;I)V" : -1157261130,
"bc.p(Lkx;I)Z" : -1555038210,
"bc.v(I)Z" : -1393904298,
"bc.x(I)V" : 1950661086,
"bd.ie(II)V" : 181127396,
"bd.o(ILcs;ZI)I" : 413151829,
"be.iv(IIIII)V" : -325933819,
"be.n(Lia;II)V" : 1817349453,
"be.s(Ljava/lang/String;B)Ljava/io/File;" : 2,
"be.u(ILcs;ZB)I" : 0,
"be.x([BB)Lcs;" : 11,
"bf.aa(B)V" : 101,
"bf.ab(I)V" : 142936820,
"bf.ah(S)V" : 200,
"bf.ai(Ljava/lang/String;I)V" : -790939352,
"bf.al(I)Llh;" : -1432486026,
"bf.an(I)V" : -668210151,
"bf.aq(B)Ljava/awt/Container;" : 17,
"bf.as(ILjava/lang/String;ZI)V" : -1600069416,
"bf.b(I)V" : -1709249029,
"bf.c(I)Z" : 671133062,
"bf.e(I)V" : -721353869,
"bf.f(Ljava/lang/Object;I)V" : 721091452,
"bf.h(III)V" : -508854098,
"bf.k(IIIB)V" : 1,
"bf.l(B)V" : 1,
"bf.p(B)Lff;" : 1,
"bf.t(I)V" : -1101149948,
"bf.v(I)V" : 546631502,
"bg.a(IS)Ljc;" : 129,
"bh.a(Lm;Lm;I)I" : -513481130,
"bh.g(I)Lbt;" : -1460580553,
"bh.gg(I)V" : 283302901,
"bi.e(ILcs;ZI)I" : -1073407294,
"bi.gd(I)V" : -2017298644,
"bj.a(IB)Z" : 29,
"bj.a(Lgx;I)Ljava/lang/Integer;" : 781966774,
"bk.gu(Lbq;I)V" : -847852752,
"bk.jc(II)Z" : -1251166831,
"bk.ku(IIII)Lbk;" : -2131355082,
"bl.a(CI)B" : 1789306866,
"bl.f(Ljava/lang/Object;ZI)[B" : -1859268163,
"bl.g(I)Z" : 459972945,
"bl.jv(Lia;I)Lia;" : 388836110,
"bl.m(B)V" : -2,
"bl.p(B)V" : 3,
"bl.x(I)V" : -2005241970,
"bl.x(IB)Z" : 0,
"bm.a(IIIIB)V" : 0,
"bm.s(IB)Lby;" : -2,
"bn.g(I)V" : 260585226,
"bn.id([Lia;IIIIIIIIB)V" : 8,
"bn.io(Ljava/lang/String;Lia;B)Ljava/lang/String;" : 30,
"bn.s(ZZI)Llv;" : 1183417792,
"bn.x(Lbf;B)V" : 5,
"bo.a(IB)Ljf;" : 3,
"bo.av(ILcs;ZI)I" : -1854356000,
"bo.f(Lge;B)V" : 2,
"bo.f(Ljava/awt/event/MouseEvent;I)I" : 578646374,
"bo.il(IIIII)V" : 1757949424,
"bp.a(I)Z" : -1433048567,
"bp.a(II)Lln;" : 302241702,
"bq.a(Lin;II)V" : 1001198726,
"bq.bd(IIIIIII)V" : 611628477,
"bq.bi(II)V" : -1433857362,
"bq.bz(IIIIIII)V" : 1567325514,
"bq.f(ILcs;ZI)I" : -1899763682,
"bq.f(Lbu;Lbu;IZIZI)I" : 1226102711,
"bq.h(ILcs;ZB)I" : -1,
"br.kv(Ljava/lang/String;ZI)V" : 1790593369,
"bs.a(I)V" : -355288644,
"bs.av([BB)[B" : 1,
"bs.ji(III)V" : 548342891,
"bt.at(I)V" : -1263025777,
"bt.gi(Lbq;II)V" : -1529490784,
"bt.s(I)Lgx;" : 74387722,
"bt.s(IIII)I" : -781205087,
"bt.v(ILcs;ZB)I" : 1,
"bu.a(IIB)I" : 1,
"bu.b(I)Z" : -1114257374,
"bu.e(I)Z" : -1716454843,
"bu.h([BZI)Ljava/lang/Object;" : 738732180,
"bu.n(I)Z" : 1001949846,
"bu.r(I)Z" : -1318371617,
"bu.t(I)Z" : -556326313,
"bv.a(I)V" : 1118589205,
"bv.is(Ljava/lang/String;Ljava/lang/String;IIIIZI)V" : 936248646,
"bw.a(IILfu;Lfk;I)Z" : -1973878234,
"bw.a(Lgx;B)V" : 9,
"bw.b(IIBI)V" : 1555038206,
"bw.e(IIBB)V" : -1,
"bw.h(B)V" : 126,
"bw.h(I)Z" : -1285553478,
"bw.m(B)I" : 1,
"bw.p(B)V" : 8,
"bw.q(I)Ldv;" : 270868885,
"bw.r(I)Z" : -1348553985,
"bw.s(B)Z" : 1,
"bw.x(B)V" : 100,
"bx.q(Lia;I[B[BB)V" : 0,
"bx.s(IB)Ljx;" : -2,
"by.ad(II)V" : -264070302,
"by.ah(IZII)V" : 261286606,
"bz.jn([Lia;Lia;ZI)V" : 1459213909,
"bz.t(ILcs;ZB)I" : 3,
"c.ib(IIIII)V" : 27853463,
"c.r(I)V" : 1334087347,
"cb.aa(ILcs;ZI)I" : 599221667,
"cb.az(ILcs;ZI)I" : -1971585838,
"cb.iz(IIIIIIIII)V" : 1136998422,
"cf.a([Ljava/lang/String;[SIIB)V" : 82,
"cf.q(IIIZII)J" : -184362900,
"cf.s(IB)Lia;" : -1,
"cg.h(II)I" : 368462775,
"cg.n(IIIB)I" : 13,
"ch.aw(ILcs;ZB)I" : -1,
"ch.s(CII)C" : 1742925831,
"ch.x(Ljava/lang/String;B)Ljava/lang/Class;" : 0,
"ck.h(B)V" : 1,
"ck.s(B)V" : 1,
"ck.x(IS)Z" : 2047,
"client.ae(I)V" : 839842829,
"client.aj(I)V" : -1093400736,
"client.au(ZB)V" : -2,
"client.av(B)V" : 1,
"client.ff(II)V" : -920552638,
"client.fi(I)V" : 610258376,
"client.fm(I)V" : -465272380,
"client.fo(I)V" : -401328439,
"client.fu(B)V" : 0,
"client.gh(B)V" : 2,
"client.gl(I)V" : -265842676,
"client.hg(Lck;I)Z" : 16776961,
"client.ic(I)Z" : 1896111338,
"client.ip(ZB)V" : 15,
"client.iy(I)V" : -1774724327,
"client.ja(Lia;I)V" : 838714686,
"client.ju(I)V" : -756058437,
"client.ln(I)Lkx;" : 49412185,
"client.r(I)V" : -1611272948,
"client.x(CII)I" : 1762474913,
"cm.a(IBI)V" : 65534,
"cm.hd(IIIIIIII)V" : -759447942,
"cm.q(I)Ldv;" : 270868885,
"cm.r(I)Z" : -1348553985,
"cm.s(IIZI)V" : 1378146881,
"co.q(I)Ldv;" : 270868885,
"cq.a(III)V" : -1070186518,
"cq.b(B)V" : -1,
"cq.gr(Ljava/lang/String;ZI)V" : -389570792,
"cq.n(B)V" : 9,
"cq.p(B)V" : -1,
"cq.q(I)V" : 628907907,
"cq.s(IB)I" : -1,
"cq.x(II)Ljava/lang/String;" : -324172300,
"cr.a(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;B)Lbl;" : 1,
"cr.s(II)Lbl;" : -1908347194,
"ct.a(IIIII)V" : -1426623809,
"ct.g(I)V" : 2019467883,
"ct.kb(Ljava/lang/String;I)V" : 1782634305,
"ct.p(Liz;II)Llv;" : 495439929,
"ct.q(I)Ldv;" : 270868885,
"ct.s(II)V" : 63583155,
"cx.m(B)Lld;" : 3,
"cy.hr(IB)V" : 1,
"cz.aj(II)V" : 1893251924,
"cz.at(I)V" : 1969212074,
"cz.au(B)V" : -1,
"cz.p([BIILen;[Lfk;I)V" : -402226336,
"da.b(CB)Z" : 1,
"da.f([BIII)I" : 1742376717,
"da.s([BIIB)V" : -1,
"da.x(ZI)V" : 495439931,
"de.g(CB)C" : 13,
"de.g(IIB)Lcs;" : 1,
"de.g([BB)V" : 2,
"de.x(B)V" : 9,
"di.a([Ljava/lang/CharSequence;III)Ljava/lang/String;" : -1699387444,
"di.jr(Lia;IB)I" : 17,
"di.ko(Lia;IIII)V" : -529963254,
"di.y(ILcs;ZI)I" : 1635420646,
"dn.a([BI)[B" : -56213800,
"dn.g(II)I" : -1564370717,
"dn.ka([Lia;II)V" : -958295899,
"dn.s(IS)I" : 16382,
"dp.a(Ljava/lang/String;Ljava/lang/Throwable;B)V" : -1,
"dp.gz(I)V" : 174309589,
"ds.a(II[II)Lce;" : -1829245270,
"ds.g(I[II)Lce;" : -915277422,
"ds.s(II[II)Lce;" : 453356516,
"ds.x(I[IB)Lce;" : 0,
"du.a(I)I" : 705859952,
"du.f(II)Z" : -159952212,
"du.g(II)[I" : 1412569886,
"du.m(IB)V" : 0,
"du.p(I)V" : 674605951,
"du.x(II)I" : -1592582549,
"dw.b(Len;[Lfk;I)V" : 1851320005,
"dw.n(Lbu;B)V" : -1,
"dx.a(IIS)I" : 4999,
"dx.f(I)V" : -787206662,
"dx.g(I)V" : -1550843987,
"dx.h([BIIB)V" : 2,
"dx.m(B)V" : 3,
"dx.p([BIIB)V" : 1,
"dy.h(Ljava/lang/CharSequence;IZI)I" : 1182321164,
"dz.s(II)Ljh;" : -12306362,
"dz.s(II)Ljt;" : -1553990030,
"e.a(I[BLfb;B)V" : 0,
"e.fv(IB)V" : 6,
"e.fz(IIB)V" : 0,
"e.ho(ZLge;I)V" : -753481020,
"ea.a(Lkl;Lkl;I)I" : 236661620,
"ed.a(Lkl;Lkl;I)I" : -1524067389,
"ed.gt(Lbq;IIIIII)V" : -845922968,
"ee.a(Lkl;Lkl;S)I" : 1500,
"ee.fw(B)V" : 5,
"ef.g(Ljava/lang/String;ILjava/lang/String;I)Z" : -1896003594,
"ef.hc(ZLge;B)V" : 49,
"ef.jg([Lia;IB)V" : 25,
"ef.x(IZIZI)V" : -1718068584,
"eg.a(Lkl;Lkl;I)I" : 843610507,
"eg.ac(ILcs;ZB)I" : 127,
"eg.s(IB)Ljn;" : 8,
"eh.a(II)Lju;" : -686750587,
"eh.ft(ZS)V" : 513,
"eh.s(II)Lix;" : 449632382,
"eh.s(Ljava/io/File;ZI)Z" : 16711935,
"ei.jd([Lia;IIIZI)V" : -720054478,
"ei.p(II)I" : 1187869470,
"ej.a(Lkl;Lkl;I)I" : -1498357881,
"ej.gs(Lbw;I)Z" : 2018992164,
"ek.s(IIILjy;II)V" : 655507997,
"el.a(Lkl;Lkl;I)I" : -1691508553,
"el.x(I)V" : -992218542,
"em.a(Ljava/io/File;I)V" : -919664594,
"em.kl(Lia;IIII)V" : -32275069,
"em.s(Ljava/lang/CharSequence;I)Z" : -1575825717,
"ep.ab(ILcs;ZI)I" : -1899763684,
"ep.b(II)Lei;" : -1071218384,
"ep.s(III)V" : -523356652,
"eq.a(Lkl;Lkl;B)I" : -2,
"er.jo(Lia;IIIIIII)V" : -37715201,
"er.m(ILcs;ZB)I" : -1,
"es.n([BI)V" : 1477873953,
"et.q(CI)Z" : 601159240,
"et.x(II)I" : -4454457,
"eu.a(Lkl;Lkl;I)I" : -847269360,
"eu.s(III)V" : -1808152535,
"ev.hi(IIZB)V" : 18,
"ey.a(Lkl;Lkl;I)I" : 2046444105,
"ey.g(Ljava/lang/String;Ljava/lang/String;ZB)Lda;" : 2,
"f.a(Lm;Lm;I)I" : 1846671743,
"f.g(ILcs;ZI)I" : 908537385,
"f.g(Lgx;II)V" : -1787245950,
"f.kp(Ljava/lang/String;ZB)Ljava/lang/String;" : 0,
"f.kt(Lia;I)I" : 557758524,
"fa.hj(IIII)I" : -127120834,
"fa.p(Lkt;Lkt;Lkt;ZB)V" : -1,
"fa.x(B)V" : -1,
"fb.a(II)[B" : 663352422,
"fb.g(I[BIZB)Z" : 15,
"fb.s(I[BII)Z" : 345161743,
"fc.lh(I)V" : -861855527,
"fc.r(ILcs;ZI)I" : 2006195166,
"fg.a(B)V" : 2,
"fg.a(S)Lfa;" : 10144,
"fg.h(Lge;II)Z" : 97676263,
"fg.ix(II)Ljava/lang/String;" : 198383047,
"fg.s(III)I" : 1327459530,
"fh.hs(IIB)V" : 0,
"fh.s(II)Ljg;" : 620258019,
"fi.a(II)Z" : 1354142902,
"fi.a(Lll;B)I" : -1,
"fi.f(B)V" : 0,
"fi.g(I)I" : -827937127,
"fi.k([BIII)V" : -1233693102,
"fi.kw(Ljava/lang/String;B)V" : 3,
"fi.x(IIIIIIB)I" : 2,
"fi.x([BIIB)I" : 1,
"fj.a(II)Z" : -1899763683,
"fj.a(Ljava/io/File;Ljava/io/File;I)V" : -1114998342,
"fj.g(B)I" : 0,
"fj.g(IIIIIIB)I" : 79,
"fj.h(B)V" : 0,
"fj.s(B)I" : 1,
"fj.x([BIII)I" : -1210405788,
"fk.a(I)V" : -611770194,
"fk.g(IIIIZB)V" : 1,
"fk.m(IIIIIZB)V" : 1,
"fk.p(IIIIZI)V" : -500057817,
"fk.s(IIIIZI)V" : 1637050670,
"fl.a(II)Lje;" : 1521679245,
"fm.ht(IIII)V" : -523356652,
"fo.a([BILjava/lang/CharSequence;I)I" : 1159428966,
"fo.g([BIIII[Lfk;I)V" : 1327459530,
"fp.s(III)I" : 1327459530,
"ft.gc(Lbw;ZS)V" : 257,
"fu.as(ILcs;ZI)I" : 302016509,
"fu.s(Lge;B)V" : 48,
"fv.a(Liz;Liz;ZII)V" : -1720129294,
"fv.g(IIB)I" : 13,
"fw.s(IS)V" : 259,
"fx.a(B)Z" : 3,
"fx.ar(ILcs;ZI)I" : -31137372,
"fx.s([BIIB)V" : 70,
"fy.a([BII[BII)I" : 1944979934,
"fy.s([BI[BIIB)I" : 20,
"fz.q(Llv;I)V" : -1078540656,
"g.kx(S)V" : 2502,
"gb.a(B)I" : 1,
"gb.g(I)V" : 521895284,
"gb.s(I)I" : 99718613,
"gb.x(I)V" : -155012128,
"gc.a(IIII)I" : -1899763684,
"gc.c(ILcs;ZB)I" : -1,
"gc.h(IIIZIZB)V" : 23,
"gc.u(III)I" : 23878205,
"ge.a(Liz;IIB)[Lld;" : 23,
"ge.jp(I)Z" : -703700792,
"ge.jq(II)I" : 1887118654,
"ge.jr(I)I" : -1075465045,
"ge.jt([BIII)V" : 1292793924,
"ge.kj(I)V" : -91714,
"gh.l(ILcs;ZB)I" : 76,
"gi.p(Ljava/lang/CharSequence;B)I" : 8,
"gj.ga(I)V" : -2035282490,
"gm.x(Ljava/lang/CharSequence;I)[B" : -1293404993,
"gn.a(Lgx;[BI)V" : -858327323,
"go.a(IZI)[B" : -1296589171,
"gq.a(Ljava/lang/CharSequence;Ljava/lang/CharSequence;IB)I" : 5,
"gq.h(IIB)I" : 1,
"gq.kr(IIIILld;Lhk;I)V" : -1418612472,
"gx.ac(B)I" : 31,
"gx.ad(B)I" : -1,
"gx.ai([BIII)V" : -594273166,
"gx.aj(S)Ljava/lang/String;" : 257,
"gx.ak([IIII)V" : -81741600,
"gx.al(B)I" : -1,
"gx.am([IIIB)V" : 0,
"gx.ao(I)I" : -316163985,
"gx.ap([II)V" : 1621051798,
"gx.aq(I)I" : -442414275,
"gx.ar(I)Ljava/lang/String;" : 770756333,
"gx.as(I)Ljava/lang/String;" : -721135627,
"gx.au(I)Ljava/lang/String;" : 1888102756,
"gx.aw(I)I" : -2142523386,
"gx.ax([II)V" : -1139374613,
"gx.az(I)I" : -1651491166,
"gx.b(ZI)V" : 1173873020,
"gx.be(S)Z" : 1107,
"gx.bu(I)I" : 2024662838,
"gx.by(I)I" : 1509644456,
"gx.c(II)V" : 1219514079,
"gx.ch([BIII)V" : 763323993,
"gx.e(Ljava/lang/String;I)V" : 1504225874,
"gx.f(IZI)Ljava/lang/String;" : 582940071,
"gx.g(I)V" : -134910295,
"gx.h(ZI)V" : 1980995418,
"gx.l(Ljava/lang/CharSequence;I)V" : 1863463456,
"gx.o([BIII)V" : -757753561,
"gx.t(Ljava/lang/String;I)V" : -997423168,
"gx.v(II)V" : -1392094080,
"gy.gq(Lbq;I)V" : 33031345,
"gz.ly(I)V" : 1339304,
"h.p(Lbu;Lbu;IZI)I" : -1748952325,
"h.s(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V" : 763156645,
"hb.a(Lhl;[IIIII)V" : 1090105654,
"hb.hf(B)V" : -1,
"hb.s(Lhl;II)V" : -809158812,
"hc.a(Lds;[B[IB)Z" : 2,
"hc.gv(III)V" : -543069418,
"hc.r(CI)Z" : 1679390240,
"hk.a(III)Z" : -1128121077,
"hk.as(Ljy;B)Z" : 1,
"hk.b(Lia;IIIB)V" : 3,
"hl.an(ILcs;ZI)I" : -1910103371,
"hl.x(ILcs;ZI)I" : 385664937,
"hn.ab(II)V" : -36819028,
"hn.ah(II)V" : -1345756874,
"hn.ak(Lhl;I)I" : -520794056,
"hn.al(II)V" : -598595792,
"hn.am(Lhl;I)I" : -1122132199,
"hn.an(I)V" : 59932716,
"hn.ao(IS)V" : 128,
"hn.at(IB)V" : 1,
"hn.aw(II)V" : 167541606,
"hn.ax(Lhl;I)I" : 657286058,
"hn.b(Lhx;ZI)V" : -1551737624,
"hn.be(Lhl;[IIII)Z" : 92154578,
"hn.bf(B)V" : 1,
"hn.bo(Lhl;I)Z" : 1592628248,
"hn.g(Lhx;Liz;Lds;II)Z" : 338728781,
"hn.k(IIIB)V" : 1,
"hn.ls(Lgx;I)V" : -1236370027,
"hn.o(III)V" : 522712138,
"hn.u(IIII)V" : -1441077132,
"hn.y(Lhl;ZB)V" : 1,
"i.a(IB)Ljq;" : 13,
"i.m(II)I" : 328778210,
"ia.a([BI)Ljava/lang/String;" : -353252804,
"ia.b(ZB)Lld;" : 7,
"ia.e(IB)Lld;" : 16,
"ia.f(Lgx;B)V" : 7,
"ia.h(Lgx;I)V" : -1234429702,
"ia.m(Lgx;B)[I" : -1,
"ia.n(I)Lkt;" : 421753985,
"ia.o(ILjava/lang/String;I)V" : -1333519203,
"ia.p(Lgx;I)[Ljava/lang/Object;" : 542349862,
"ia.r(Lju;IZLil;B)Ldv;" : -2,
"ia.t(ZI)Lhk;" : -51731421,
"ic.b(Liz;IIB)Z" : -1,
"if.g([Lbu;II[I[II)V" : 1383511622,
"if.s(Lif;I)Z" : 818064734,
"ig.hu(Lbj;B)V" : 2,
"ii.n(IIIIIZB)Lld;" : 2,
"ik.g(Lge;I)V" : 1244850771,
"ik.hq(Lfh;I)V" : -1237176758,
"il.a([I[IZII)V" : -1797663590,
"il.f(I)V" : 684089267,
"il.g(IZI)V" : -310896557,
"il.h(Lgx;B)V" : 2,
"il.he(IIIIII)V" : 1597666720,
"il.m(I)Ldk;" : -398095808,
"il.p(Lju;ILju;IB)Ldv;" : 0,
"il.q(I)I" : -1107905560,
"il.s(IZI)V" : 258827147,
"in.cl(I)I" : -1072006222,
"in.dg(Lfb;I[BZB)V" : 1,
"in.dl(B)V" : 0,
"in.dn(II)Z" : 1536737195,
"in.ds(I[BZZI)V" : 956902428,
"in.dt(I)I" : -1062754734,
"in.dz(III)V" : -1693261231,
"in.q(II)I" : 1178383852,
"in.r(IB)V" : 9,
"io.p(ILcs;ZB)I" : 1,
"ip.hl(ZLge;I)V" : 1467913083,
"iq.f(IILld;FI)V" : 704611128,
"iq.g(IB)Lld;" : 0,
"iq.gb(IIIIZI)V" : 1785115947,
"iq.p(Lld;Lld;Llh;B)V" : 1,
"iq.s(II)V" : -2029849843,
"iq.x(III)V" : -2042722903,
"ir.f(I)V" : -2131355084,
"iu.ig(Lbw;IIII)V" : -685713479,
"iu.kz(IIIILld;Lhk;B)V" : 8,
"iv.a(Ljava/lang/CharSequence;I)Ljava/lang/String;" : -1913197059,
"iw.fh(IIB)V" : 2,
"iy.a(II)Lja;" : 299293337,
"iz.a([BB)V" : -1,
"iz.ab(Ljava/lang/String;Ljava/lang/String;I)Z" : 1244245246,
"iz.b(II)[B" : 987310919,
"iz.e(II)[B" : -1294518996,
"iz.f(II)Z" : -2035474006,
"iz.h(IIB)Z" : 0,
"iz.k(I)V" : -1119601835,
"iz.m(I)Z" : 35823373,
"iz.n(III)[B" : 516194823,
"iz.p(II)Z" : 541672068,
"iz.t(II)[I" : 431985491,
"iz.u(I)V" : -1524099318,
"iz.v(I[II)Z" : 227748206,
"iz.x(II[II)[B" : -834173405,
"j.a(Lag;B)V" : -1,
"j.g(CI)C" : -981963683,
"j.g(III)Z" : 1060896560,
"j.h(III)Lif;" : -175568126,
"j.hm(IIIIIIIIIB)V" : 13,
"j.iq(II)Ljava/lang/String;" : 1836496129,
"j.s(CI)Z" : 197071592,
"j.s(IIII)Z" : -1346882543,
"ja.g(Lgx;II)V" : 1365905715,
"ja.s(Lgx;B)V" : 23,
"jc.b(II)Ljc;" : 96183287,
"jc.e(ZI)Z" : 1314943295,
"jc.f(Ljc;Ljc;I)V" : -1552569050,
"jc.g(Lgx;I)V" : -1429982553,
"jc.l(ZI)Ldk;" : 1545641841,
"jc.m(II)Ldk;" : -573893718,
"jc.o(IIS)I" : 3147,
"jc.q(IB)Ldv;" : 4,
"jc.r(ZB)Ldk;" : 1,
"jc.t(ZI)Z" : 564174324,
"jc.u(ILjava/lang/String;I)Ljava/lang/String;" : -2051827725,
"jc.x(I)V" : 305928935,
"jc.x(Lgx;IB)V" : 0,
"jc.y(I)I" : 122221946,
"jd.f(ZI)Lld;" : 838332995,
"jd.h(I)V" : 65279,
"jd.n(Ljava/lang/String;B)Ljava/lang/String;" : 6,
"jd.p(II)Lld;" : 1990361836,
"jd.x(Lgx;II)V" : -2060573893,
"je.b(I)Lkt;" : -2064178208,
"je.f(B)Lld;" : 68,
"je.g(Lgx;IB)V" : -1,
"je.h(IB)Ljava/lang/String;" : 1,
"je.jx(IIIIII)V" : -508181654,
"je.m(CI)Z" : 760945280,
"je.m(I)Lld;" : -1778105957,
"je.q(I)Lld;" : -827937128,
"je.x(I)Lje;" : 943450442,
"jf.g(Lgx;II)V" : 214023150,
"jf.s(Lgx;B)V" : 3,
"jg.ah(ILcs;ZI)I" : 532847216,
"jg.b(III)I" : 10887810,
"jg.f(Lju;ILju;II)Ldv;" : -40433393,
"jg.h(Lgx;IB)V" : 64,
"jg.m(B)Ljg;" : 0,
"jg.n(ILjava/lang/String;I)Ljava/lang/String;" : -147724755,
"jg.p(I)Ldk;" : 1597666720,
"jg.q(B)Z" : -2,
"jg.s(Ljava/lang/String;ZLjava/lang/String;ZB)V" : -1,
"jg.x(Lgx;B)V" : 11,
"jh.g(Lgx;I)V" : -667595371,
"jh.h(IB)Ldv;" : 41,
"jh.x(Lgx;II)V" : -972042923,
"jl.a(Lgx;B)V" : 5,
"jl.ii(ILjava/lang/String;I)V" : -1675865809,
"jl.s(Lgx;II)V" : 572994941,
"jn.g(Lgx;I)V" : 96183287,
"jn.la(Ljava/lang/String;I)Ljava/lang/String;" : 477812378,
"jn.x(Lgx;II)V" : -1850197339,
"jo.g(Lgx;II)V" : 723793981,
"jo.h(II)V" : -740923085,
"jo.x(Lgx;III)V" : 384685616,
"jp.g(I)Z" : -498132400,
"jp.g(Lgx;II)V" : 424690960,
"jp.h(I)Lld;" : -380044805,
"jp.hp(ZI)V" : 1068773475,
"jp.s(Lgx;B)V" : 9,
"jp.x(B)Lld;" : 0,
"jq.au(ILcs;ZI)I" : -1963146961,
"jq.f(ILjava/lang/String;S)Ljava/lang/String;" : 5007,
"jq.h(III)I" : -698436080,
"jr.fn(II)V" : -1893789506,
"jr.g(Ljava/lang/CharSequence;B)Ljava/lang/String;" : -1,
"jr.jt(Lia;Ljc;IIZI)V" : -2033743109,
"jt.g(Lgx;I)V" : 721996786,
"jt.h(Ljava/lang/CharSequence;II[BII)I" : -1648858462,
"jt.k(ILcs;ZB)I" : 6,
"jt.x(Lgx;II)V" : 1576334712,
"ju.f(Ldv;III)Ldv;" : 132641558,
"ju.g(Lgx;II)V" : -613501112,
"ju.h(Ldv;II)Ldv;" : -1682213593,
"ju.m(Ldv;ILju;II)Ldv;" : 1211273008,
"ju.p(Ldv;II)Ldv;" : 172834485,
"ju.p(Lge;ILbw;II)V" : -1670832392,
"ju.q(Ldv;II)Ldv;" : -1048507799,
"ju.s(Lgx;I)V" : -1788727042,
"ju.x(B)V" : 0,
"jv.g(B)Lfa;" : 7,
"jw.a(II)Ljz;" : -1393220766,
"jw.g(Lgx;II)V" : 253176345,
"jw.h(II)V" : -89150727,
"jw.kd(Lbk;ZI)V" : -1454243751,
"jw.s(I)V" : 1378135916,
"jw.x(Lgx;III)V" : -467387569,
"jx.f(B)Ldk;" : 1,
"jx.g(Lgx;B)V" : 29,
"jx.h(I)Z" : -1555038209,
"jx.m(I)Ldk;" : -1339242269,
"jx.p(I)Z" : -1362075535,
"jx.s(Liz;III)Lld;" : 1385222262,
"jx.x(Lgx;IB)V" : 0,
"jy.b(II[[IIIILju;II)Ldv;" : 8388609,
"jy.e(I)Ljy;" : -1512852885,
"jy.f(II)Z" : 282955687,
"jy.g(S)V" : 8364,
"jy.h(Lgx;II)V" : -1717982543,
"jy.l(I)Z" : 150610019,
"jy.m(II[[IIIII)Lem;" : -372875047,
"jy.n(III)Ldk;" : -884974338,
"jy.q(II[[IIIIB)Ldv;" : 25,
"jy.r(IIB)I" : -1,
"jy.t(ILjava/lang/String;I)Ljava/lang/String;" : -1133392868,
"jy.x(Lgx;I)V" : 1763228330,
"jz.fs(IIII)V" : -1466898577,
"jz.g(Lgx;B)V" : 2,
"jz.h(I)Z" : -2131355083,
"jz.jp(Lia;B)Z" : -2,
"jz.x(Lgx;II)V" : -1511633123,
"k.hb(Lbw;IIBI)V" : -1717122274,
"k.m(B)V" : 2,
"ka.s(I)V" : -2839567,
"ka.x(I)V" : -670001098,
"kd.aa(Lkx;Lkx;I)Lkn;" : -2059524068,
"kd.ab(IB)Lkn;" : -1,
"kd.ah(I)V" : 1677000161,
"kd.an(Lkn;I)I" : -1066148450,
"kd.as(Ljava/util/Comparator;I)V" : 1772662082,
"kd.at(Lkn;I)V" : -818755498,
"kd.av(Lkn;I)V" : -1176966737,
"kd.l(Lkx;B)Z" : 100,
"kd.o(Lkx;I)Lkn;" : -1474250075,
"kd.v(Lkn;B)V" : 0,
"kd.y(Lkx;I)Lkn;" : -10040824,
"ke.a([Lkw;I)Ljava/util/HashMap;" : 943906518,
"kg.q(IIIIIILen;Lfk;I)V" : 330856458,
"kj.m(Ljava/util/Comparator;I)V" : -1871871525,
"kj.q(Lkn;Lkn;B)I" : 1,
"kl.bg(B)Z" : 1,
"km.f(I)V" : 592369164,
"km.g(I)V" : 1843719486,
"km.gj(II)V" : -1194096980,
"km.h(B)Z" : -1,
"km.s(I)Z" : -1813992429,
"kn.ae(I)Ljava/lang/String;" : 1341360476,
"kn.at(I)Ljava/lang/String;" : -1555038208,
"kn.av(Lkx;Lkx;I)V" : 275778859,
"kn.ih(IIIILjava/lang/String;I)V" : -1657907412,
"kn.ik(II)Z" : 271561465,
"kp.a(Lgx;Lgs;I)Lgs;" : -692792992,
"kr.g(Lkx;ZB)Z" : -1,
"kr.kh(Lgx;II)V" : -1134408571,
"kr.kn(Lia;I)V" : -2138249594,
"kr.n(Lgx;IB)V" : 1,
"ks.a(Lks;B)I" : 1,
"ku.g(Lgx;II)V" : -1361804166,
"kw.fk(I)V" : 1462687380,
"kw.fl(IZZZB)Lin;" : 6,
"kw.fr(B)V" : 0,
"kw.jj(B)V" : 1,
"kx.g(Lkx;I)I" : 1091130939,
"kx.s(I)Z" : 2085790353,
"ky.ck(Lgx;B)V" : 1,
"ky.cn(I)V" : 1819322040,
"ky.cr(Lgx;I)V" : -2138810208,
"ky.cv(Lkm;I)V" : -794082731,
"l.go(I)I" : 689623594,
"l.lg(I)V" : 212688817,
"l.x(IIIII)V" : 1330963020,
"lf.a(Liz;I)V" : 216314308,
"lg.a(Lkn;Lkn;B)I" : 0,
"lh.h(Llh;Llh;I)V" : -1899763684,
"lh.x(Llh;Llh;I)V" : 65281,
"li.a(Lgx;I)V" : 82212899,
"lk.a(Lkn;Lkn;B)I" : 3,
"lm.a(I)Lli;" : -1704489684,
"lo.ae(ILcs;ZI)I" : 491075880,
"lq.a(Liz;Liz;Liz;Lkt;Ljava/util/HashMap;[Llv;B)V" : 2,
"lq.aa(IIIIIII)V" : -1022244844,
"lq.ab(IIIIB)V" : 15,
"lq.ai(IIIB)V" : 4,
"lq.aj(III)V" : -1596162919,
"lq.an(IB)F" : 0,
"lq.ap(II)V" : -368766016,
"lq.aq(I)I" : 96183288,
"lq.ar(IIII)V" : -1654813278,
"lq.as(III)V" : -418862019,
"lq.at(I)I" : -1389281243,
"lq.au(II)Lag;" : -482362793,
"lq.az(B)Lif;" : 0,
"lq.b(I)Z" : 1196890805,
"lq.bb(S)Lat;" : 3647,
"lq.bg(II)Z" : -827937128,
"lq.bi(IZI)V" : 1401518352,
"lq.bn(ILif;S)Lif;" : 3622,
"lq.bo(II)V" : 517430306,
"lq.bp(I)Z" : 115992480,
"lq.br(IIIIIII)V" : -1670644894,
"lq.bv(II)Z" : 2068200578,
"lq.bw(B)Lat;" : 0,
"lq.bz(IZI)V" : -345932703,
"lq.c(IIIIIII)Z" : 977978274,
"lq.e(IIIZB)V" : -1,
"lq.f(I)V" : -1442221252,
"lq.g(IIZIIIII)V" : -311515493,
"lq.k(IIIB)V" : -1,
"lq.m(IIZI)V" : 443741720,
"lq.n(IIIB)Lag;" : 1,
"lq.p(I)V" : 946356797,
"lq.r(II)V" : -1958030248,
"lq.t(I)I" : -1613065466,
"lq.v(IIIIII)V" : 1578223622,
"lq.x(IIZZI)V" : 703776978,
"lq.y(Lag;Lif;Lif;ZI)V" : 559163206,
"lr.f([BIIB)Z" : 1,
"lw.a(Ljava/lang/String;B)V" : 0,
"lw.s(B)I" : 1,
"m.s(IIII)Lcs;" : -3560696,
"m.x([BIIIIIII[Lfk;S)V" : 254,
"m.y(IIIB)I" : 0,
"n.a(Lm;Lm;I)I" : 965460013,
"n.g(III)Lia;" : -115409750,
"n.jk(II)V" : -1949538187,
"o.a(Lgx;I)V" : -2015278485,
"o.gx(Lbw;III)V" : 16748609,
"o.hh(I)V" : 900432092,
"o.s(Lgx;I)V" : -1171328621,
"p.a(Ljava/util/Comparator;ZB)V" : -1,
"p.f([BIIB)Ljava/lang/String;" : 1,
"p.gk(ZB)V" : 1,
"p.jz(Lia;III)V" : -1232547140,
"p.km(IB)V" : 1,
"q.a(Lm;Lm;I)I" : 806214979,
"r.a(Lm;Lm;I)I" : -587761847,
"r.q(I)Ljava/lang/String;" : 1332980896,
"s.ac(I)I" : 756871814,
"s.fx(B)V" : 1,
"s.jh(Lia;III)V" : -718297066,
"s.kq(Lia;I)Z" : -1017775700,
"t.lf(B)Z" : 0,
"v.a(Lag;B)V" : -1,
"v.fy(Ljava/lang/String;I)V" : -1100446886,
"v.g(III)Z" : 1060896560,
"v.gw(B)V" : 9,
"v.h(III)Lif;" : -175568126,
"v.s(IIII)Z" : -1346882543,
"v.s([BIII)Ljava/lang/String;" : -2131355082,
"v.x(IIIB)[I" : 2,
"w.e(IILgx;II)V" : -1175687218,
"w.in(IIIIIIS)V" : 254,
"w.m(I)Z" : 665939044,
"w.n(IILgx;B)V" : 1,
"w.o(III)I" : 174332944,
"w.q(Liz;I)V" : -1888528129,
"w.r(IILgx;II)V" : -2131355082,
"x.g(Ljava/lang/Class;I)La;" : -559220730,
"x.s(Ljava/lang/Class;I)Lx;" : -803222413,
"y.g(IB)Ly;" : 7,
"y.h(Lgx;IIIIIIB)V" : 2,
"y.if(B)V" : 10,
"y.s(CI)Z" : 1212295357,
"y.s(FB)Z" : 0,
"y.s(Lge;II)V" : 1027527763,
"z.fc(Lju;IIII)V" : 2082929660,
"z.jb(IB)V" : 15
}

32406
extended-mixins/hooks.json Normal file

File diff suppressed because it is too large Load Diff

111
extended-mixins/pom.xml Normal file
View File

@@ -0,0 +1,111 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>net.runelite</groupId>
<artifactId>runelite-parent</artifactId>
<version>1.5.24-SNAPSHOT</version>
</parent>
<artifactId>extended-mixins</artifactId>
<name>RuneLite Extended Mixins</name>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.runelite.rs</groupId>
<artifactId>runescape-api</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.10.19</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<!-- RuneScape classes do not verify
under Java 7+ due to the obfuscation
-->
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>net.runelite</groupId>
<artifactId>extended-mixin-processor</artifactId>
<version>${project.version}</version>
<configuration>
</configuration>
<executions>
<execution>
<id>reob-classes</id>
<phase>process-classes</phase>
<configuration>
<hooks>${artifactId}/hooks.json</hooks>
<ops>${artifactId}/gamepack.deob.jar.op.json</ops>
</configuration>
<goals>
<goal>process-mixins</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixinprocessor.annotations;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Append
{
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixinprocessor.annotations;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Inject
{
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixinprocessor.annotations;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Overwrite
{
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixinprocessor.annotations;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Prepend
{
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixinprocessor.annotations;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Provided
{
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixinprocessor.annotations;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Reobfuscate
{
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixins;
import net.runelite.api.events.AnimationChanged;
import net.runelite.api.events.GraphicChanged;
import us.runelitepl.mixinprocessor.annotations.Overwrite;
import us.runelitepl.mixinprocessor.annotations.Provided;
import us.runelitepl.mixinprocessor.annotations.Reobfuscate;
public class Actor
{
@Reobfuscate
@Provided
int sequence;
@Overwrite
public int getAnimation()
{
return sequence * 42069;
}
@Overwrite
public void animationChanged(int n)
{
AnimationChanged animationChanged = new AnimationChanged();
animationChanged.setActor((net.runelite.api.Actor) this);
Client.INSTANCE.getCallbacks().post(animationChanged);
}
@Overwrite
public void graphicChanged(int n)
{
GraphicChanged graphicChanged = new GraphicChanged();
graphicChanged.setActor((net.runelite.api.Actor)this);
Client.INSTANCE.getCallbacks().post(graphicChanged);
}
}

View File

@@ -0,0 +1,543 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixins;
import net.runelite.api.MenuEntry;
import net.runelite.api.Node;
import net.runelite.api.hooks.Callbacks;
import net.runelite.rs.api.RSCollisionData;
import net.runelite.rs.api.RSDeque;
import net.runelite.rs.api.RSNode;
import us.runelitepl.mixinprocessor.annotations.Inject;
import us.runelitepl.mixinprocessor.annotations.Overwrite;
import us.runelitepl.mixinprocessor.annotations.Prepend;
import us.runelitepl.mixinprocessor.annotations.Provided;
import us.runelitepl.mixinprocessor.annotations.Reobfuscate;
import java.util.List;
public class Client
{
@Provided
public static boolean isHidingEntities;
@Provided
public static boolean hideLocalPlayer2D;
@Provided
public static boolean hideLocalPlayer;
@Provided
public static boolean hidePlayers2D;
@Provided
public static boolean hidePlayers;
@Provided
public static boolean hideAttackers;
@Provided
public static boolean hideProjectiles;
@Provided
public static boolean hideNPCs2D;
@Provided
public static boolean hideNPCs;
@Provided
public static boolean hideFriends;
@Provided
public static boolean hideClanMates;
@Inject
public static Client INSTANCE;
@Inject
public static boolean printMenuActions;
@Provided
public static int oldMenuEntryCount;
@Reobfuscate
@Provided
static boolean renderSelf;
@Provided
public static final int[] rl$modelViewportXs = new int[0];
@Provided
public static final int[] rl$modelViewportYs = new int[0];
@Prepend
private void prepend$rl$$init()
{
INSTANCE = this;
printMenuActions = false;
}
@Inject
public void toggleRenderSelf()
{
renderSelf = !renderSelf;
}
@Provided
public int getMenuOptionCount()
{
throw new RuntimeException();
}
@Provided
public String[] getMenuOptions()
{
throw new RuntimeException();
}
@Provided
public String[] getMenuTargets()
{
throw new RuntimeException();
}
@Provided
public int[] getMenuIdentifiers()
{
throw new RuntimeException();
}
@Provided
public int[] getMenuTypes()
{
throw new RuntimeException();
}
@Provided
public int[] getMenuActionParams0()
{
throw new RuntimeException();
}
@Provided
public int[] getMenuActionParams1()
{
throw new RuntimeException();
}
@Provided
public boolean[] getMenuForceLeftClick()
{
throw new RuntimeException();
}
@Provided
public void setMenuOptionCount(int i)
{
throw new RuntimeException();
}
@Provided
public Callbacks getCallbacks()
{
throw new RuntimeException();
}
@Provided
public RSCollisionData[] getRsCollisionMaps()
{
throw new RuntimeException();
}
@Provided
public RSDeque getProjectilesDeque()
{
throw new RuntimeException();
}
@Overwrite
public List getProjectiles()
{
List list = new java.util.ArrayList();
RSNode head = getProjectilesDeque().getHead();
for (Node node = ((Node) head).getNext();
node != head;
node = node.getNext())
{
list.add(node);
}
return list;
}
@Inject
public void setPrintMenuActions(boolean b)
{
printMenuActions = b;
}
@Overwrite
public RSCollisionData[] getCollisionMaps()
{
return getRsCollisionMaps();
}
@Overwrite
public void setMenuEntries(MenuEntry[] arrmenuEntry)
{
int n2 = 0;
String[] arrstring = this.getMenuOptions();
String[] arrstring2 = this.getMenuTargets();
int[] arrn = this.getMenuIdentifiers();
int[] arrn2 = this.getMenuTypes();
int[] arrn3 = this.getMenuActionParams0();
int[] arrn4 = this.getMenuActionParams1();
boolean[] arrbl = getMenuForceLeftClick();
net.runelite.api.MenuEntry[] arrmenuEntry2 = arrmenuEntry;
int n3 = arrmenuEntry2.length;
int n4 = 0;
do
{
String string;
if (n4 >= n3)
{
this.setMenuOptionCount(n2);
oldMenuEntryCount = n2;
return;
}
net.runelite.api.MenuEntry menuEntry = arrmenuEntry2[n4];
int n5 = menuEntry.getType();
arrstring[n2] = menuEntry.getOption();
arrstring2[n2] = menuEntry.getTarget();
arrn[n2] = menuEntry.getIdentifier();
arrn2[n2] = n5;
arrn3[n2] = menuEntry.getParam0();
arrn4[n2] = menuEntry.getParam1();
arrbl[n2] = menuEntry.isForceLeftClick();
++n2;
++n4;
}
while (true);
}
@Overwrite
public static void onMenuOptionsChanged(int n2)
{
int n3;
int n4 = oldMenuEntryCount;
oldMenuEntryCount = n3 = INSTANCE.getMenuOptionCount();
if (n3 != n4 + 1)
{
return;
}
net.runelite.api.events.MenuEntryAdded menuEntryAdded =
new net.runelite.api.events.MenuEntryAdded(INSTANCE.getMenuOptions()[n3 - 1],
INSTANCE.getMenuTargets()[n3 - 1],
INSTANCE.getMenuTypes()[n3 - 1],
INSTANCE.getMenuIdentifiers()[n3 - 1],
INSTANCE.getMenuActionParams0()[n3 - 1],
INSTANCE.getMenuActionParams1()[n3 - 1]);
INSTANCE.getCallbacks().post(menuEntryAdded);
}
@Overwrite
public static void copy$processClientError(String s, Throwable e, byte b)
{
System.err.println("[RL+] Error thrown: " + s);
e.printStackTrace();
}
@Inject
public net.runelite.api.MouseRecorder getMouseRecorder()
{
return _Statics_.mouseRecorder;
}
@Inject
public boolean boundingboxCheck2(net.runelite.api.Model model, int n2, int n3, int n4)
{
int n5 = INSTANCE.getCameraPitch();
int n6 = INSTANCE.getCameraYaw();
int n7 = net.runelite.api.Perspective.SINE[n5];
int n8 = net.runelite.api.Perspective.COSINE[n5];
int n9 = net.runelite.api.Perspective.SINE[n6];
int n10 = net.runelite.api.Perspective.COSINE[n6];
int n11 = INSTANCE.getCenterX();
int n12 = INSTANCE.getCenterY();
int n13 = INSTANCE.getViewportMouseX();
int n14 = INSTANCE.getViewportMouseY();
int n15 = INSTANCE.get3dZoom();
int n16 = (n13 - n11) * 50 / n15;
int n17 = (n14 - n12) * 50 / n15;
int n18 = (n13 - n11) * 10000 / n15;
int n19 = (n14 - n12) * 10000 / n15;
int n20 = Client.rl$rot1(n17, 50, n8, n7);
int n21 = Client.rl$rot2(n17, 50, n8, n7);
n17 = n20;
n20 = Client.rl$rot1(n19, 10000, n8, n7);
int n22 = Client.rl$rot2(n19, 10000, n8, n7);
n19 = n20;
n20 = Client.rl$rot3(n16, n21, n10, n9);
n21 = Client.rl$rot4(n16, n21, n10, n9);
n16 = n20;
n20 = Client.rl$rot3(n18, n22, n10, n9);
n22 = Client.rl$rot4(n18, n22, n10, n9);
int n23 = (n20 - n16) / 2;
int n24 = (n19 - n17) / 2;
int n25 = (n22 - n21) / 2;
int n26 = Math.abs(n23);
int n27 = Math.abs(n24);
int n28 = Math.abs(n25);
int n29 = n2 + model.getCenterX();
int n30 = n3 + model.getCenterY();
int n31 = n4 + model.getCenterZ();
int n32 = model.getExtremeX();
int n33 = model.getExtremeY();
int n34 = model.getExtremeZ();
int n35 = (n16 + n20) / 2;
int n36 = (n17 + n19) / 2;
int n37 = (n22 + n21) / 2;
int n38 = n35 - n29;
int n39 = n36 - n30;
int n40 = n37 - n31;
if (Math.abs(n38) > n32 + n26)
{
return false;
}
if (Math.abs(n39) > n33 + n27)
{
return false;
}
if (Math.abs(n40) > n34 + n28)
{
return false;
}
if (Math.abs(n40 * n24 - n39 * n25) > n33 * n28 + n34 * n27)
{
return false;
}
if (Math.abs(n38 * n25 - n40 * n23) > n34 * n26 + n32 * n28)
{
return false;
}
if (Math.abs(n39 * n23 - n38 * n24) <= n33 * n26 + n32 * n27)
{
return true;
}
return false;
}
@Overwrite
public void checkClickbox(net.runelite.api.Model model, int n2, int n3, int n4, int n5, int n6, int n7, int n8, int n9, long l2)
{
int n10;
int n11;
int n12;
int n13;
int n14;
net.runelite.rs.api.RSModel rSModel = (net.runelite.rs.api.RSModel) model;
boolean bl2 = l2 != 0L && (int) (l2 >>> 16 & 1L) != 1;
boolean bl3 = INSTANCE.getViewportContainsMouse();
if (!bl2)
{
return;
}
if (!bl3)
{
return;
}
boolean bl4 = this.boundingboxCheck2(rSModel, n7, n8, n9);
if (!bl4)
{
return;
}
if (rSModel.isClickable())
{
this.addHashAtMouse(l2);
return;
}
int n15 = rSModel.getVerticesCount();
int n16 = rSModel.getTrianglesCount();
int[] arrn = rSModel.getVerticesX();
int[] arrn2 = rSModel.getVerticesY();
int[] arrn3 = rSModel.getVerticesZ();
int[] arrn4 = rSModel.getTrianglesX();
int[] arrn5 = rSModel.getTrianglesY();
int[] arrn6 = rSModel.getTrianglesZ();
int[] arrn7 = rSModel.getFaceColors3();
int n17 = INSTANCE.get3dZoom();
int n18 = INSTANCE.getCenterX();
int n19 = INSTANCE.getCenterY();
int n20 = 0;
int n21 = 0;
if (n2 != 0)
{
n20 = net.runelite.api.Perspective.SINE[n2];
n21 = net.runelite.api.Perspective.COSINE[n2];
}
for (n14 = 0; n14 < n15; ++n14)
{
n11 = arrn[n14];
n13 = arrn2[n14];
n12 = arrn3[n14];
if (n2 != 0)
{
n10 = n12 * n20 + n11 * n21 >> 16;
n12 = n12 * n21 - n11 * n20 >> 16;
n11 = n10;
}
n10 = (n12 += n9) * n5 + n6 * (n11 += n7) >> 16;
n12 = n6 * n12 - n11 * n5 >> 16;
n11 = n10;
n10 = n4 * (n13 += n8) - n12 * n3 >> 16;
if ((n12 = n13 * n3 + n4 * n12 >> 16) >= 50)
{
Client.rl$modelViewportYs[n14] = n11 * n17 / n12 + n18;
Client.rl$modelViewportXs[n14] = n10 * n17 / n12 + n19;
continue;
}
Client.rl$modelViewportYs[n14] = -5000;
}
n14 = INSTANCE.getViewportMouseX();
n11 = INSTANCE.getViewportMouseY();
n13 = 0;
while (n13 < n16)
{
if (arrn7[n13] != -2)
{
int n22;
boolean bl5;
int n23;
n12 = arrn4[n13];
n10 = arrn5[n13];
int n24 = arrn6[n13];
int n25 = rl$modelViewportYs[n12];
int n26 = rl$modelViewportYs[n10];
int n27 = rl$modelViewportYs[n24];
int n28 = rl$modelViewportXs[n12];
int n29 = rl$modelViewportXs[n10];
int n30 = rl$modelViewportXs[n24];
if (n25 != -5000 && n26 != -5000 && n27 != -5000 && (bl5 = (n23 = (n22 = rSModel.isClickable() ? 20
: 5) + n11) < n28 && n23 < n29 && n23 < n30 ? false
: ((n23 = n11 - n22) > n28 && n23 > n29 && n23 > n30 ? false
: ((n23 = n22 + n14) < n25 && n23 < n26 && n23 < n27 ? false
: (n23 = n14 - n22) <= n25 || n23 <= n26 || n23 <= n27))))
{
this.addHashAtMouse(l2);
return;
}
}
++n13;
}
}
@Provided
public boolean getViewportContainsMouse()
{
throw new RuntimeException();
}
@Provided
public void addHashAtMouse(long l)
{
throw new RuntimeException();
}
@Provided
public int getCameraPitch()
{
throw new RuntimeException();
}
@Provided
public int getCameraYaw()
{
throw new RuntimeException();
}
@Provided
public int getCenterX()
{
throw new RuntimeException();
}
@Provided
public int getCenterY()
{
throw new RuntimeException();
}
@Provided
public int getViewportMouseX()
{
throw new RuntimeException();
}
@Provided
public int getViewportMouseY()
{
throw new RuntimeException();
}
@Provided
public int get3dZoom()
{
throw new RuntimeException();
}
@Provided
public static int rl$rot1(int a, int b, int c, int d)
{
throw new RuntimeException();
}
@Provided
public static int rl$rot2(int a, int b, int c, int d)
{
throw new RuntimeException();
}
@Provided
public static int rl$rot3(int a, int b, int c, int d)
{
throw new RuntimeException();
}
@Provided
public static int rl$rot4(int a, int b, int c, int d)
{
throw new RuntimeException();
}
@Inject
public void invokeMenuAction(int actionParam, int widgetId, int opcode, int targetId, String menuOption,
String menuTarget, int mouseX, int mouseY)
{
_Statics_.menuAction(actionParam, widgetId, opcode, targetId, menuOption,
menuTarget, mouseX, mouseY);
}
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixins;
import net.runelite.rs.api.RSMouseRecorder;
import us.runelitepl.mixinprocessor.annotations.Inject;
import us.runelitepl.mixinprocessor.annotations.Provided;
import us.runelitepl.mixinprocessor.annotations.Reobfuscate;
public class MouseRecorder implements RSMouseRecorder
{
@Provided
@Reobfuscate
int[] xs;
@Provided
@Reobfuscate
int[] ys;
@Provided
@Reobfuscate
long[] millis;
@Provided
@Reobfuscate
int index;
@Inject
public int[] getXs()
{
return xs;
}
@Inject
public int[] getYs()
{
return ys;
}
@Inject
public long[] getMillis()
{
return millis;
}
@Inject
public int getIndex()
{
return index * 42069;
}
}

View File

@@ -0,0 +1,81 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixins;
import net.runelite.api.SkullIcon;
import us.runelitepl.mixinprocessor.annotations.Inject;
import us.runelitepl.mixinprocessor.annotations.Overwrite;
import us.runelitepl.mixinprocessor.annotations.Provided;
import us.runelitepl.mixinprocessor.annotations.Reobfuscate;
public class Player
{
@Reobfuscate
@Provided
int headIconPk;
@Reobfuscate
@Provided
int index;
@Inject
public int getHeadIconPk()
{
return headIconPk * 42069;
}
@Overwrite
public SkullIcon getSkullIcon()
{
switch(getHeadIconPk())
{
case 0:
return SkullIcon.SKULL;
case 1:
return SkullIcon.SKULL_FIGHT_PIT;
case 8:
return SkullIcon.DEAD_MAN_FIVE;
case 9:
return SkullIcon.DEAD_MAN_FOUR;
case 10:
return SkullIcon.DEAD_MAN_THREE;
case 11:
return SkullIcon.DEAD_MAN_TWO;
case 12:
return SkullIcon.DEAD_MAN_ONE;
default:
return null;
}
}
@Inject
public int getIndex()
{
return index * 42069;
}
}

View File

@@ -0,0 +1,81 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixins;
import net.runelite.api.Actor;
import net.runelite.api.coords.LocalPoint;
import net.runelite.api.events.ProjectileMoved;
import net.runelite.rs.api.RSClient;
import us.runelitepl.mixinprocessor.annotations.Inject;
import us.runelitepl.mixinprocessor.annotations.Overwrite;
import us.runelitepl.mixinprocessor.annotations.Provided;
import us.runelitepl.mixinprocessor.annotations.Reobfuscate;
public class Projectile
{
@Reobfuscate
@Provided
int targetIndex;
@Inject
public int getTargetId()
{
return targetIndex * 42069;
}
@Overwrite
public void projectileMoved(int x, int y, int z, int n3)
{
LocalPoint position = new LocalPoint(x, y);
ProjectileMoved event = new ProjectileMoved();
event.setProjectile((net.runelite.api.Projectile) this);
event.setPosition(position);
event.setZ(z);
((RSClient) Client.INSTANCE).getCallbacks().post(event);
}
@Inject
public Actor getInteracting()
{
final int _targ = this.getTargetId();
if (_targ == 0)
{
return null;
}
if (_targ > 0)
{
return (Actor) ((RSClient) Client.INSTANCE).getCachedNPCs()[_targ - 1];
}
final int n = -_targ - 1;
if (n == ((RSClient) Client.INSTANCE).getLocalInteractingIndex())
{
return (Actor) ((RSClient) Client.INSTANCE).getLocalPlayer();
}
return (Actor) ((RSClient) Client.INSTANCE).getCachedPlayers()[n];
}
}

View File

@@ -0,0 +1,104 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixins;
import net.runelite.rs.api.RSClient;
import net.runelite.rs.api.RSNPC;
import net.runelite.rs.api.RSPlayer;
import net.runelite.rs.api.RSProjectile;
import us.runelitepl.mixinprocessor.annotations.Overwrite;
public class Scene
{
@Overwrite
public static boolean shouldDraw(Object renderable, boolean drawingUI)
{
if (!Client.isHidingEntities)
{
return true;
}
if(renderable instanceof RSPlayer)
{
RSPlayer p = (RSPlayer) renderable;
if(Client.hideClanMates && p.isClanMember())
{
return false;
}
}
if (renderable instanceof RSPlayer)
{
boolean local = drawingUI ? Client.hideLocalPlayer2D : Client.hideLocalPlayer;
boolean other = drawingUI ? Client.hidePlayers2D : Client.hidePlayers;
boolean isLocalPlayer = renderable == ((RSClient)Client.INSTANCE).getLocalPlayer();
if (isLocalPlayer ? local : other)
{
RSPlayer player = (RSPlayer) renderable;
if (!Client.hideAttackers)
{
if (player.getInteracting() == ((RSClient)Client.INSTANCE).getLocalPlayer())
{
return true;
}
}
if (player.getName() == null)
{
// player.isFriend() and player.isClanMember() npe when the player has a null name
return false;
}
return (!Client.hideFriends && player.isFriend()) || (!isLocalPlayer && !Client.hideClanMates && player.isClanMember());
}
}
else if (renderable instanceof RSNPC)
{
RSNPC npc = (RSNPC) renderable;
if (!Client.hideAttackers)
{
if (npc.getInteracting() == ((RSClient)Client.INSTANCE).getLocalPlayer())
{
return true;
}
}
return drawingUI ? !Client.hideNPCs2D : !Client.hideNPCs;
}
else if (renderable instanceof RSProjectile)
{
return !Client.hideProjectiles;
}
return true;
}
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 us.runelitepl.mixins;
import us.runelitepl.mixinprocessor.annotations.Prepend;
import us.runelitepl.mixinprocessor.annotations.Provided;
import us.runelitepl.mixinprocessor.annotations.Reobfuscate;
public class _Statics_
{
@Provided
@Reobfuscate
static MouseRecorder mouseRecorder;
@Prepend
@Reobfuscate
static final void prepend$menuAction(int actionParam, int widgetId, int opcode, int targetId, String menuOption,
String menuTarget, int mouseX, int mouseY)
{
if(Client.printMenuActions)
{
int printOpcode = opcode;
if(opcode >= 2000)
{
printOpcode -= 2000;
}
System.out.format("menuAction triggered: '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s'\n", actionParam, widgetId,
printOpcode, targetId, menuOption, menuTarget, mouseX, mouseY);
}
}
@Provided
@Reobfuscate
static final void menuAction(int actionParam, int widgetId, int opcode, int targetId, String menuOption,
String menuTarget, int mouseX, int mouseY)
{
throw new RuntimeException();
}
}

View File

@@ -0,0 +1,22 @@
Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -115,6 +115,8 @@
<module>cache</module>
<module>cache-client</module>
<module>cache-updater</module>
<module>extended-mixin-processor</module>
<module>extended-mixins</module>
<module>runelite-api</module>
<module>runelite-client</module>
<module>runelite-mixins</module>

View File

@@ -1615,5 +1615,9 @@ public interface Client extends GameEngine
void toggleRenderSelf();
void invokeMenuAction(int var1, int var2, int var3, int var4, String var5, String var6, int var7, int var8);
MouseRecorder getMouseRecorder();
void setPrintMenuActions(boolean b);
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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;
public interface MouseRecorder
{
int[] getXs();
int[] getYs();
long[] getMillis();
int getIndex();
}

View File

@@ -221,6 +221,11 @@
<version>1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.runelite</groupId>
<artifactId>extended-mixins</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
@@ -272,6 +277,11 @@
<artifactId>naturalmouse</artifactId>
<version>[1.0.0,)</version>
</dependency>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm-all</artifactId>
<version>6.0_BETA</version>
</dependency>
</dependencies>
<build>
@@ -315,7 +325,6 @@
<goal>shade</goal>
</goals>
<configuration>
<minimizeJar>true</minimizeJar>
<shadedArtifactAttached>true</shadedArtifactAttached>
<shadedClassifierName>shaded</shadedClassifierName>

View File

@@ -118,6 +118,19 @@ class DevToolsPanel extends PluginPanel
varInspector.open();
}
});
container.add(plugin.getLogMenuActions());
plugin.getLogMenuActions().addActionListener((ev) ->
{
if(plugin.getLogMenuActions().isActive())
{
client.setPrintMenuActions(false);
}
else
{
client.setPrintMenuActions(true);
}
});
return container;
}

View File

@@ -126,6 +126,7 @@ public class DevToolsPlugin extends Plugin
private DevToolsButton detachedCamera;
private DevToolsButton widgetInspector;
private DevToolsButton varInspector;
private DevToolsButton logMenuActions;
private NavigationButton navButton;
@Provides
@@ -173,6 +174,8 @@ public class DevToolsPlugin extends Plugin
overlayManager.add(cameraOverlay);
overlayManager.add(worldMapLocationOverlay);
overlayManager.add(mapRegionOverlay);
logMenuActions = new DevToolsButton("Menu Actions");
final DevToolsPanel panel = injector.getInstance(DevToolsPanel.class);

View File

@@ -32,101 +32,82 @@ import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import io.sigpipe.jbsdiff.InvalidHeaderException;
import io.sigpipe.jbsdiff.Patch;
import java.applet.Applet;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import java.util.logging.Logger;
import javassist.ClassPool;
import javassist.NotFoundException;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import lombok.extern.slf4j.Slf4j;
import net.runelite.client.RuneLite;
import static net.runelite.client.rs.ClientUpdateCheckMode.AUTO;
import static net.runelite.client.rs.ClientUpdateCheckMode.NONE;
import static net.runelite.client.rs.ClientUpdateCheckMode.VANILLA;
import net.runelite.client.rs.bytecode.ByteCodePatcher;
import net.runelite.client.rs.bytecode.ByteCodeUtils;
import net.runelite.client.rs.bytecode.Hooks;
import net.runelite.client.rs.mixins.MixinRunner;
import net.runelite.http.api.RuneLiteAPI;
import okhttp3.Request;
import okhttp3.Response;
import org.apache.commons.compress.compressors.CompressorException;
import org.xeustechnologies.jcl.JarClassLoader;
@Slf4j
@Singleton
public class ClientLoader
{
public static File hooksFile = new File(RuneLite.RUNELITE_DIR + "/hooks-" + RuneLiteAPI.getVersion() + "-.json");
private final ClientConfigLoader clientConfigLoader;
private ClientUpdateCheckMode updateCheckMode;
private static String[] preotectedStuffs;
private static int stepCount;
@Inject
private ClientLoader(
@Named("updateCheckMode") final ClientUpdateCheckMode updateCheckMode,
final ClientConfigLoader clientConfigLoader)
@Named("updateCheckMode") final ClientUpdateCheckMode updateCheckMode,
final ClientConfigLoader clientConfigLoader)
{
this.updateCheckMode = updateCheckMode;
this.clientConfigLoader = clientConfigLoader;
}
public Applet load()
{
if (updateCheckMode == NONE)
{
return null;
}
try
{
File injectedClientFile = ByteCodeUtils.injectedClientFile;
File hijackedClientFile = ByteCodeUtils.hijackedClientFile;
Manifest manifest = new Manifest();
manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
JarOutputStream target = new JarOutputStream(new FileOutputStream(injectedClientFile), manifest);
RSConfig config = clientConfigLoader.fetch();
Map<String, byte[]> zipFile = new HashMap<>();
{
String codebase = config.getCodeBase();
String initialJar = config.getInitialJar();
URL url = new URL(codebase + initialJar);
Request request = new Request.Builder()
.url(url)
.build();
.url(url)
.build();
try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute())
{
JarInputStream jis;
jis = new JarInputStream(response.body().byteStream());
byte[] tmp = new byte[4096];
ByteArrayOutputStream buffer = new ByteArrayOutputStream(756 * 1024);
for (; ; )
@@ -136,7 +117,7 @@ public class ClientLoader
{
break;
}
buffer.reset();
for (; ; )
{
@@ -147,12 +128,12 @@ public class ClientLoader
}
buffer.write(tmp, 0, n);
}
zipFile.put(metadata.getName(), buffer.toByteArray());
}
}
}
if (updateCheckMode == AUTO)
{
Map<String, String> hashes;
@@ -162,41 +143,33 @@ public class ClientLoader
{
}.getType());
}
for (Map.Entry<String, String> file : hashes.entrySet())
{
byte[] bytes = zipFile.get(file.getKey());
String ourHash = null;
if (bytes != null)
{
ourHash = Hashing.sha512().hashBytes(bytes).toString();
}
if (!file.getValue().equals(ourHash))
{
if (hijackedClientFile.exists())
{
Logger.getAnonymousLogger().warning("[RuneLitePlus] Hash checking / Client patching skipped due to hijacked client.");
updateCheckMode = VANILLA;
break;
}
else
{
log.info("{} had a hash mismatch; falling back to vanilla. {} != {}", file.getKey(), file.getValue(), ourHash);
log.info("Client is outdated!");
updateCheckMode = VANILLA;
break;
}
log.info("{} had a hash mismatch; falling back to vanilla. {} != {}", file.getKey(),
file.getValue(), ourHash);
log.info("Client is outdated!");
updateCheckMode = VANILLA;
break;
}
}
}
if (updateCheckMode == AUTO)
{
ByteArrayOutputStream patchOs = new ByteArrayOutputStream(756 * 1024);
int patchCount = 0;
for (Map.Entry<String, byte[]> file : zipFile.entrySet())
{
byte[] bytes;
@@ -206,292 +179,110 @@ public class ClientLoader
{
continue;
}
bytes = ByteStreams.toByteArray(is);
}
patchOs.reset();
Patch.patch(file.getValue(), bytes, patchOs);
file.setValue(patchOs.toByteArray());
++patchCount;
if (!file.getKey().startsWith("META"))
{
add(file.getValue(), file.getKey(), target);
}
}
target.close();
log.info("Patched {} classes", patchCount);
}
if (hooksFile.exists())
log.info("Patching for RuneLitePlus");
if (updateCheckMode == AUTO)
{
ByteCodePatcher.classPool = new ClassPool(true);
ByteCodePatcher.classPool.appendClassPath(RuneLite.RUNELITE_DIR + "/injectedClient-" + RuneLiteAPI.getVersion() + "-.jar");
Gson gson = new Gson();
Hooks hooks = gson.fromJson(new BufferedReader(new FileReader(hooksFile)), Hooks.class);
if (hooks.clientInstance.equals("") ||
hooks.clientClass.equals("") ||
hooks.projectileClass.equals("") ||
hooks.actorClass.equals("") ||
hooks.playerClass.equals(""))
HashMap<String, byte[]> patches = new HashMap<>();
for (Map.Entry<String, byte[]> file : zipFile.entrySet())
{
log.info("[RuneLitePlus] Bad hooks, re-scraping.");
stepCount = getStepCount(ByteCodeUtils.injectedClientFile.getPath());
ByteCodePatcher.clientInstance = initHookScrape(ByteCodeUtils.injectedClientFile.getPath());
ByteCodePatcher.findHooks(injectedClientFile.getPath());
}
else
{
ByteCodePatcher.clientInstance = hooks.clientInstance;
ByteCodePatcher.applyHooks(ByteCodeUtils.injectedClientFile, hooks);
log.info("[RuneLitePlus] Loaded hooks");
}
}
else
{
log.info("[RuneLitePlus] Hooks file not found, scraping hooks.");
stepCount = getStepCount(ByteCodeUtils.injectedClientFile.getPath());
ByteCodePatcher.clientInstance = initHookScrape(ByteCodeUtils.injectedClientFile.getPath());
ByteCodePatcher.hooks.protectedStuff = preotectedStuffs;
ByteCodePatcher.findHooks(injectedClientFile.getPath());
}
Map<String, byte[]> zipFile2 = new HashMap<>();
JarInputStream jis = new JarInputStream(new FileInputStream(hijackedClientFile));
byte[] tmp = new byte[4096];
ByteArrayOutputStream buffer = new ByteArrayOutputStream(756 * 1024);
for (; ; )
{
JarEntry metadata = jis.getNextJarEntry();
if (metadata == null)
{
break;
}
buffer.reset();
for (; ; )
{
int n = jis.read(tmp);
if (n <= -1)
byte[] patchClass;
try (InputStream is = ClientLoader.class.getResourceAsStream("/extended-mixins/" + file.getKey()))
{
break;
if (is == null)
{
continue;
}
patchClass = ByteStreams.toByteArray(is);
}
buffer.write(tmp, 0, n);
patches.put(file.getKey(), patchClass);
}
zipFile2.put(metadata.getName(), buffer.toByteArray());
new MixinRunner(zipFile, patches).run();
}
for (Map.Entry<String, byte[]> entry : zipFile.entrySet())
{
if (entry.getKey().contains("class"))
{
Files.write(new File("H:\\rsclasses\\" + entry.getKey()).toPath(), entry.getValue());
}
}
String initialClass = config.getInitialClass();
ClassLoader rsClassLoader = new ClassLoader(ClientLoader.class.getClassLoader())
{
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException
{
String path = name.replace('.', '/').concat(".class");
byte[] data = zipFile2.get(path);
byte[] data = zipFile.get(path);
if (data == null)
{
throw new ClassNotFoundException(name);
}
return defineClass(name, data, 0, data.length);
}
};
Class<?> clientClass = rsClassLoader.loadClass(initialClass);
Applet rs = (Applet) clientClass.newInstance();
rs.setStub(new RSAppletStub(config));
return rs;
}
catch (IOException | ClassNotFoundException | InstantiationException | IllegalAccessException
| CompressorException | InvalidHeaderException | SecurityException e)
catch (IOException | ClassNotFoundException | InstantiationException | IllegalAccessException | CompressorException | InvalidHeaderException | SecurityException | NoSuchMethodException | InvocationTargetException e)
{
if (e instanceof ClassNotFoundException)
{
log.error("Unable to load client - class not found. This means you"
+ " are not running RuneLite with Maven as the client patch"
+ " is not in your classpath.");
+ " are not running RuneLite with Maven as the client patch"
+ " is not in your classpath.");
}
log.error("Error loading RS!", e);
return null;
}
catch (NotFoundException e)
{
e.printStackTrace();
}
return null;
}
private void add(byte[] bytes, String entryName, JarOutputStream target) throws IOException
{
JarEntry entry = new JarEntry(entryName);
target.putNextEntry(entry);
target.write(bytes);
target.closeEntry();
}
private static int getStepCount(String jarFile)
{
int stepCount = 0;
JarClassLoader jcl = new JarClassLoader();
BufferedInputStream in = null;
try
{
ClassPool classPool = new ClassPool(true);
classPool.appendClassPath(RuneLite.RUNELITE_DIR + "/injectedClient-" + RuneLiteAPI.getVersion() + "-.jar");
JarEntry entry = new JarEntry(entryName);
target.putNextEntry(entry);
target.write(bytes);
target.closeEntry();
}
catch (NotFoundException e)
finally
{
e.printStackTrace();
}
try
{
jcl.add(new FileInputStream(jarFile));
try (JarInputStream in = new JarInputStream(new BufferedInputStream(new FileInputStream(jarFile))))
if (in != null)
{
JarEntry entry;
while ((entry = in.getNextJarEntry()) != null)
{
if (entry.getName().endsWith(".class"))
{
stepCount++;
}
}
in.close();
}
}
catch (Exception e)
{
e.printStackTrace();
}
return stepCount;
}
private static String initHookScrape(String jarFile)
{
int currentStep = 0;
RuneLite.splashScreen.setMessage("Analyzing injected client");
List<String> protectedStuff = new ArrayList<>();
String clientInstance = "";
JarClassLoader jcl = new JarClassLoader();
try
{
ClassPool classPool = new ClassPool(true);
classPool.appendClassPath(RuneLite.RUNELITE_DIR + "/injectedClient-" + RuneLiteAPI.getVersion() + "-.jar");
}
catch (NotFoundException e)
{
e.printStackTrace();
}
try
{
jcl.add(new FileInputStream(jarFile));
try (JarInputStream in = new JarInputStream(new BufferedInputStream(new FileInputStream(jarFile))))
{
JarEntry entry;
while ((entry = in.getNextJarEntry()) != null)
{
if (entry.getName().endsWith(".class"))
{
File temp = new File(jarFile);
ClassLoader cl = ClassLoader.getSystemClassLoader();
try
{
URLClassLoader child = new URLClassLoader(
new URL[]{temp.toURI().toURL()},
cl
);
try
{
Class classToLoad = Class.forName(entry.getName().replace(".class", ""), false, child);
RuneLite.splashScreen.setSubMessage(entry.getName());
currentStep++;
RuneLite.splashScreen.setProgress(currentStep, stepCount);
JarClassLoader jcl2 = new JarClassLoader();
try
{
jcl2.add(new FileInputStream(ByteCodeUtils.injectedClientFile));
Field[] fields = classToLoad.getDeclaredFields();
Method[] methods = classToLoad.getDeclaredMethods();
for (Field f : fields)
{
try
{
if (f.getName().contains("$"))
{
log.info(classToLoad.getName() + "." + f.getName());
protectedStuff.add(classToLoad.getName() + "." + f.getName());
}
if (f.getType().getName().equals("client"))
{
ByteCodePatcher.hooks.clientInstance = classToLoad.getName() + "." + f.getName();
clientInstance = classToLoad.getName() + "." + f.getName();
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
for (Method m : methods)
{
RuneLite.splashScreen.setSubMessage("Checked " + m.getName());
if (m.getName().contains("$"))
{
protectedStuff.add(classToLoad.getName() + "." + m.getName());
}
}
RuneLite.splashScreen.setProgress(currentStep, stepCount);
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
}
catch (Exception e)
{
e.printStackTrace();
}
RuneLite.splashScreen.setProgress(2, 5);
}
catch (Exception e)
{
e.printStackTrace();
log.info("Class not found: " + entry.getName());
}
}
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
int i = 0;
for (String ignored : protectedStuff)
{
i++;
}
preotectedStuffs = new String[i];
i = 0;
for (String o : protectedStuff)
{
preotectedStuffs[i] = o;
i++;
}
return clientInstance;
}
}

View File

@@ -1,298 +0,0 @@
package net.runelite.client.rs.bytecode;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.NotFoundException;
import lombok.extern.slf4j.Slf4j;
import net.runelite.client.RuneLite;
import net.runelite.client.rs.ClientLoader;
import net.runelite.client.rs.bytecode.transformers.ActorTransform;
import net.runelite.client.rs.bytecode.transformers.ClientTransform;
import net.runelite.client.rs.bytecode.transformers.ErrorTransform;
import net.runelite.client.rs.bytecode.transformers.PlayerTransform;
import net.runelite.client.rs.bytecode.transformers.ProjectileTransform;
import net.runelite.http.api.RuneLiteAPI;
import org.xeustechnologies.jcl.JarClassLoader;
@Slf4j
public class ByteCodePatcher
{
public static List<CtClass> modifiedClasses = new ArrayList<>();
public static Hooks hooks = new Hooks();
public static String clientInstance;
private static JarClassLoader jcl = new JarClassLoader();
public static ClassPool classPool = null;
private static ClassLoader cl = ClassLoader.getSystemClassLoader();
private static int classCount = 0;
public static void applyHooks(File jf, Hooks hooks)
{
RuneLite.splashScreen.setProgress(0, 5);
RuneLite.splashScreen.setMessage("Applying cached bytecode patches...");
try
{
URLClassLoader child = new URLClassLoader(
new URL[]{jf.toURI().toURL()},
cl
);
try
{
RuneLite.splashScreen.setSubMessage("Transforming Client");
Class clientClass = Class.forName(hooks.clientClass, false, child);
transformClient(clientClass);
RuneLite.splashScreen.setProgress(1, 5);
RuneLite.splashScreen.setSubMessage("Transforming Actor");
Class actorClass = Class.forName(hooks.actorClass, false, child);
transformActor(actorClass);
RuneLite.splashScreen.setProgress(2, 5);
RuneLite.splashScreen.setSubMessage("Transforming Projectile");
Class projectileClass = Class.forName(hooks.projectileClass, false, child);
transformProjectile(projectileClass);
RuneLite.splashScreen.setProgress(3, 5);
RuneLite.splashScreen.setSubMessage("Transforming Player");
Class playerClass = Class.forName(hooks.playerClass, false, child);
transformPlayer(playerClass);
RuneLite.splashScreen.setProgress(4, 5);
// Odds and ends
RuneLite.splashScreen.setSubMessage("Transforming Error method");
transformStackTrace();
RuneLite.splashScreen.setProgress(5, 5);
RuneLite.splashScreen.setSubMessage("");
ByteCodeUtils.updateHijackedJar();
}
catch (Exception e)
{
// e.printStackTrace();
}
}
catch (Exception e)
{
// e.printStackTrace();
}
}
public static void findHooks(String jf)
{
RuneLite.splashScreen.setMessage("Hijacking Classes");
try
{
classPool = new ClassPool(true);
classPool.appendClassPath(RuneLite.RUNELITE_DIR + "/injectedClient-" + RuneLiteAPI.getVersion() + "-.jar");
}
catch (NotFoundException e)
{
e.printStackTrace();
}
try
{
jcl.add(new FileInputStream(jf));
try (JarInputStream in = new JarInputStream(new BufferedInputStream(new FileInputStream(jf))))
{
JarEntry entry;
while ((entry = in.getNextJarEntry()) != null)
{
if (entry.getName().endsWith(".class"))
{
classCount++;
}
}
}
int i = 0;
jcl.add(new FileInputStream(jf));
try (JarInputStream in = new JarInputStream(new BufferedInputStream(new FileInputStream(jf))))
{
JarEntry entry;
while ((entry = in.getNextJarEntry()) != null)
{
if (entry.getName().endsWith(".class"))
{
RuneLite.splashScreen.setProgress(i, classCount);
RuneLite.splashScreen.setSubMessage("Checking " + entry.getName());
checkClasses(new File(jf), entry);
i++;
}
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
Gson gson = new GsonBuilder().setPrettyPrinting().create();
try
{
Writer writer = new FileWriter(ClientLoader.hooksFile);
gson.toJson(hooks, writer);
writer.flush();
writer.close();
}
catch (IOException e)
{
e.printStackTrace();
}
ByteCodeUtils.updateHijackedJar();
}
private static void checkClasses(File jf, JarEntry entry)
{
try
{
URLClassLoader child = new URLClassLoader(
new URL[]{jf.toURI().toURL()},
cl
);
try
{
Class classToLoad = Class.forName(entry.getName().replace(".class", ""), false, child);
checkClient(classToLoad);
checkActor(classToLoad);
checkProjectile(classToLoad);
checkPlayer(classToLoad);
}
catch (Exception e)
{
// e.printStackTrace();
}
}
catch (Exception e)
{
// e.printStackTrace();
// System.out.println("Class not found: "+entry.getName());
}
}
private static void checkClient(Class current)
{
try
{
Method method = current.getDeclaredMethod("getProjectiles");
if (method != null)
{
hooks.clientClass = current.getName();
log.info("[RuneLitePlus] Transforming Client at class: " + current.getName());
ClientTransform ct = new ClientTransform();
ct.modify(current);
}
}
catch (NoSuchMethodException | NoClassDefFoundError e)
{
// e.printStackTrace();
}
}
private static void transformClient(Class client)
{
log.info("[RuneLitePlus] Transforming Client at class: " + client.getName());
ClientTransform ct = new ClientTransform();
ct.modify(client);
}
private static void checkActor(Class current)
{
try
{
Method method = current.getDeclaredMethod("setCombatInfo", new Class[]{int.class, int.class, int.class, int.class, int.class, int.class});
if (method != null)
{
hooks.actorClass = current.getName();
log.info("[RuneLitePlus] Transforming Actor at class: " + current.getName());
ActorTransform at = new ActorTransform();
at.modify(current);
}
}
catch (NoSuchMethodException | NoClassDefFoundError e)
{
// e.printStackTrace();
}
}
private static void transformActor(Class actor)
{
log.info("[RuneLitePlus] Transforming Actor at class: " + actor.getName());
ActorTransform at = new ActorTransform();
at.modify(actor);
}
private static void checkProjectile(Class current)
{
try
{
Method method = current.getDeclaredMethod("projectileMoved", new Class[]{int.class, int.class, int.class, int.class});
if (method != null)
{
hooks.projectileClass = current.getName();
log.info("[RuneLitePlus] Transforming Projectile at class: " + current.getName());
ProjectileTransform pt = new ProjectileTransform();
pt.modify(current);
}
}
catch (NoSuchMethodException | NoClassDefFoundError e)
{
// e.printStackTrace();
}
}
private static void transformProjectile(Class projectile)
{
log.info("[RuneLitePlus] Transforming Projectile at class: " + projectile.getName());
ProjectileTransform pt = new ProjectileTransform();
pt.modify(projectile);
}
private static void checkPlayer(Class current)
{
try
{
Method method = current.getDeclaredMethod("getSkullIcon");
if (method != null)
{
hooks.playerClass = current.getName();
log.info("[RuneLitePlus] Transforming Player at class: " + current.getName());
PlayerTransform pt = new PlayerTransform();
pt.modify(current);
}
}
catch (NoSuchMethodException | NoClassDefFoundError e)
{
// e.printStackTrace();
}
}
private static void transformPlayer(Class player)
{
log.info("[RuneLitePlus] Transforming Player at class: " + player.getName());
PlayerTransform pt = new PlayerTransform();
pt.modify(player);
}
private static void transformStackTrace()
{
log.info("[RuneLitePlus] Transforming Stack Trace");
ErrorTransform et = new ErrorTransform();
et.modify(null);
}
}

View File

@@ -1,141 +0,0 @@
package net.runelite.client.rs.bytecode;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import javassist.CtClass;
import net.runelite.client.RuneLite;
import net.runelite.http.api.RuneLiteAPI;
public class ByteCodeUtils
{
//TODO: Write method to delete old revision injected clients.
public static File injectedClientFile = new File(RuneLite.RUNELITE_DIR + "/injectedClient-" + RuneLiteAPI.getVersion() + "-.jar");
public static File hijackedClientFile = new File(RuneLite.RUNELITE_DIR + "/hijackedClient-" + RuneLiteAPI.getVersion() + "-.jar");
public static JarOutputStream target;
static void updateHijackedJar()
{
Manifest manifest = new Manifest();
manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
try
{
target = new JarOutputStream(new FileOutputStream(hijackedClientFile), manifest);
}
catch (IOException e)
{
e.printStackTrace();
}
try
{
JarFile original = new JarFile(injectedClientFile);
Enumeration<JarEntry> entries = original.entries();
while (entries.hasMoreElements())
{
JarEntry entry = entries.nextElement();
boolean skip = false;
for (CtClass ct : ByteCodePatcher.modifiedClasses)
{
if ((ct.getName() + ".class").equals(entry.getName()))
{
skip = true;
}
}
if (!skip)
{
add(entry);
}
}
for (CtClass ct : ByteCodePatcher.modifiedClasses)
{
add(ct);
}
target.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
private static void add(CtClass ct)
{
try
{
JarEntry newEntry = new JarEntry(ct.getName() + ".class");
target.putNextEntry(newEntry);
target.write(ct.toBytecode());
target.closeEntry();
}
catch (Exception e)
{
e.printStackTrace();
}
}
private static void add(JarEntry entry) throws IOException
{
try
{
if (!entry.getName().startsWith("META") && !entry.getName().equals(""))
{
target.putNextEntry(entry);
target.write(getBytesFromZipFile(entry.getName()));
target.closeEntry();
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
private static byte[] getBytesFromZipFile(String entryName)
{
ZipFile zipFile;
try
{
zipFile = new ZipFile(injectedClientFile);
Enumeration<? extends ZipEntry> entries = zipFile.entries();
while (entries.hasMoreElements())
{
ZipEntry entry = entries.nextElement();
if (entry.getName().equals(entryName))
{
InputStream stream = zipFile.getInputStream(entry);
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[1024];
while ((nRead = stream.read(data, 0, data.length)) != -1)
{
buffer.write(data, 0, nRead);
}
buffer.flush();
return buffer.toByteArray();
}
}
}
catch (IOException e)
{
e.printStackTrace();
}
return null;
}
}

View File

@@ -1,14 +0,0 @@
package net.runelite.client.rs.bytecode;
public class Hooks {
public String clientInstance = "";
public String actorClass = "";
public String projectileClass = "";
public String playerClass = "";
public String[] protectedStuff;
public String clientClass = "";
public Hooks() {
}
}

View File

@@ -1,106 +0,0 @@
package net.runelite.client.rs.bytecode.transformers;
import javassist.CannotCompileException;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.CtNewMethod;
import javassist.NotFoundException;
import lombok.extern.slf4j.Slf4j;
import net.runelite.client.rs.bytecode.ByteCodePatcher;
@Slf4j
public class ActorTransform implements Transform
{
private CtClass ct;
@Override
public void modify(Class actor)
{
try
{
ct = ByteCodePatcher.classPool.get(actor.getName());
transformGetAnimation();
transformAnimationChanged();
transformGraphicChanged();
ByteCodePatcher.modifiedClasses.add(ct);
}
catch (CannotCompileException | NotFoundException e)
{
e.printStackTrace();
}
}
private void transformGetAnimation() throws CannotCompileException, NotFoundException
{
CtMethod protectedAnimation = ct.getDeclaredMethod("1protect$getRsAnimation");
ct.removeMethod(protectedAnimation);
protectedAnimation.setName("getRsAnimation");
ct.addMethod(protectedAnimation);
CtMethod getAnimation = ct.getDeclaredMethod("getAnimation");
ct.removeMethod(getAnimation);
getAnimation = CtNewMethod.make(
"public int getAnimation()" +
"{" +
" return this.getRsAnimation();" +
"}", ct);
ct.addMethod(getAnimation);
log.info(
"[RuneLitePlus] transformed {} ({}) at class: {}",
this.getClass().getSimpleName(),
new Object(){}.getClass().getEnclosingMethod().getName(),
ct.getName()
);
}
private void transformAnimationChanged() throws CannotCompileException, NotFoundException
{
CtMethod getAnimationChanged = ct.getDeclaredMethod("animationChanged", new CtClass[]{CtClass.intType});
ct.removeMethod(getAnimationChanged);
getAnimationChanged = CtNewMethod.make(
"public void animationChanged(int n)" +
"{" +
" net.runelite.api.events.AnimationChanged animationChanged = new net.runelite.api.events.AnimationChanged();" +
" animationChanged.setActor((net.runelite.api.Actor) this);" +
ByteCodePatcher.clientInstance + ".getCallbacks().post((java.lang.Object)animationChanged);" +
"}", ct);
ct.addMethod(getAnimationChanged);
log.info(
"[RuneLitePlus] transformed {} ({}) at class: {}",
this.getClass().getSimpleName(),
new Object(){}.getClass().getEnclosingMethod().getName(),
ct.getName()
);
}
private void transformGraphicChanged() throws CannotCompileException, NotFoundException
{
CtMethod graphicChanged = ct.getDeclaredMethod("graphicChanged", new CtClass[]{CtClass.intType});
ct.removeMethod(graphicChanged);
graphicChanged = CtNewMethod.make(
"public void graphicChanged(int paramInt)" +
"{" +
" net.runelite.api.events.GraphicChanged localGraphicChanged = new net.runelite.api.events.GraphicChanged();" +
" localGraphicChanged.setActor(this);" +
ByteCodePatcher.clientInstance + ".getCallbacks().post(localGraphicChanged);" +
"}", ct);
ct.addMethod(graphicChanged);
log.info(
"[RuneLitePlus] transformed {} ({}) at class: {}",
this.getClass().getSimpleName(),
new Object(){}.getClass().getEnclosingMethod().getName(),
ct.getName()
);
}
}

View File

@@ -1,642 +0,0 @@
package net.runelite.client.rs.bytecode.transformers;
import javassist.CannotCompileException;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.CtNewMethod;
import javassist.NotFoundException;
import javassist.bytecode.AnnotationsAttribute;
import javassist.bytecode.ClassFile;
import javassist.bytecode.ConstPool;
import lombok.extern.slf4j.Slf4j;
import net.runelite.client.rs.bytecode.ByteCodePatcher;
@Slf4j
public class ClientTransform implements Transform
{
private CtClass ct;
@Override
public void modify(Class clazz)
{
try
{
ct = ByteCodePatcher.classPool.get(clazz.getName());
transformProtectedGetMenuOptions();
transformProtectedGetMenuTargets();
transformProtectedGetMenuIdentifiers();
transformProtectedGetMenuTypes();
transformProtectedGetMenuActionParams0();
transformProtectedGetMenuActionParams1();
transformGetMenuEntries();
transformSetMenuEntries();
transformOnMenuOptionsChanged();
transformGetProjectiles();
transformGetCollisionMaps();
transformDraw2010Menu();
transformRenderSelf();
transformboundingBoxCheck();
transformcheckClickBox();
ByteCodePatcher.modifiedClasses.add(ct);
}
catch (Exception e)
{
e.printStackTrace();
}
}
private void transformProtectedGetMenuOptions() throws CannotCompileException, NotFoundException
{
CtMethod protectedGetMenuOptions;
protectedGetMenuOptions = ct.getDeclaredMethod("1protect$getMenuOptions");
ct.removeMethod(protectedGetMenuOptions);
protectedGetMenuOptions.setName("getMenuOptions");
ct.addMethod(protectedGetMenuOptions);
log.info(
"[RuneLitePlus] transformed {} ({}) at class: {}",
this.getClass().getSimpleName(),
new Object(){}.getClass().getEnclosingMethod().getName(),
ct.getName()
);
}
private void transformGetProjectiles() throws CannotCompileException, NotFoundException
{
CtMethod getProjectiles;
CtMethod getProjectilesDeque = ct.getDeclaredMethod("1protect$getProjectilesDeque");
ct.removeMethod(getProjectilesDeque);
getProjectilesDeque.setName("getProjectilesDeque");
ct.addMethod(getProjectilesDeque);
getProjectiles = ct.getDeclaredMethod("getProjectiles");
ct.removeMethod(getProjectiles);
getProjectiles = CtNewMethod.make(
"public java.util.List getProjectiles() { " +
"java.util.ArrayList localArrayList = new java.util.ArrayList();" +
"net.runelite.rs.api.RSDeque localRSDeque = getProjectilesDeque();" +
"net.runelite.rs.api.RSNode localRSNode = localRSDeque.getHead();" +
"for (net.runelite.api.Node localNode = localRSNode.getNext(); localNode != localRSNode; localNode = localNode.getNext()) {" +
"net.runelite.api.Projectile localProjectile = (net.runelite.api.Projectile)localNode;" +
"localArrayList.add(localProjectile); }" +
"return localArrayList; }", ct);
ct.addMethod(getProjectiles);
ClassFile classFile = ct.getClassFile();
ConstPool constPool = classFile.getConstPool();
AnnotationsAttribute attr = new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag);
javassist.bytecode.annotation.Annotation annotation = new javassist.bytecode.annotation.Annotation("Override", constPool);
attr.setAnnotation(annotation);
getProjectiles.getMethodInfo().addAttribute(attr);
log.info(
"[RuneLitePlus] transformed {} ({}) at class: {}",
this.getClass().getSimpleName(),
new Object(){}.getClass().getEnclosingMethod().getName(),
ct.getName()
);
}
private void transformProtectedGetMenuTargets() throws CannotCompileException, NotFoundException
{
CtMethod protectedGetMenuTargets;
protectedGetMenuTargets = ct.getDeclaredMethod("1protect$getMenuTargets");
ct.removeMethod(protectedGetMenuTargets);
protectedGetMenuTargets.setName("getMenuTargets");
ct.addMethod(protectedGetMenuTargets);
log.info(
"[RuneLitePlus] transformed {} ({}) at class: {}",
this.getClass().getSimpleName(),
new Object(){}.getClass().getEnclosingMethod().getName(),
ct.getName()
);
}
private void transformGetCollisionMaps() throws CannotCompileException, NotFoundException
{
CtMethod getCollisionMaps;
CtMethod protectedMaps = ct.getDeclaredMethod("1protect$getRsCollisionMaps");
ct.removeMethod(protectedMaps);
protectedMaps.setName("getRsCollisionMaps");
ct.addMethod(protectedMaps);
getCollisionMaps = ct.getDeclaredMethod("getCollisionMaps");
ct.removeMethod(getCollisionMaps);
getCollisionMaps = CtMethod.make("public net.runelite.rs.api.RSCollisionData[] getCollisionMaps() { return getRsCollisionMaps(); }", ct);
ct.addMethod(getCollisionMaps);
log.info(
"[RuneLitePlus] transformed {} ({}) at class: {}",
this.getClass().getSimpleName(),
new Object(){}.getClass().getEnclosingMethod().getName(),
ct.getName()
);
}
private void transformProtectedGetMenuIdentifiers() throws CannotCompileException, NotFoundException
{
CtMethod protectedGetMenuIdentifiers;
protectedGetMenuIdentifiers = ct.getDeclaredMethod("1protect$getMenuIdentifiers");
ct.removeMethod(protectedGetMenuIdentifiers);
protectedGetMenuIdentifiers.setName("getMenuIdentifiers");
ct.addMethod(protectedGetMenuIdentifiers);
log.info(
"[RuneLitePlus] transformed {} ({}) at class: {}",
this.getClass().getSimpleName(),
new Object(){}.getClass().getEnclosingMethod().getName(),
ct.getName()
);
}
private void transformProtectedGetMenuTypes() throws CannotCompileException, NotFoundException
{
CtMethod protectedGetMenuTypes;
protectedGetMenuTypes = ct.getDeclaredMethod("1protect$getMenuTypes");
// Don't remove as this is referenced elsewhere in client
// ct.removeMethod(protectedGetMenuTypes);
CtMethod newProtectedGetMenuTypes = CtNewMethod.copy(protectedGetMenuTypes, ct, null);
newProtectedGetMenuTypes.setName("getMenuTypes");
ct.addMethod(newProtectedGetMenuTypes);
log.info(
"[RuneLitePlus] transformed {} ({}) at class: {}",
this.getClass().getSimpleName(),
new Object(){}.getClass().getEnclosingMethod().getName(),
ct.getName()
);
}
private void transformProtectedGetMenuActionParams0() throws CannotCompileException, NotFoundException
{
CtMethod protectedGetMenuActionParams0;
protectedGetMenuActionParams0 = ct.getDeclaredMethod("1protect$getMenuActionParams0");
ct.removeMethod(protectedGetMenuActionParams0);
protectedGetMenuActionParams0.setName("getMenuActionParams0");
ct.addMethod(protectedGetMenuActionParams0);
log.info(
"[RuneLitePlus] transformed {} ({}) at class: {}",
this.getClass().getSimpleName(),
new Object(){}.getClass().getEnclosingMethod().getName(),
ct.getName()
);
}
private void transformProtectedGetMenuActionParams1() throws CannotCompileException, NotFoundException
{
CtMethod protectedGetMenuActionParams1;
protectedGetMenuActionParams1 = ct.getDeclaredMethod("1protect$getMenuActionParams1");
ct.removeMethod(protectedGetMenuActionParams1);
protectedGetMenuActionParams1.setName("getMenuActionParams1");
ct.addMethod(protectedGetMenuActionParams1);
log.info(
"[RuneLitePlus] transformed {} ({}) at class: {}",
this.getClass().getSimpleName(),
new Object(){}.getClass().getEnclosingMethod().getName(),
ct.getName()
);
}
private void transformGetMenuEntries() throws CannotCompileException, NotFoundException
{
CtMethod getMenuEntries;
getMenuEntries = ct.getDeclaredMethod("getMenuEntries");
ct.removeMethod(getMenuEntries);
getMenuEntries = CtMethod.make(
"public net.runelite.api.MenuEntry[] getMenuEntries()" +
"{" +
" int n2 = this.getMenuOptionCount();" +
" String[] arrstring = this.getMenuOptions();" +
" String[] arrstring2 = this.getMenuTargets();" +
" int[] arrn = this.getMenuIdentifiers();" +
" int[] arrn2 = this.getMenuTypes();" +
" int[] arrn3 = this.getMenuActionParams0();" +
" int[] arrn4 = this.getMenuActionParams1();" +
" boolean[] arrbl = this.getMenuForceLeftClick();" +
" net.runelite.api.MenuEntry[] arrmenuEntry = new net.runelite.api.MenuEntry[n2];" +
" int n3 = 0;" +
" while (n3 < n2) " +
" {" +
" net.runelite.api.MenuEntry menuEntry = arrmenuEntry[n3] = new net.runelite.api.MenuEntry();" +
" menuEntry.setOption(arrstring[n3]);" +
" menuEntry.setTarget(arrstring2[n3]);" +
" menuEntry.setIdentifier(arrn[n3]);" +
" menuEntry.setType(arrn2[n3]);" +
" menuEntry.setParam0(arrn3[n3]);" +
" menuEntry.setParam1(arrn4[n3]);" +
" menuEntry.setForceLeftClick(arrbl[n3]);" +
" ++n3;" +
" }" +
" return arrmenuEntry;" +
"}", ct);
ct.addMethod(getMenuEntries);
log.info(
"[RuneLitePlus] transformed {} ({}) at class: {}",
this.getClass().getSimpleName(),
new Object(){}.getClass().getEnclosingMethod().getName(),
ct.getName()
);
}
private void transformSetMenuEntries() throws CannotCompileException, NotFoundException
{
CtMethod setMenuEntries;
setMenuEntries = ct.getDeclaredMethod("setMenuEntries");
ct.removeMethod(setMenuEntries);
setMenuEntries = CtNewMethod.make(
"public void setMenuEntries(net.runelite.api.MenuEntry[] arrmenuEntry)" +
"{" +
" int n2 = 0;" +
" String[] arrstring = this.getMenuOptions();" +
" String[] arrstring2 = this.getMenuTargets();" +
" int[] arrn = this.getMenuIdentifiers();" +
" int[] arrn2 = this.getMenuTypes();" +
" int[] arrn3 = this.getMenuActionParams0();" +
" int[] arrn4 = this.getMenuActionParams1();" +
" boolean[] arrbl = getMenuForceLeftClick();" +
" net.runelite.api.MenuEntry[] arrmenuEntry2 = arrmenuEntry;" +
" int n3 = arrmenuEntry2.length;" +
" int n4 = 0;" +
" do" +
" {" +
" String string;" +
" if (n4 >= n3)" +
" {" +
" this.setMenuOptionCount(n2);" +
" oldMenuEntryCount = n2;" +
" return;" +
" }" +
" net.runelite.api.MenuEntry menuEntry = arrmenuEntry2[n4];" +
" int n5 = menuEntry.getType();" +
" arrstring[n2] = menuEntry.getOption();" +
" arrstring2[n2] = menuEntry.getTarget();" +
" arrn[n2] = menuEntry.getIdentifier();" +
" arrn2[n2] = n5;" +
" arrn3[n2] = menuEntry.getParam0();" +
" arrn4[n2] = menuEntry.getParam1();" +
" arrbl[n2] = menuEntry.isForceLeftClick();" +
" ++n2;" +
" ++n4;" +
" } while (true);" +
"}"
, ct);
ct.addMethod(setMenuEntries);
}
private void transformOnMenuOptionsChanged() throws CannotCompileException, NotFoundException
{
CtMethod onMenuOptionsChanged;
onMenuOptionsChanged = ct.getDeclaredMethod("onMenuOptionsChanged", new CtClass[]{CtClass.intType});
ct.removeMethod(onMenuOptionsChanged);
onMenuOptionsChanged = CtMethod.make(
"public static void onMenuOptionsChanged(int n2)" +
"{" +
" int n3;" +
" int n4 = oldMenuEntryCount;" +
" oldMenuEntryCount = n3 = " + ByteCodePatcher.clientInstance + ".getMenuOptionCount();" +
" if (n3 != n4 + 1) return;" +
" net.runelite.api.events.MenuEntryAdded menuEntryAdded = new net.runelite.api.events.MenuEntryAdded(" +
ByteCodePatcher.clientInstance + ".getMenuOptions()[n3 - 1]," +
ByteCodePatcher.clientInstance + ".getMenuTargets()[n3 - 1]," +
ByteCodePatcher.clientInstance + ".getMenuTypes()[n3 - 1]," +
ByteCodePatcher.clientInstance + ".getMenuIdentifiers()[n3 - 1]," +
ByteCodePatcher.clientInstance + ".getMenuActionParams0()[n3 - 1]," +
ByteCodePatcher.clientInstance + ".getMenuActionParams1()[n3 - 1]);" +
ByteCodePatcher.clientInstance + ".getCallbacks().post((Object)menuEntryAdded);" +
"}"
, ct);
ct.addMethod(onMenuOptionsChanged);
log.info(
"[RuneLitePlus] transformed {} ({}) at class: {}",
this.getClass().getSimpleName(),
new Object(){}.getClass().getEnclosingMethod().getName(),
ct.getName()
);
}
private void transformRenderSelf() throws CannotCompileException
{
CtMethod renderSelf;
renderSelf = CtMethod.make("public void toggleRenderSelf() { jb = !jb; }", ct);
ClassFile classFile = ct.getClassFile();
ConstPool constPool = classFile.getConstPool();
AnnotationsAttribute attr = new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag);
javassist.bytecode.annotation.Annotation annotation = new javassist.bytecode.annotation.Annotation("Export", constPool);
attr.setAnnotation(annotation);
renderSelf.getMethodInfo().addAttribute(attr);
ct.addMethod(renderSelf);
log.info(
"[RuneLitePlus] transformed {} ({}) at class: {}",
this.getClass().getSimpleName(),
new Object(){}.getClass().getEnclosingMethod().getName(),
ct.getName()
);
}
private void transformDraw2010Menu() throws CannotCompileException, NotFoundException
{
CtMethod draw2010Menu;
draw2010Menu = ct.getDeclaredMethod("draw2010Menu");
ct.removeMethod(draw2010Menu);
draw2010Menu = CtNewMethod.make(
"public void draw2010Menu()" +
"{" +
" int n2 = this.getMenuX();" +
" int n3 = this.getMenuY();" +
" int n4 = this.getMenuWidth();" +
" int n5 = this.getMenuHeight();" +
" this.RasterizerDrawHorizontalLine(n2 + 2, n3, n4 - 4, 7170651);" +
" this.RasterizerDrawHorizontalLine(n2 + 2, n3 + n5 - 1, n4 - 4, 7170651);" +
" this.RasterizerDrawVerticalLine(n2, n3 + 2, n5 - 4, 7170651);" +
" this.RasterizerDrawVerticalLine(n2 + n4 - 1, n3 + 2, n5 - 4, 7170651);" +
" this.RasterizerDrawRectangle(n2 + 1, n3 + 5, n4 - 2, n5 - 6, 2827810);" +
" this.RasterizerDrawHorizontalLine(n2 + 1, n3 + 17, n4 - 2, 2827810);" +
" this.RasterizerDrawCircle(n2 + 2, n3 + n5 - 3, 0, 2827810);" +
" this.RasterizerDrawCircle(n2 + n4 - 3, n3 + n5 - 3, 0, 2827810);" +
" this.RasterizerDrawGradient(n2 + 2, n3 + 1, n4 - 4, 16, 3288610, 592388);" +
" this.RasterizerFillRectangle(n2 + 1, n3 + 1, 2, 4, 2827810);" +
" this.RasterizerFillRectangle(n2 + n4 - 3, n3 + 1, 2, 4, 2827810);" +
" this.RasterizerDrawHorizontalLine(n2 + 2, n3 + 18, n4 - 4, 5392957);" +
" this.RasterizerDrawHorizontalLine(n2 + 3, n3 + n5 - 3, n4 - 6, 5392957);" +
" this.RasterizerDrawVerticalLine(n2 + 2, n3 + 18, n5 - 21, 5392957);" +
" this.RasterizerDrawVerticalLine(n2 + n4 - 3, n3 + 18, n5 - 21, 5392957);" +
" this.RasterizerFillRectangle(n2 + 3, n3 + 19, n4 - 6, n5 - 22, 2828060);" +
" this.RasterizerDrawCircle(n2 + 1, n3 + 1, 0, 7170651);" +
" this.RasterizerDrawCircle(n2 + n4 - 2, n3 + 1, 0, 7170651);" +
" this.RasterizerDrawCircle(n2 + 1, n3 + n5 - 2, 0, 7170651);" +
" this.RasterizerDrawCircle(n2 + n4 - 2, n3 + n5 - 2, 0, 7170651);" +
" net.runelite.rs.api.RSFont rSFont = this.getFontBold12();" +
" rSFont.drawTextLeftAligned(\"Choose Option\", n2 + 3, n3 + 14, 13023381, -1);" +
" int n6 = this.getMouseX();" +
" int n7 = this.getMouseY();" +
" int n8 = this.getMenuOptionCount();" +
" String[] arrstring = this.getMenuTargets();" +
" String[] arrstring2 = this.getMenuOptions();" +
" for (int i = 0; i < n8; ++i)" +
" {" +
" int n9 = n3 + (n8 - 1 - i) * 15 + 31;" +
" String string = arrstring2[i];" +
" if (!arrstring[i].isEmpty())" +
" {" +
" string = string + \" \" + arrstring[i];" +
" }" +
" rSFont.drawTextLeftAligned(string, n2 + 3, n9, 13023381, -1);" +
" if (n6 <= n2 || n6 >= n4 + n2 || n7 <= n9 - 13 || n7 >= n9 + 3)" +
" {" +
" continue;" +
" }" +
" this.RasterizerFillRectangleAlpha(n2 + 3, n9 - 12, n4 - 6, 15, 16777215, 80);" +
" }" +
"}"
, ct);
ct.addMethod(draw2010Menu);
log.info(
"[RuneLitePlus] transformed {} ({}) at class: {}",
this.getClass().getSimpleName(),
new Object(){}.getClass().getEnclosingMethod().getName(),
ct.getName()
);
}
//TODO: fix not being able to click far away objects towards top of screen only.
private void transformboundingBoxCheck() throws CannotCompileException
{
CtMethod boundingboxCheck2;
boundingboxCheck2 = CtMethod.make(
"public boolean boundingboxCheck2(net.runelite.api.Model model, int n2, int n3, int n4)" +
"{" +
" int n5 = " + ByteCodePatcher.clientInstance + ".getCameraPitch();" +
" int n6 = " + ByteCodePatcher.clientInstance + ".getCameraYaw();" +
" int n7 = net.runelite.api.Perspective.SINE[n5];" +
" int n8 = net.runelite.api.Perspective.COSINE[n5];" +
" int n9 = net.runelite.api.Perspective.SINE[n6];" +
" int n10 = net.runelite.api.Perspective.COSINE[n6];" +
" int n11 = " + ByteCodePatcher.clientInstance + ".getCenterX();" +
" int n12 = " + ByteCodePatcher.clientInstance + ".getCenterY();" +
" int n13 = " + ByteCodePatcher.clientInstance + ".getViewportMouseX();" +
" int n14 = " + ByteCodePatcher.clientInstance + ".getViewportMouseY();" +
" int n15 = " + ByteCodePatcher.clientInstance + ".get3dZoom();" +
" int n16 = (n13 - n11) * 50 / n15;" +
" int n17 = (n14 - n12) * 50 / n15;" +
" int n18 = (n13 - n11) * 10000 / n15;" +
" int n19 = (n14 - n12) * 10000 / n15;" +
" int n20 = client.rl$rot1(n17, 50, n8, n7);" +
" int n21 = client.rl$rot2(n17, 50, n8, n7);" +
" n17 = n20;" +
" n20 = client.rl$rot1(n19, 10000, n8, n7);" +
" int n22 = client.rl$rot2(n19, 10000, n8, n7);" +
" n19 = n20;" +
" n20 = client.rl$rot3(n16, n21, n10, n9);" +
" n21 = client.rl$rot4(n16, n21, n10, n9);" +
" n16 = n20;" +
" n20 = client.rl$rot3(n18, n22, n10, n9);" +
" n22 = client.rl$rot4(n18, n22, n10, n9);" +
" int n23 = (n20 - n16) / 2;" +
" int n24 = (n19 - n17) / 2;" +
" int n25 = (n22 - n21) / 2;" +
" int n26 = Math.abs(n23);" +
" int n27 = Math.abs(n24);" +
" int n28 = Math.abs(n25);" +
" int n29 = n2 + model.getCenterX();" +
" int n30 = n3 + model.getCenterY();" +
" int n31 = n4 + model.getCenterZ();" +
" int n32 = model.getExtremeX();" +
" int n33 = model.getExtremeY();" +
" int n34 = model.getExtremeZ();" +
" int n35 = (n16 + n20) / 2;" +
" int n36 = (n17 + n19) / 2;" +
" int n37 = (n22 + n21) / 2;" +
" int n38 = n35 - n29;" +
" int n39 = n36 - n30;" +
" int n40 = n37 - n31;" +
" if (Math.abs(n38) > n32 + n26)" +
" {" +
" return false;" +
" }" +
" if (Math.abs(n39) > n33 + n27)" +
" {" +
" return false;" +
" }" +
" if (Math.abs(n40) > n34 + n28)" +
" {" +
" return false;" +
" }" +
" if (Math.abs(n40 * n24 - n39 * n25) > n33 * n28 + n34 * n27)" +
" {" +
" return false;" +
" }" +
" if (Math.abs(n38 * n25 - n40 * n23) > n34 * n26 + n32 * n28)" +
" {" +
" return false;" +
" }" +
" if (Math.abs(n39 * n23 - n38 * n24) <= n33 * n26 + n32 * n27)" +
" {" +
" return true;" +
" }" +
" return false;" +
"}", ct);
ct.addMethod(boundingboxCheck2);
log.info(
"[RuneLitePlus] transformed {} ({}) at class: {}",
this.getClass().getSimpleName(),
new Object(){}.getClass().getEnclosingMethod().getName(),
ct.getName()
);
}
private void transformcheckClickBox() throws CannotCompileException, NotFoundException
{
CtMethod checkClickBox;
checkClickBox = ct.getDeclaredMethod("checkClickbox");
ct.removeMethod(checkClickBox);
checkClickBox = CtMethod.make(
"public void checkClickbox(net.runelite.api.Model model, int n2, int n3, int n4, int n5, int n6, int n7, int n8, int n9, long l2) {" +
" int n10;" +
" int n11;" +
" int n12;" +
" int n13;" +
" int n14;" +
" net.runelite.rs.api.RSModel rSModel = (net.runelite.rs.api.RSModel)model;" +
" boolean bl2 = l2 != 0L && (int)(l2 >>> 16 & 1L) != 1;" +
" boolean bl3 = " + ByteCodePatcher.clientInstance + ".getViewportContainsMouse();" +
" if (!bl2)" +
" {" +
" return;" +
" }" +
" if (!bl3)" +
" {" +
" return;" +
" }" +
" boolean bl4 = this.boundingboxCheck2((net.runelite.api.Model)rSModel, n7, n8, n9);" +
" if (!bl4)" +
" {" +
" return;" +
" }" +
" if (rSModel.isClickable())" +
" {" +
" this.addHashAtMouse(l2);" +
" return;" +
" }" +
" int n15 = rSModel.getVerticesCount();" +
" int n16 = rSModel.getTrianglesCount();" +
" int[] arrn = rSModel.getVerticesX();" +
" int[] arrn2 = rSModel.getVerticesY();" +
" int[] arrn3 = rSModel.getVerticesZ();" +
" int[] arrn4 = rSModel.getTrianglesX();" +
" int[] arrn5 = rSModel.getTrianglesY();" +
" int[] arrn6 = rSModel.getTrianglesZ();" +
" int[] arrn7 = rSModel.getFaceColors3();" +
" int n17 = " + ByteCodePatcher.clientInstance + ".get3dZoom();" +
" int n18 = " + ByteCodePatcher.clientInstance + ".getCenterX();" +
" int n19 = " + ByteCodePatcher.clientInstance + ".getCenterY();" +
" int n20 = 0;" +
" int n21 = 0;" +
" if (n2 != 0)" +
" {" +
" n20 = net.runelite.api.Perspective.SINE[n2];" +
" n21 = net.runelite.api.Perspective.COSINE[n2];" +
" }" +
" for (n14 = 0; n14 < n15; ++n14)" +
" {" +
" n11 = arrn[n14];" +
" n13 = arrn2[n14];" +
" n12 = arrn3[n14];" +
" if (n2 != 0)" +
" {" +
" n10 = n12 * n20 + n11 * n21 >> 16;" +
" n12 = n12 * n21 - n11 * n20 >> 16;" +
" n11 = n10;" +
" }" +
" n10 = (n12 += n9) * n5 + n6 * (n11 += n7) >> 16;" +
" n12 = n6 * n12 - n11 * n5 >> 16;" +
" n11 = n10;" +
" n10 = n4 * (n13 += n8) - n12 * n3 >> 16;" +
" if ((n12 = n13 * n3 + n4 * n12 >> 16) >= 50)" +
" {" +
" client.rl$modelViewportYs[n14] = n11 * n17 / n12 + n18;" +
" client.rl$modelViewportXs[n14] = n10 * n17 / n12 + n19;" +
" continue;" +
" }" +
" client.rl$modelViewportYs[n14] = -5000;" +
" }" +
" n14 = " + ByteCodePatcher.clientInstance + ".getViewportMouseX();" +
" n11 = " + ByteCodePatcher.clientInstance + ".getViewportMouseY();" +
" n13 = 0;" +
" while (n13 < n16)" +
" {" +
" if (arrn7[n13] != -2)" +
" {" +
" int n22;" +
" boolean bl5;" +
" int n23;" +
" n12 = arrn4[n13];" +
" n10 = arrn5[n13];" +
" int n24 = arrn6[n13];" +
" int n25 = rl$modelViewportYs[n12];" +
" int n26 = rl$modelViewportYs[n10];" +
" int n27 = rl$modelViewportYs[n24];" +
" int n28 = rl$modelViewportXs[n12];" +
" int n29 = rl$modelViewportXs[n10];" +
" int n30 = rl$modelViewportXs[n24];" +
" if (n25 != -5000 && n26 != -5000 && n27 != -5000 && (bl5 = (n23 = (n22 = rSModel.isClickable() ? 20 : 5) + n11) < n28 && n23 < n29 && n23 < n30 ? false : ((n23 = n11 - n22) > n28 && n23 > n29 && n23 > n30 ? false : ((n23 = n22 + n14) < n25 && n23 < n26 && n23 < n27 ? false : (n23 = n14 - n22) <= n25 || n23 <= n26 || n23 <= n27))))" +
" {" +
" this.addHashAtMouse(l2);" +
" return;" +
" }" +
" }" +
" ++n13;" +
" }" +
"}", ct);
ct.addMethod(checkClickBox);
log.info(
"[RuneLitePlus] transformed {} ({}) at class: {}",
this.getClass().getSimpleName(),
new Object(){}.getClass().getEnclosingMethod().getName(),
ct.getName()
);
}
}

View File

@@ -1,57 +0,0 @@
package net.runelite.client.rs.bytecode.transformers;
import javassist.CannotCompileException;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.NotFoundException;
import lombok.extern.slf4j.Slf4j;
import net.runelite.client.rs.bytecode.ByteCodePatcher;
@Slf4j
// This prevents the client from sending stack traces to Jagex at all, even classes outside of runelite.
public class ErrorTransform implements Transform
{
private CtClass ct;
// Where Runelites error interceptor is located, not auto-scraped.
private static final String ERROR_INSTANCE_CLASS = "dp";
private static final String ERROR_INSTANCE_METHOD = "a";
// private static final String ERROR_WARNING = "Tried to send a warning";
@Override
public void modify(Class clazz)
{
try
{
ct = ByteCodePatcher.classPool.get(ERROR_INSTANCE_CLASS);
transformError();
ByteCodePatcher.modifiedClasses.add(ct);
}
catch (CannotCompileException | NotFoundException e)
{
e.printStackTrace();
}
}
private void transformError() throws CannotCompileException, NotFoundException
{
CtMethod error = ct.getDeclaredMethod(ERROR_INSTANCE_METHOD);
ct.removeMethod(error);
error = CtMethod.make(
"public static void a(String string, Throwable throwable, byte by)" +
"{" +
" throwable.printStackTrace();" +
" System.out.println(\"[RuneLitePlus] Prevented preceeding stack trace from being sent to Jagex\");" +
"}", ct);
ct.addMethod(error);
log.info(
"[RuneLitePlus] transformed {} ({}) at class: {}",
this.getClass().getSimpleName(),
new Object(){}.getClass().getEnclosingMethod().getName(),
ct.getName()
);
}
}

View File

@@ -1,89 +0,0 @@
package net.runelite.client.rs.bytecode.transformers;
import javassist.CannotCompileException;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.CtNewMethod;
import javassist.NotFoundException;
import lombok.extern.slf4j.Slf4j;
import net.runelite.client.rs.bytecode.ByteCodePatcher;
@Slf4j
public class PlayerTransform implements Transform
{
private CtClass ct;
@Override
public void modify(Class player)
{
try
{
ct = ByteCodePatcher.classPool.get(player.getName());
transformProtectedGetSkullIcon();
transformGetSkullIcon();
ByteCodePatcher.modifiedClasses.add(ct);
}
catch (CannotCompileException | NotFoundException e)
{
e.printStackTrace();
}
}
private void transformProtectedGetSkullIcon() throws CannotCompileException, NotFoundException
{
CtMethod protectedGetSkullIcon;
protectedGetSkullIcon = ct.getDeclaredMethod("1protect$getRsSkullIcon");
ct.removeMethod(protectedGetSkullIcon);
protectedGetSkullIcon.setName("getRsSkullIcon");
ct.addMethod(protectedGetSkullIcon);
log.info(
"[RuneLitePlus] transformed {} ({}) at class: {}",
this.getClass().getSimpleName(),
new Object(){}.getClass().getEnclosingMethod().getName(),
ct.getName()
);
}
private void transformGetSkullIcon() throws CannotCompileException, NotFoundException
{
CtMethod getSkullIcon;
String SkullIcon = "net.runelite.api.SkullIcon";
getSkullIcon = ct.getDeclaredMethod("getSkullIcon");
ct.removeMethod(getSkullIcon);
getSkullIcon = CtNewMethod.make(
"public " + SkullIcon + " getSkullIcon()" +
"{" +
"switch (this.getRsSkullIcon())" +
"{" +
"case 0:" +
"return " + SkullIcon + ".SKULL;" +
"case 1:" +
"return " + SkullIcon + ".SKULL_FIGHT_PIT;" +
"case 8:" +
"return " + SkullIcon + ".DEAD_MAN_FIVE;" +
"case 9:" +
"return " + SkullIcon + ".DEAD_MAN_FOUR;" +
"case 10:" +
"return " + SkullIcon + ".DEAD_MAN_THREE;" +
"case 11:" +
"return " + SkullIcon + ".DEAD_MAN_TWO;" +
"case 12:" +
"return " + SkullIcon + ".DEAD_MAN_ONE;" +
"}" +
"return null;" +
"}", ct);
ct.addMethod(getSkullIcon);
log.info(
"[RuneLitePlus] transformed {} ({}) at class: {}",
this.getClass().getSimpleName(),
new Object(){}.getClass().getEnclosingMethod().getName(),
ct.getName()
);
}
}

View File

@@ -1,112 +0,0 @@
package net.runelite.client.rs.bytecode.transformers;
import javassist.CannotCompileException;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.CtNewMethod;
import javassist.NotFoundException;
import lombok.extern.slf4j.Slf4j;
import net.runelite.client.rs.bytecode.ByteCodePatcher;
@Slf4j
public class ProjectileTransform implements Transform
{
private CtClass ct;
// Next variable is manually added, and will break on rev update
private static final String interactingIntvalue = "-1655053057";
@Override
public void modify(Class projectile)
{
try
{
ct = ByteCodePatcher.classPool.get(projectile.getName());
transformGetAnimation();
transformInteracting();
ByteCodePatcher.modifiedClasses.add(ct);
}
catch (CannotCompileException | NotFoundException e)
{
e.printStackTrace();
}
}
private void transformGetAnimation() throws CannotCompileException, NotFoundException
{
CtMethod getAnimation;
getAnimation = ct.getDeclaredMethod("projectileMoved", new CtClass[]{CtClass.intType, CtClass.intType, CtClass.intType, CtClass.intType});
ct.removeMethod(getAnimation);
getAnimation = CtNewMethod.make(
"public void projectileMoved(int n, int n2, int n3, int n4)" +
"{ " +
" int n5 = this.getId();" +
" net.runelite.api.coords.LocalPoint localPoint = new net.runelite.api.coords.LocalPoint(n, n2);" +
" net.runelite.api.events.ProjectileMoved projectileMoved = new net.runelite.api.events.ProjectileMoved();" +
" projectileMoved.setProjectile(this);" +
" projectileMoved.setPosition(localPoint);" +
" projectileMoved.setZ(n3);" +
ByteCodePatcher.clientInstance + ".getCallbacks().post(projectileMoved);" +
"}", ct);
ct.addMethod(getAnimation);
log.info(
"[RuneLitePlus] transformed {} ({}) at class: {}",
this.getClass().getSimpleName(),
new Object(){}.getClass().getEnclosingMethod().getName(),
ct.getName()
);
}
private void transformInteracting() throws CannotCompileException
{
CtMethod getRsInteracting;
CtMethod getInteracting;
getRsInteracting = CtNewMethod.make("public int getRsInteracting() { return this.n * " + interactingIntvalue + "; }", ct);
ct.addMethod(getRsInteracting);
getInteracting = CtNewMethod.make(
"public net.runelite.api.Actor getInteracting()" +
"{" +
" int var1 = this.getRsInteracting();" +
" if (var1 == 0)" +
" {" +
" return null;" +
" }" +
" else" +
" {" +
" int var2;" +
" if (var1 > 0)" +
" {" +
" var2 = var1 - 1;" +
" net.runelite.rs.api.RSNPC[] var4 = " + ByteCodePatcher.clientInstance + ".getCachedNPCs();" +
" return var4[var2];" +
" }" +
" else" +
" {" +
" var2 = -var1 - 1;" +
" if (var2 == " + ByteCodePatcher.clientInstance + ".getLocalInteractingIndex())" +
" {" +
" return " + ByteCodePatcher.clientInstance + ".getLocalPlayer();" +
" }" +
" else" +
" {" +
" net.runelite.rs.api.RSPlayer[] var3 = " + ByteCodePatcher.clientInstance + ".getCachedPlayers();" +
" return var3[var2];" +
" }" +
" }" +
" }" +
"}", ct);
ct.addMethod(getInteracting);
log.info(
"[RuneLitePlus] transformed {} ({}) at class: {}",
this.getClass().getSimpleName(),
new Object(){}.getClass().getEnclosingMethod().getName(),
ct.getName()
);
}
}

View File

@@ -1,7 +0,0 @@
package net.runelite.client.rs.bytecode.transformers;
public interface Transform {
void modify(Class clazz);
}

View File

@@ -0,0 +1,134 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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.client.rs.mixins;
import lombok.RequiredArgsConstructor;
import net.runelite.client.rs.mixins.transformers.*;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.commons.ClassRemapper;
import org.objectweb.asm.commons.Remapper;
import org.objectweb.asm.tree.ClassNode;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
@RequiredArgsConstructor
public class MixinRunner
{
private final Map<String, byte[]> classes;
private final Map<String, byte[]> patches;
public Map<String, byte[]> run()
throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException
{
runVisitor(InterfaceTransformer.class);
runVisitor(OverwriteTransformer.class);
runSanityChecker(OverwriteSanityCheck.class);
runVisitor(InjectTransformer.class);
runVisitor(AppendTransformer.class); // append has to come before prepend or append does nothing
// (test method: Projectile.rl$$init()V )
runVisitor(PrependTransformer.class);
runRemapper(ProtectTransformer.class);
recalcMaxes();
return classes;
}
private void runRemapper(Class<? extends Remapper> clazz) throws IllegalAccessException, InstantiationException
{
for (Map.Entry<String, byte[]> entry : classes.entrySet())
{
if (entry.getKey().contains("META-INF"))
{
continue;
}
Remapper inst = clazz.newInstance();
ClassReader cr = new ClassReader(entry.getValue());
ClassWriter cw = new ClassWriter(cr, 1);
cr.accept(new ClassRemapper(cw, inst), 0);
entry.setValue(cw.toByteArray());
}
}
private void runVisitor(Class<? extends ClassVisitor> clazz)
throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException
{
runVisitor(clazz, 1);
}
private void runVisitor(Class<? extends ClassVisitor> clazz, int flags)
throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException
{
for (Map.Entry<String, byte[]> entry : classes.entrySet())
{
if (entry.getKey().contains("META-INF"))
{
continue;
}
ClassReader cr = new ClassReader(entry.getValue());
ClassWriter cw = new ClassWriter(cr, flags);
byte[] patch = patches.getOrDefault(entry.getKey(), null);
ClassNode node = new ClassNode();
cr.accept(node, 0);
ClassVisitor inst = clazz.getConstructor(ClassVisitor.class, byte[].class, ClassNode.class).newInstance(cw,
patch, node);
cr.accept(inst, 0);
entry.setValue(cw.toByteArray());
}
}
private void runSanityChecker(Class<? extends SanityChecker> clazz)
throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException
{
runSanityChecker(clazz, 1);
}
private void runSanityChecker(Class<? extends SanityChecker> clazz, int flags)
throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException
{
for (Map.Entry<String, byte[]> entry : patches.entrySet())
{
ClassReader cr = new ClassReader(entry.getValue());
ClassWriter cw = new ClassWriter(cr, flags);
ClassNode node = new ClassNode();
cr.accept(node, 0);
SanityChecker inst = clazz.getConstructor(ClassVisitor.class, ClassNode.class).newInstance(cw, node);
cr.accept(inst, 0);
}
}
private void recalcMaxes()
throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException
{
runVisitor(DoNothingTransformer.class, 3);
}
}

View File

@@ -0,0 +1,120 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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.client.rs.mixins.transformers;
import lombok.extern.slf4j.Slf4j;
import net.runelite.client.util.RefUtils;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.LabelNode;
import org.objectweb.asm.tree.LineNumberNode;
import org.objectweb.asm.tree.MethodNode;
@Slf4j
public class AppendTransformer extends ClassVisitor implements Opcodes
{
private final byte[] patch;
private String className;
private ClassNode classNode;
public AppendTransformer(ClassVisitor classVisitor, byte[] patch, ClassNode node)
{
super(Opcodes.ASM6, classVisitor);
this.patch = patch;
this.classNode = node;
}
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces)
{
className = name;
super.visit(version, access, name, signature, superName, interfaces);
}
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions)
{
if (patch == null)
{
return super.visitMethod(access, name, descriptor, signature, exceptions);
}
ClassReader cr = new ClassReader(patch);
ClassNode patchNode = new ClassNode(Opcodes.ASM6);
cr.accept(patchNode, 0);
for (Object obj : patchNode.methods)
{
MethodNode patchMethod = (MethodNode) obj;
if ((patchMethod.access == access && patchMethod.name.equals("append$" + name) &&
patchMethod.desc.equals(descriptor)) &&
RefUtils.checkAnnotation(patchMethod, "Append"))
{
MethodVisitor mv =
new MethodVisitor(Opcodes.ASM6, super.visitMethod(access, name, descriptor, signature,
exceptions))
{
};
mv.visitCode();
for (Object obj2 : classNode.methods)
{
MethodNode classMethod = (MethodNode) obj2;
if (classMethod.access == access && classMethod.name.equals(name) &&
classMethod.desc.equals(descriptor))
{
AbstractInsnNode inode = classMethod.instructions.getLast();
while(inode instanceof LabelNode || inode instanceof LineNumberNode)
{
inode = inode.getPrevious();
}
if(RefUtils.isReturn(inode.getOpcode(), true))
{
log.error("[Append] Can't append to {}.{}, requires typed return opcode", className, name);
return super.visitMethod(access, name, descriptor, signature, exceptions);
}
classMethod.instructions.remove(inode);
classMethod.accept(new MethodReflector(mv));
break;
}
}
patchMethod.accept(new MethodReflector(mv));
mv.visitEnd();
return mv;
}
}
return super.visitMethod(access, name, descriptor, signature, exceptions);
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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.client.rs.mixins.transformers;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.ClassNode;
public class DoNothingTransformer extends ClassVisitor
{
public DoNothingTransformer(ClassVisitor parent, byte[] patch, ClassNode node)
{
super(Opcodes.ASM6, parent);
}
}

View File

@@ -0,0 +1,125 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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.client.rs.mixins.transformers;
import net.runelite.client.util.RefUtils;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.MethodNode;
public class InjectTransformer extends ClassVisitor
{
private final byte[] patch;
private ClassNode node;
private String className;
private boolean patching = false;
public InjectTransformer(ClassVisitor classVisitor, byte[] patch, ClassNode node)
{
super(Opcodes.ASM6, classVisitor);
this.patch = patch;
this.node = node;
}
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces)
{
className = name;
super.visit(version, access, name, signature, superName, interfaces);
}
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions)
{
if (patch == null || name.startsWith("1protect$"))
{
return super.visitMethod(access, name, descriptor, signature, exceptions);
}
if (name.startsWith("prepend$") || name.startsWith("append$")||
(patching && name.startsWith("<")))
{
return null;
}
MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
ClassReader cr = new ClassReader(patch);
ClassNode patchNode = new ClassNode(Opcodes.ASM6);
cr.accept(patchNode, 0);
for (Object obj : patchNode.methods)
{
MethodNode node = (MethodNode) obj;
if ((node.access == access && node.name.equals(name) && node.desc.equals(descriptor)) &&
RefUtils.checkAnnotation(node, "Inject"))
{
mv.visitCode();
node.accept(new MethodReflector(mv));
mv.visitEnd();
}
}
return mv;
}
@Override
public void visitEnd()
{
if (patch == null)
{
super.visitEnd();
return;
}
ClassReader cr = new ClassReader(patch);
ClassNode patchNode = new ClassNode(Opcodes.ASM6);
cr.accept(patchNode, 0);
patching = true;
for (Object obj : patchNode.methods)
{
MethodNode node = (MethodNode) obj;
if (RefUtils.checkAnnotation(node, "Inject"))
{
visitMethod(node.access, node.name, node.desc, node.signature,
(String[]) node.exceptions.toArray(new String[0]));
}
}
for (Object obj : patchNode.fields)
{
FieldNode node = (FieldNode) obj;
if (RefUtils.checkAnnotation(node, "Inject"))
{
visitField(node.access, node.name, node.desc, node.signature, node.value);
}
}
patching = false;
super.visitEnd();
}
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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.client.rs.mixins.transformers;
import lombok.extern.slf4j.Slf4j;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.ClassNode;
import java.util.ArrayList;
import java.util.Arrays;
@Slf4j
public class InterfaceTransformer extends ClassVisitor implements Opcodes
{
private final byte[] patch;
private ClassNode node;
private String className;
public InterfaceTransformer(ClassVisitor classVisitor, byte[] patch, ClassNode node)
{
super(Opcodes.ASM6, classVisitor);
this.patch = patch;
this.node = node;
}
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces)
{
className = name;
if(patch != null)
{
ClassReader reader = new ClassReader(patch);
ClassNode pNode = new ClassNode();
reader.accept(pNode, 0);
if(pNode.interfaces != null && pNode.interfaces.size() != 0)
{
if(interfaces == null)
{
interfaces = (String[]) pNode.interfaces.toArray(new String[0]);
}
else
{
ArrayList<String> list = new ArrayList<>(Arrays.asList(interfaces));
pNode.interfaces.forEach((s) -> list.add((String) s));
interfaces = list.toArray(new String[0]);
}
}
}
super.visit(version, access, name, signature, superName, interfaces);
}
}

View File

@@ -0,0 +1,295 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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.client.rs.mixins.transformers;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.Handle;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.TypePath;
public class MethodReflector extends MethodVisitor
{
private MethodVisitor target;
public MethodReflector(MethodVisitor target)
{
super(Opcodes.ASM6);
this.target = target;
}
public void visitParameter(String var1, int var2)
{
if (target != null)
{
target.visitParameter(var1, var2);
}
super.visitParameter(var1, var2);
}
public AnnotationVisitor visitAnnotationDefault()
{
return super.visitAnnotationDefault();
}
public AnnotationVisitor visitAnnotation(String var1, boolean var2)
{
return super.visitAnnotation(var1, var2);
}
public AnnotationVisitor visitTypeAnnotation(int var1, TypePath var2, String var3, boolean var4)
{
return super.visitTypeAnnotation(var1, var2, var3, var4);
}
public AnnotationVisitor visitParameterAnnotation(int var1, String var2, boolean var3)
{
return super.visitParameterAnnotation(var1, var2, var3);
}
public void visitAttribute(Attribute var1)
{
if (target != null)
{
target.visitAttribute(var1);
}
super.visitAttribute(var1);
}
public void visitFrame(int var1, int var2, Object[] var3, int var4, Object[] var5)
{
if (target != null)
{
target.visitFrame(var1, var2, var3, var4, var5);
}
super.visitFrame(var1, var2, var3, var4, var5);
}
public void visitInsn(int var1)
{
if (target != null)
{
target.visitInsn(var1);
}
super.visitInsn(var1);
}
public void visitIntInsn(int var1, int var2)
{
if (target != null)
{
target.visitIntInsn(var1, var2);
}
super.visitIntInsn(var1, var2);
}
public void visitVarInsn(int var1, int var2)
{
if (target != null)
{
target.visitVarInsn(var1, var2);
}
super.visitVarInsn(var1, var2);
}
public void visitTypeInsn(int var1, String var2)
{
if (target != null)
{
target.visitTypeInsn(var1, var2);
}
super.visitTypeInsn(var1, var2);
}
public void visitFieldInsn(int var1, String var2, String var3, String var4)
{
if (target != null)
{
target.visitFieldInsn(var1, var2, var3, var4);
}
super.visitFieldInsn(var1, var2, var3, var4);
}
/**
* @deprecated
*/
public void visitMethodInsn(int var1, String var2, String var3, String var4)
{
if (target != null)
{
target.visitMethodInsn(var1, var2, var3, var4);
}
super.visitMethodInsn(var1, var2, var3, var4);
}
public void visitMethodInsn(int var1, String var2, String var3, String var4, boolean var5)
{
if (target != null)
{
target.visitMethodInsn(var1, var2, var3, var4, var5);
}
super.visitMethodInsn(var1, var2, var3, var4, var5);
}
public void visitInvokeDynamicInsn(String var1, String var2, Handle var3, Object... var4)
{
if (target != null)
{
target.visitInvokeDynamicInsn(var1, var2, var3, var4);
}
super.visitInvokeDynamicInsn(var1, var2, var3, var4);
}
public void visitJumpInsn(int var1, Label var2)
{
if (target != null)
{
target.visitJumpInsn(var1, var2);
}
super.visitJumpInsn(var1, var2);
}
public void visitLabel(Label var1)
{
if (target != null)
{
target.visitLabel(var1);
}
super.visitLabel(var1);
}
public void visitLdcInsn(Object var1)
{
if (target != null)
{
target.visitLdcInsn(var1);
}
super.visitLdcInsn(var1);
}
public void visitIincInsn(int var1, int var2)
{
if (target != null)
{
target.visitIincInsn(var1, var2);
}
super.visitIincInsn(var1, var2);
}
public void visitTableSwitchInsn(int var1, int var2, Label var3, Label... var4)
{
if (target != null)
{
target.visitTableSwitchInsn(var1, var2, var3, var4);
}
super.visitTableSwitchInsn(var1, var2, var3, var4);
}
public void visitLookupSwitchInsn(Label var1, int[] var2, Label[] var3)
{
if (target != null)
{
target.visitLookupSwitchInsn(var1, var2, var3);
}
super.visitLookupSwitchInsn(var1, var2, var3);
}
public void visitMultiANewArrayInsn(String var1, int var2)
{
if (target != null)
{
target.visitMultiANewArrayInsn(var1, var2);
}
super.visitMultiANewArrayInsn(var1, var2);
}
public AnnotationVisitor visitInsnAnnotation(int var1, TypePath var2, String var3, boolean var4)
{
if (target != null)
{
target.visitInsnAnnotation(var1, var2, var3, var4);
}
return super.visitInsnAnnotation(var1, var2, var3, var4);
}
public void visitTryCatchBlock(Label var1, Label var2, Label var3, String var4)
{
if (target != null)
{
target.visitTryCatchBlock(var1, var2, var3, var4);
}
super.visitTryCatchBlock(var1, var2, var3, var4);
}
public AnnotationVisitor visitTryCatchAnnotation(int var1, TypePath var2, String var3, boolean var4)
{
if (target != null)
{
target.visitTryCatchAnnotation(var1, var2, var3, var4);
}
return super.visitTryCatchAnnotation(var1, var2, var3, var4);
}
public void visitLocalVariable(String var1, String var2, String var3, Label var4, Label var5, int var6)
{
if (target != null)
{
target.visitLocalVariable(var1, var2, var3, var4, var5, var6);
}
super.visitLocalVariable(var1, var2, var3, var4, var5, var6);
}
public AnnotationVisitor visitLocalVariableAnnotation(int var1, TypePath var2, Label[] var3, Label[] var4, int[] var5, String var6, boolean var7)
{
if (target != null)
{
target.visitLocalVariableAnnotation(var1, var2, var3, var4, var5, var6, var7);
}
return super.visitLocalVariableAnnotation(var1, var2, var3, var4, var5, var6, var7);
}
public void visitLineNumber(int var1, Label var2)
{
if (target != null)
{
target.visitLineNumber(var1, var2);
}
super.visitLineNumber(var1, var2);
}
public void visitMaxs(int var1, int var2)
{
if (target != null)
{
target.visitMaxs(var1, var2);
}
super.visitMaxs(var1, var2);
}
}

View File

@@ -0,0 +1,87 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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.client.rs.mixins.transformers;
import lombok.extern.slf4j.Slf4j;
import net.runelite.client.util.RefUtils;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode;
import java.util.ArrayList;
@Slf4j
public class OverwriteSanityCheck extends SanityChecker implements Opcodes
{
private String className;
private ClassNode patchNode;
public static final ArrayList<String> methodsUsed = new ArrayList<>();
public OverwriteSanityCheck(ClassVisitor classVisitor, ClassNode node)
{
super(ASM6, classVisitor);
this.className = node.name;
this.patchNode = node;
}
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions)
{
String check = String.format("%s %s %s %s", className, name,
descriptor, access);
MethodNode methodNode = null;
for (Object obj2 : patchNode.methods)
{
MethodNode classMethod = (MethodNode) obj2;
if (classMethod.access == access && classMethod.name.equals(name) &&
classMethod.desc.equals(descriptor))
{
methodNode = classMethod;
}
}
if(methodNode == null)
{
log.error("[OverwriteSanity] Failed to find original patch method for {}", check);
return super.visitMethod(access, name, descriptor, signature, exceptions);
}
if (!RefUtils.checkAnnotation(methodNode, "Overwrite"))
{
return super.visitMethod(access, name, descriptor, signature, exceptions);
}
if (!methodsUsed.contains(check))
{
throw new RuntimeException("[OverwriteSanity] Overwrite target not found: " + check);
}
return super.visitMethod(access, name, descriptor, signature, exceptions);
}
}

View File

@@ -0,0 +1,102 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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.client.rs.mixins.transformers;
import lombok.extern.slf4j.Slf4j;
import net.runelite.client.util.RefUtils;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode;
@Slf4j
public class OverwriteTransformer extends ClassVisitor
{
private final byte[] patch;
private ClassNode node;
private String className;
public OverwriteTransformer(ClassVisitor classVisitor, byte[] patch, ClassNode node)
{
super(Opcodes.ASM6, classVisitor);
this.patch = patch;
this.node = node;
this.className = node.name;
}
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces)
{
className = name;
super.visit(version, access, name, signature, superName, interfaces);
}
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions)
{
if (patch == null || name.startsWith("1protect$"))
{
return super.visitMethod(access, name, descriptor, signature, exceptions);
}
if (name.startsWith("prepend$") || name.startsWith("append$"))
{
return null;
}
ClassReader cr = new ClassReader(patch);
ClassNode patchNode = new ClassNode(Opcodes.ASM6);
cr.accept(patchNode, 0);
for (Object obj : patchNode.methods)
{
MethodNode patchMethod = (MethodNode) obj;
if (patchMethod.access == access && patchMethod.name.equals(name) && patchMethod.desc.equals(descriptor))
{
if (RefUtils.checkAnnotation(patchMethod, "Overwrite"))
{
MethodVisitor mv =
new MethodVisitor(Opcodes.ASM6, super.visitMethod(access, name, descriptor, signature,
exceptions))
{
};
mv.visitCode();
patchMethod.accept(new MethodReflector(mv));
mv.visitEnd();
String s = String.format("%s %s %s %s", className, patchMethod.name,
patchMethod.desc, patchMethod.access);
OverwriteSanityCheck.methodsUsed.add(s);
return mv;
}
}
}
return super.visitMethod(access, name, descriptor, signature, exceptions);
}
}

View File

@@ -0,0 +1,125 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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.client.rs.mixins.transformers;
import net.runelite.client.util.RefUtils;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.MethodNode;
public class PrependTransformer extends ClassVisitor
{
private final byte[] patch;
private String className;
private ClassNode classNode;
public PrependTransformer(ClassVisitor classVisitor, byte[] patch, ClassNode node)
{
super(Opcodes.ASM6, classVisitor);
this.patch = patch;
this.classNode = node;
}
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces)
{
className = name;
super.visit(version, access, name, signature, superName, interfaces);
}
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions)
{
if (patch == null)
{
return super.visitMethod(access, name, descriptor, signature, exceptions);
}
ClassReader cr = new ClassReader(patch);
ClassNode patchNode = new ClassNode(Opcodes.ASM6);
cr.accept(patchNode, 0);
for (Object obj : patchNode.methods)
{
MethodNode patchMethod = (MethodNode) obj;
if ((patchMethod.access == access && patchMethod.name.equals("prepend$" + name) &&
patchMethod.desc.equals(descriptor)) &&
RefUtils.checkAnnotation(patchMethod, "Prepend"))
{
MethodVisitor mv =
new MethodVisitor(Opcodes.ASM6, super.visitMethod(access, name, descriptor, signature,
exceptions))
{
};
mv.visitCode();
AbstractInsnNode node = patchMethod.instructions.getLast();
while (!(node instanceof InsnNode))
{
node = node.getPrevious();
}
if (RefUtils.isReturn(node.getOpcode()))
{
patchMethod.instructions.remove(node);
}
patchMethod.accept(new MethodReflector(mv));
for (Object obj2 : classNode.methods)
{
MethodNode classMethod = (MethodNode) obj2;
if (classMethod.access == access && classMethod.name.equals(name) &&
classMethod.desc.equals(descriptor))
{
classMethod.accept(new MethodReflector(mv));
break;
}
}
mv.visitEnd();
return mv;
}
}
return super.visitMethod(access, name, descriptor, signature, exceptions);
}
@Override
public void visitEnd()
{
if (patch == null)
{
super.visitEnd();
return;
}
super.visitEnd();
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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.client.rs.mixins.transformers;
import org.objectweb.asm.commons.Remapper;
public class ProtectTransformer extends Remapper
{
public String mapFieldName(String owner, String name, String descriptor)
{
if (name.startsWith("1protect$"))
{
name = name.substring("1protect$".length());
}
return super.mapFieldName(owner, name, descriptor);
}
public String mapMethodName(String owner, String name, String descriptor)
{
if (name.startsWith("1protect$"))
{
name = name.substring("1protect$".length());
}
return super.mapMethodName(owner, name, descriptor);
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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.client.rs.mixins.transformers;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Opcodes;
public abstract class SanityChecker extends ClassVisitor implements Opcodes
{
protected SanityChecker(int i, ClassVisitor classVisitor)
{
super(i, classVisitor);
}
}

View File

@@ -0,0 +1,84 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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.client.util;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AnnotationNode;
import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.MethodNode;
public class RefUtils implements Opcodes
{
private static final String TYPE_PREFIX = "us/runelitepl/mixinprocessor/annotations/";
public static boolean isReturn(int opcode, boolean checkType)
{
return (opcode == RETURN && !checkType) || opcode == IRETURN || opcode == LRETURN || opcode == DRETURN ||
opcode == ARETURN || opcode == FRETURN;
}
public static boolean isReturn(int opcode)
{
return isReturn(opcode, false);
}
public static boolean checkAnnotation(MethodNode method, String annotation)
{
if (method.visibleAnnotations != null)
{
for (Object obj : method.visibleAnnotations)
{
if (((AnnotationNode) obj).desc.equals(makeAnnotationDesc(annotation)))
{
return true;
}
}
}
return false;
}
public static boolean checkAnnotation(FieldNode field, String annotation)
{
if (field.visibleAnnotations != null)
{
for (Object obj : field.visibleAnnotations)
{
if (((AnnotationNode) obj).desc.equals(makeAnnotationDesc(annotation)))
{
return true;
}
}
}
return false;
}
public static String makeAnnotationDesc(String annot)
{
return "L" + TYPE_PREFIX + annot + ";";
}
}

View File

@@ -975,5 +975,11 @@ public interface RSClient extends RSGameEngine, Client
@Import("renderSelf")
void toggleRenderSelf();
@Import("mouseRecorder")
RSMouseRecorder getMouseRecorder();
@Import("printMenuActions")
void setPrintMenuActions(boolean b);
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) 2019, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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.rs.api;
import net.runelite.api.MouseRecorder;
import net.runelite.mapping.Import;
public interface RSMouseRecorder extends MouseRecorder
{
@Import("xs")
int[] getXs();
@Import("ys")
int[] getYs();
@Import("millis")
long[] getMillis();
@Import("index")
int getIndex();
}