This commit is contained in:
PKLite
2019-06-11 19:25:40 -04:00
98 changed files with 3387 additions and 1651 deletions

View File

@@ -1,13 +1,13 @@
language: java language: java
sudo: false sudo: false
dist: xenial dist: trusty
cache: cache:
directories: directories:
- $HOME/.m2 - $HOME/.m2
jdk: jdk:
- openjdk8 - oraclejdk8
- openjdk11
install: true install: true
script: ./travis/build.sh script: ./travis/build.sh
before_install: before_install:
- chmod +x ./travis/build.sh - chmod +x ./travis/build.sh

View File

@@ -30,7 +30,7 @@ import java.util.Properties;
public class CacheProperties public class CacheProperties
{ {
private static Properties getProperies() throws IOException private static Properties getProperties() throws IOException
{ {
Properties properties = new Properties(); Properties properties = new Properties();
InputStream resourceAsStream = StoreLocation.class.getResourceAsStream("/cache.properties"); InputStream resourceAsStream = StoreLocation.class.getResourceAsStream("/cache.properties");
@@ -40,11 +40,11 @@ public class CacheProperties
public static int getRsVersion() throws IOException public static int getRsVersion() throws IOException
{ {
return Integer.parseInt(getProperies().getProperty("rs.version")); return Integer.parseInt(getProperties().getProperty("rs.version"));
} }
public static int getCacheVersion() throws IOException public static int getCacheVersion() throws IOException
{ {
return Integer.parseInt(getProperies().getProperty("cache.version")); return Integer.parseInt(getProperties().getProperty("cache.version"));
} }
} }

View File

@@ -165,7 +165,7 @@ public class MapDumperTest
@Test @Test
@Ignore @Ignore
public void dunpJson() throws IOException public void dumpJson() throws IOException
{ {
File base = StoreLocation.LOCATION, File base = StoreLocation.LOCATION,
outDir = folder.newFolder(); outDir = folder.newFolder();

View File

@@ -203,10 +203,17 @@ public class Method
return (accessFlags & ACC_STATIC) != 0; return (accessFlags & ACC_STATIC) != 0;
} }
public void setStatic() public void setStatic(boolean s)
{
if (s)
{ {
accessFlags |= ACC_STATIC; accessFlags |= ACC_STATIC;
} }
else
{
accessFlags &= ~ACC_STATIC;
}
}
public boolean isSynchronized() public boolean isSynchronized()
{ {

View File

@@ -27,14 +27,10 @@ package net.runelite.deob;
import com.google.common.base.Stopwatch; import com.google.common.base.Stopwatch;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import net.runelite.asm.ClassFile;
import net.runelite.asm.ClassGroup; import net.runelite.asm.ClassGroup;
import net.runelite.asm.Field;
import net.runelite.asm.Method;
import net.runelite.asm.Type;
import net.runelite.asm.attributes.Annotations;
import net.runelite.asm.execution.Execution; import net.runelite.asm.execution.Execution;
import net.runelite.deob.deobfuscators.CastNull; import net.runelite.deob.deobfuscators.CastNull;
import net.runelite.deob.deobfuscators.StaticShouldBeInstance;
import net.runelite.deob.deobfuscators.constparam.ConstantParameter; import net.runelite.deob.deobfuscators.constparam.ConstantParameter;
import net.runelite.deob.deobfuscators.EnumDeobfuscator; import net.runelite.deob.deobfuscators.EnumDeobfuscator;
import net.runelite.deob.deobfuscators.FieldInliner; import net.runelite.deob.deobfuscators.FieldInliner;
@@ -85,28 +81,12 @@ public class Deob
ClassGroup group = JarUtil.loadJar(new File(args[0])); ClassGroup group = JarUtil.loadJar(new File(args[0]));
for (ClassFile f : group.getClasses()) if (args.length > 2 && args[2].equals("rl"))
{ {
f.getAnnotations().clearAnnotations(); run(group, new StaticShouldBeInstance());
for (Method m : f.getMethods())
{
Annotations an = m.getAnnotations();
an.clearAnnotations();
}
for (Field fi : f.getFields())
{
Annotations an = fi.getAnnotations();
if (an.find(new Type("Ljavax/inject/Inject;")) == null)
{
an.clearAnnotations();
} }
else else
{ {
logger.info("Class {}, field {} has inject", f.getClassName(), fi.getName());
}
}
}
// remove except RuntimeException // remove except RuntimeException
run(group, new RuntimeExceptions()); run(group, new RuntimeExceptions());
@@ -164,6 +144,7 @@ public class Deob
new ReflectionTransformer().transform(group); new ReflectionTransformer().transform(group);
new MaxMemoryTransformer().transform(group); new MaxMemoryTransformer().transform(group);
//new RuneliteBufferTransformer().transform(group); //new RuneliteBufferTransformer().transform(group);
}
JarUtil.saveJar(group, new File(args[1])); JarUtil.saveJar(group, new File(args[1]));

View File

@@ -0,0 +1,171 @@
package net.runelite.deob.deobfuscators;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import net.runelite.asm.ClassFile;
import net.runelite.asm.ClassGroup;
import net.runelite.asm.Field;
import net.runelite.asm.Type;
import net.runelite.asm.attributes.Annotations;
import net.runelite.asm.attributes.Code;
import net.runelite.asm.attributes.code.Instruction;
import net.runelite.asm.attributes.code.Instructions;
import net.runelite.asm.attributes.code.instruction.types.ReturnInstruction;
import net.runelite.asm.attributes.code.instructions.InvokeStatic;
import net.runelite.asm.attributes.code.instructions.InvokeVirtual;
import net.runelite.asm.pool.Method;
import net.runelite.asm.signature.Signature;
import net.runelite.deob.Deobfuscator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class StaticShouldBeInstance implements Deobfuscator
{
private static final Logger logger = LoggerFactory.getLogger(StaticShouldBeInstance.class);
private static Map<Method, Method> methods = new HashMap<>();
public void run(ClassGroup group)
{
int replacedCalls = 0;
int removedInstructions = 0;
int removedMethods = 0;
int removedAnnotations = 0;
List<net.runelite.asm.Method> obfuscatedMethods = new ArrayList<>();
for (ClassFile cf : group.getClasses())
{
// Remove unused annotations
Annotations a = cf.getAnnotations();
removedAnnotations += a.getAnnotations().size();
a.clearAnnotations();
Type type = new Type('L' + cf.getClassName() + ';');
obfuscatedMethods.clear();
for (net.runelite.asm.Method m : cf.getMethods())
{
// Remove unused annotations
a = m.getAnnotations();
removedAnnotations += a.size();
a.clearAnnotations();
if (m.isStatic() && m.getCode() != null)
{
if (checkIfObf(m, type, cf))
{
removedMethods++;
obfuscatedMethods.add(m);
}
}
}
for (net.runelite.asm.Method m : obfuscatedMethods)
{
Signature sig = m.getDescriptor();
Signature.Builder builder = new Signature.Builder();
builder.setReturnType(sig.getReturnValue());
if (sig.getArguments().size() > 1)
{
builder.addArguments(sig.getArguments().subList(1, sig.getArguments().size()));
}
Signature toFind = builder.build();
net.runelite.asm.Method notStatic = cf.findMethod(m.getName(), toFind);
net.runelite.asm.pool.Method oldPool = m.getPoolMethod();
cf.removeMethod(notStatic);
m.setDescriptor(toFind);
m.setStatic(false);
Code c = m.getCode();
Instructions ins = c.getInstructions();
int startLength = ins.getInstructions().size();
ListIterator<Instruction> it = ins.getInstructions().listIterator();
assert it.hasNext();
Instruction i = it.next();
while (!(i instanceof ReturnInstruction))
{
it.remove();
i = it.next();
}
it.remove();
net.runelite.asm.pool.Method newPool = m.getPoolMethod();
methods.put(oldPool, newPool);
removedInstructions += startLength - ins.getInstructions().size();
}
for (Field fi : cf.getFields())
{
a = fi.getAnnotations();
if (a.find(new Type("Ljavax/inject/Inject;")) == null)
{
removedAnnotations += a.size();
a.clearAnnotations();
}
else
{
logger.info("Class {}, field {} has inject", cf.getClassName(), fi.getName());
}
}
}
for (ClassFile cf : group.getClasses())
{
for (net.runelite.asm.Method m : cf.getMethods())
{
if (m.getCode() == null)
{
continue;
}
Instructions ins = m.getCode().getInstructions();
List<Instruction> instructions = ins.getInstructions();
for (int i1 = 0, instructionsSize = instructions.size(); i1 < instructionsSize; i1++)
{
Instruction i = instructions.get(i1);
if (!(i instanceof InvokeStatic))
{
continue;
}
if (methods.containsKey(((InvokeStatic) i).getMethod()))
{
InvokeVirtual invoke = new InvokeVirtual(ins, methods.get(((InvokeStatic) i).getMethod()));
ins.replace(i, invoke);
replacedCalls++;
}
}
}
}
logger.info("Made {} methods not static, removed {} instructions, replaced {} invokes, and removed {} annotations", removedMethods, removedInstructions, replacedCalls, removedAnnotations);
}
private static boolean checkIfObf(net.runelite.asm.Method m, Type type, ClassFile cf)
{
Signature sig = m.getDescriptor();
if (sig.getArguments().size() < 1 || !sig.getTypeOfArg(0).equals(type))
{
return false;
}
Signature.Builder builder = new Signature.Builder();
builder.setReturnType(sig.getReturnValue());
if (sig.getArguments().size() > 1)
{
builder.addArguments(sig.getArguments().subList(1, sig.getArguments().size()));
}
Signature toFind = builder.build();
net.runelite.asm.Method notStatic = cf.findMethod(m.getName(), toFind);
return notStatic != null;
}
}

View File

@@ -60,7 +60,7 @@ public class OpcodesTransformer implements Transformer
if (clinit == null) if (clinit == null)
{ {
clinit = new Method(runeliteOpcodes, "<clinit>", new Signature("()V")); clinit = new Method(runeliteOpcodes, "<clinit>", new Signature("()V"));
clinit.setStatic(); clinit.setStatic(true);
Code code = new Code(clinit); Code code = new Code(clinit);
code.setMaxStack(1); code.setMaxStack(1);
clinit.setCode(code); clinit.setCode(code);

View File

@@ -26,19 +26,24 @@ package net.runelite.deob.updater;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.Map;
import net.runelite.asm.ClassGroup; import net.runelite.asm.ClassGroup;
import net.runelite.asm.Field;
import net.runelite.asm.Method;
import net.runelite.deob.deobfuscators.Renamer;
import net.runelite.deob.deobfuscators.mapping.AnnotationIntegrityChecker; import net.runelite.deob.deobfuscators.mapping.AnnotationIntegrityChecker;
import net.runelite.deob.deobfuscators.mapping.AnnotationMapper; import net.runelite.deob.deobfuscators.mapping.AnnotationMapper;
import net.runelite.deob.deobfuscators.mapping.Mapper; import net.runelite.deob.deobfuscators.mapping.Mapper;
import net.runelite.deob.deobfuscators.mapping.ParallelExecutorMapping; import net.runelite.deob.deobfuscators.mapping.ParallelExecutorMapping;
import net.runelite.deob.util.JarUtil; import net.runelite.deob.util.JarUtil;
import net.runelite.deob.util.NameMappings;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class UpdateMappings public class UpdateMappings
{ {
private static final Logger logger = LoggerFactory.getLogger(UpdateMappings.class); private static final Logger logger = LoggerFactory.getLogger(UpdateMappings.class);
private static boolean renameRL = true;
private final ClassGroup group1, group2; private final ClassGroup group1, group2;
public UpdateMappings(ClassGroup group1, ClassGroup group2) public UpdateMappings(ClassGroup group1, ClassGroup group2)
@@ -74,6 +79,32 @@ public class UpdateMappings
pr.run(); pr.run();
} }
public void updateRL()
{
Mapper mapper = new Mapper(group1, group2);
mapper.run();
ParallelExecutorMapping mapping = mapper.getMapping();
NameMappings names = new NameMappings();
for (Map.Entry<Object, Object> e : mapping.getMap().entrySet())
{
Object k = e.getKey();
Object v = e.getValue();
if (k instanceof Field)
{
names.map(((Field) v).getPoolField(), ((Field) k).getName());
}
else if (k instanceof Method)
{
names.map(((Method) v).getPoolMethod(), ((Method) k).getName());
}
}
Renamer renamer = new Renamer(names);
renamer.run(group2);
}
public void save(File out) throws IOException public void save(File out) throws IOException
{ {
JarUtil.saveJar(group2, out); JarUtil.saveJar(group2, out);
@@ -90,7 +121,14 @@ public class UpdateMappings
JarUtil.loadJar(new File(args[0])), JarUtil.loadJar(new File(args[0])),
JarUtil.loadJar(new File(args[1])) JarUtil.loadJar(new File(args[1]))
); );
if (renameRL)
{
u.updateRL();
}
else
{
u.update(); u.update();
}
u.save(new File(args[2])); u.save(new File(args[2]));
} }
} }

View File

@@ -39,7 +39,7 @@ public class ClassGroupFactory
private static void addVoidMethod(ClassFile cf, String name) private static void addVoidMethod(ClassFile cf, String name)
{ {
Method method = new Method(cf, name, new Signature("()V")); Method method = new Method(cf, name, new Signature("()V"));
method.setStatic(); method.setStatic(true);
cf.addMethod(method); cf.addMethod(method);
Code code = new Code(method); Code code = new Code(method);
@@ -63,7 +63,7 @@ public class ClassGroupFactory
cf.addField(field); cf.addField(field);
Method method = new Method(cf, "func", new Signature("()V")); Method method = new Method(cf, "func", new Signature("()V"));
method.setStatic(); method.setStatic(true);
cf.addMethod(method); cf.addMethod(method);
Code code = new Code(method); Code code = new Code(method);
@@ -71,7 +71,7 @@ public class ClassGroupFactory
{ {
method = new Method(cf, "func2", new Signature("(III)V")); method = new Method(cf, "func2", new Signature("(III)V"));
method.setStatic(); method.setStatic(true);
cf.addMethod(method); cf.addMethod(method);
code = new Code(method); code = new Code(method);

View File

@@ -70,6 +70,7 @@ public class UpdateMappingsTest
} }
@Test @Test
@Ignore
public void testRun() throws IOException public void testRun() throws IOException
{ {
File client = new File(properties.getRsClient()); File client = new File(properties.getRsClient());

View File

@@ -52,6 +52,7 @@ import net.runelite.deob.util.JarUtil;
import net.runelite.deob.util.NameMappings; import net.runelite.deob.util.NameMappings;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.TemporaryFolder; import org.junit.rules.TemporaryFolder;
@@ -87,12 +88,13 @@ public class HookImporter
@After @After
public void after() throws IOException public void after() throws IOException
{ {
File out = new File("C:/Users/Lucas/Desktop/client.jar"); File out = folder.newFile("client.jar");
JarUtil.saveJar(group, out); JarUtil.saveJar(group, out);
logger.info("Wrote to {}", out); logger.info("Wrote to {}", out);
} }
@Test @Test
@Ignore
public void importHooks() public void importHooks()
{ {
int classes = 0, fields = 0, methods = 0, access = 0; int classes = 0, fields = 0, methods = 0, access = 0;

View File

@@ -1,3 +1,3 @@
rs.client=C:/Users/Lucas/Desktop/gamepack180_deob.jar rs.client=${net.runelite.rs:rs-client:jar}
rs.version=180 rs.version=180
vanilla.client=${net.runelite.rs:vanilla:jar} vanilla.client=${net.runelite.rs:vanilla:jar}

View File

@@ -96,7 +96,7 @@ public class AccountClient
} }
} }
public boolean sesssionCheck() public boolean sessionCheck()
{ {
HttpUrl url = RuneLiteAPI.getApiBase().newBuilder() HttpUrl url = RuneLiteAPI.getApiBase().newBuilder()
.addPathSegment("account") .addPathSegment("account")

View File

@@ -23,7 +23,8 @@
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 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"> <project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
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> <modelVersion>4.0.0</modelVersion>
<parent> <parent>

View File

@@ -47,23 +47,21 @@ import net.runelite.deob.DeobAnnotations;
import net.runelite.deob.deobfuscators.arithmetic.DMath; import net.runelite.deob.deobfuscators.arithmetic.DMath;
import net.runelite.injector.raw.ClearColorBuffer; import net.runelite.injector.raw.ClearColorBuffer;
import net.runelite.injector.raw.DrawAfterWidgets; import net.runelite.injector.raw.DrawAfterWidgets;
import net.runelite.injector.raw.DrawMenu;
import net.runelite.injector.raw.RasterizerHook; import net.runelite.injector.raw.RasterizerHook;
import net.runelite.injector.raw.RenderDraw; import net.runelite.injector.raw.RenderDraw;
import net.runelite.injector.raw.ScriptVM; import net.runelite.injector.raw.ScriptVM;
import net.runelite.mapping.Import; import net.runelite.mapping.Import;
import net.runelite.rs.api.RSClient;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import net.runelite.rs.api.RSClient;
public class Inject public class Inject
{ {
private static final Logger logger = LoggerFactory.getLogger(Inject.class);
public static final java.lang.Class<?> CLIENT_CLASS = RSClient.class; public static final java.lang.Class<?> CLIENT_CLASS = RSClient.class;
public static final String API_PACKAGE_BASE = "net.runelite.rs.api.RS"; public static final String API_PACKAGE_BASE = "net.runelite.rs.api.RS";
public static final String RL_API_PACKAGE_BASE = "net.runelite.api."; public static final String RL_API_PACKAGE_BASE = "net.runelite.api.";
private static final Logger logger = LoggerFactory.getLogger(Inject.class);
private final InjectHookMethod hookMethod = new InjectHookMethod(this); private final InjectHookMethod hookMethod = new InjectHookMethod(this);
private final InjectGetter getters = new InjectGetter(this); private final InjectGetter getters = new InjectGetter(this);
@@ -71,6 +69,7 @@ public class Inject
private final InjectInvoker invokes = new InjectInvoker(this); private final InjectInvoker invokes = new InjectInvoker(this);
private final InjectConstruct construct = new InjectConstruct(this); private final InjectConstruct construct = new InjectConstruct(this);
private final DrawMenu drawMenu = new DrawMenu(this);
private final RasterizerHook rasterizerHook = new RasterizerHook(this); private final RasterizerHook rasterizerHook = new RasterizerHook(this);
private final MixinInjector mixinInjector = new MixinInjector(this); private final MixinInjector mixinInjector = new MixinInjector(this);
private final DrawAfterWidgets drawAfterWidgets = new DrawAfterWidgets(this); private final DrawAfterWidgets drawAfterWidgets = new DrawAfterWidgets(this);
@@ -87,34 +86,6 @@ public class Inject
this.vanilla = vanilla; this.vanilla = vanilla;
} }
public Type getFieldType(Field f)
{
Type type = f.getType();
Annotation obfSignature = f.getAnnotations().find(DeobAnnotations.OBFUSCATED_SIGNATURE);
if (obfSignature != null)
{
//Annotation exists. Type was updated by us during deobfuscation
type = DeobAnnotations.getObfuscatedType(f);
}
return type;
}
public Signature getMethodSignature(Method m)
{
Signature signature = m.getDescriptor();
Annotation obfSignature = m.getAnnotations().find(DeobAnnotations.OBFUSCATED_SIGNATURE);
if (obfSignature != null)
{
//Annotation exists. Signature was updated by us during deobfuscation
signature = DeobAnnotations.getObfuscatedSignature(m);
}
return signature;
}
/** /**
* Convert a java.lang.Class to a Type * Convert a java.lang.Class to a Type
* *
@@ -173,6 +144,34 @@ public class Inject
return Type.getType("L" + c.getName().replace('.', '/') + ";", dimms); return Type.getType("L" + c.getName().replace('.', '/') + ";", dimms);
} }
public Type getFieldType(Field f)
{
Type type = f.getType();
Annotation obfSignature = f.getAnnotations().find(DeobAnnotations.OBFUSCATED_SIGNATURE);
if (obfSignature != null)
{
//Annotation exists. Type was updated by us during deobfuscation
type = DeobAnnotations.getObfuscatedType(f);
}
return type;
}
public Signature getMethodSignature(Method m)
{
Signature signature = m.getDescriptor();
Annotation obfSignature = m.getAnnotations().find(DeobAnnotations.OBFUSCATED_SIGNATURE);
if (obfSignature != null)
{
//Annotation exists. Signature was updated by us during deobfuscation
signature = DeobAnnotations.getObfuscatedSignature(m);
}
return signature;
}
/** /**
* Build a Signature from a java method * Build a Signature from a java method
* *
@@ -334,6 +333,7 @@ public class Inject
scriptVM.inject(); scriptVM.inject();
clearColorBuffer.inject(); clearColorBuffer.inject();
renderDraw.inject(); renderDraw.inject();
drawMenu.inject();
} }
private java.lang.Class injectInterface(ClassFile cf, ClassFile other) private java.lang.Class injectInterface(ClassFile cf, ClassFile other)

View File

@@ -54,7 +54,7 @@ public class InjectConstruct
private final Inject inject; private final Inject inject;
public InjectConstruct(Inject inject) InjectConstruct(Inject inject)
{ {
this.inject = inject; this.inject = inject;
} }
@@ -99,7 +99,7 @@ public class InjectConstruct
} }
} }
public void injectConstruct(ClassFile targetClass, java.lang.reflect.Method apiMethod) throws InjectionException void injectConstruct(ClassFile targetClass, java.lang.reflect.Method apiMethod) throws InjectionException
{ {
logger.info("Injecting construct for {}", apiMethod); logger.info("Injecting construct for {}", apiMethod);

View File

@@ -44,7 +44,7 @@ import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class InjectGetter class InjectGetter
{ {
private static final Logger logger = LoggerFactory.getLogger(InjectGetter.class); private static final Logger logger = LoggerFactory.getLogger(InjectGetter.class);
@@ -52,12 +52,12 @@ public class InjectGetter
private int injectedGetters; private int injectedGetters;
public InjectGetter(Inject inject) InjectGetter(Inject inject)
{ {
this.inject = inject; this.inject = inject;
} }
public void injectGetter(ClassFile clazz, java.lang.reflect.Method method, Field field, Number getter) void injectGetter(ClassFile clazz, java.lang.reflect.Method method, Field field, Number getter)
{ {
// clazz = class file we're injecting the method into. // clazz = class file we're injecting the method into.
// method = api method (java reflect) that we're overriding // method = api method (java reflect) that we're overriding
@@ -148,7 +148,7 @@ public class InjectGetter
++injectedGetters; ++injectedGetters;
} }
public int getInjectedGetters() int getInjectedGetters()
{ {
return injectedGetters; return injectedGetters;
} }

View File

@@ -41,9 +41,11 @@ import net.runelite.asm.attributes.code.instruction.types.SetFieldInstruction;
import net.runelite.asm.attributes.code.instructions.ArrayStore; import net.runelite.asm.attributes.code.instructions.ArrayStore;
import net.runelite.asm.attributes.code.instructions.CheckCast; import net.runelite.asm.attributes.code.instructions.CheckCast;
import net.runelite.asm.attributes.code.instructions.Dup; import net.runelite.asm.attributes.code.instructions.Dup;
import net.runelite.asm.attributes.code.instructions.IMul;
import net.runelite.asm.attributes.code.instructions.InvokeStatic; import net.runelite.asm.attributes.code.instructions.InvokeStatic;
import net.runelite.asm.attributes.code.instructions.InvokeVirtual; import net.runelite.asm.attributes.code.instructions.InvokeVirtual;
import net.runelite.asm.attributes.code.instructions.LDC; import net.runelite.asm.attributes.code.instructions.LDC;
import net.runelite.asm.attributes.code.instructions.LMul;
import net.runelite.asm.attributes.code.instructions.PutField; import net.runelite.asm.attributes.code.instructions.PutField;
import net.runelite.asm.attributes.code.instructions.Swap; import net.runelite.asm.attributes.code.instructions.Swap;
import net.runelite.asm.execution.Execution; import net.runelite.asm.execution.Execution;
@@ -53,28 +55,16 @@ import net.runelite.asm.signature.Signature;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class InjectHook class InjectHook
{ {
private static final Logger logger = LoggerFactory.getLogger(InjectHook.class); private static final Logger logger = LoggerFactory.getLogger(InjectHook.class);
static class HookInfo
{
String fieldName;
String clazz;
Method method;
boolean before;
}
private static final String HOOK_METHOD_SIGNATURE = "(I)V"; private static final String HOOK_METHOD_SIGNATURE = "(I)V";
private static final String CLINIT = "<clinit>"; private static final String CLINIT = "<clinit>";
private final Inject inject; private final Inject inject;
private final Map<Field, HookInfo> hooked = new HashMap<>(); private final Map<Field, HookInfo> hooked = new HashMap<>();
private int injectedHooks; private int injectedHooks;
public InjectHook(Inject inject) InjectHook(Inject inject)
{ {
this.inject = inject; this.inject = inject;
} }
@@ -84,7 +74,7 @@ public class InjectHook
hooked.put(field, hookInfo); hooked.put(field, hookInfo);
} }
public void run() void run()
{ {
Execution e = new Execution(inject.getVanilla()); Execution e = new Execution(inject.getVanilla());
e.populateInitialMethods(); e.populateInitialMethods();
@@ -139,8 +129,7 @@ public class InjectHook
StackContext objectStackContext = null; StackContext objectStackContext = null;
if (sfi instanceof PutField) if (sfi instanceof PutField)
{ {
StackContext objectStack = ic.getPops().get(1); // Object being set on objectStackContext = ic.getPops().get(1);
objectStackContext = objectStack;
} }
int idx = ins.getInstructions().indexOf(sfi); int idx = ins.getInstructions().indexOf(sfi);
@@ -216,8 +205,7 @@ public class InjectHook
StackContext objectStackContext = null; StackContext objectStackContext = null;
if (arrayReferencePushed.getInstruction().getType() == InstructionType.GETFIELD) if (arrayReferencePushed.getInstruction().getType() == InstructionType.GETFIELD)
{ {
StackContext objectReference = arrayReferencePushed.getPops().get(0); objectStackContext = arrayReferencePushed.getPops().get(0);
objectStackContext = objectReference;
} }
// inject hook after 'i' // inject hook after 'i'
@@ -262,6 +250,21 @@ public class InjectHook
ins.getInstructions().add(idx++, new Dup(ins)); // dup value ins.getInstructions().add(idx++, new Dup(ins)); // dup value
idx = recursivelyPush(ins, idx, object); idx = recursivelyPush(ins, idx, object);
ins.getInstructions().add(idx++, new Swap(ins)); ins.getInstructions().add(idx++, new Swap(ins));
if (hookInfo.getter != null)
{
assert hookInfo.getter instanceof Integer || hookInfo.getter instanceof Long;
if (hookInfo.getter instanceof Integer)
{
ins.getInstructions().add(idx++, new LDC(ins, (int) hookInfo.getter));
ins.getInstructions().add(idx++, new IMul(ins));
}
else
{
ins.getInstructions().add(idx++, new LDC(ins, (long) hookInfo.getter));
ins.getInstructions().add(idx++, new LMul(ins));
}
}
if (!value.type.equals(methodArgumentType)) if (!value.type.equals(methodArgumentType))
{ {
CheckCast checkCast = new CheckCast(ins); CheckCast checkCast = new CheckCast(ins);
@@ -377,8 +380,17 @@ public class InjectHook
} }
} }
public int getInjectedHooks() int getInjectedHooks()
{ {
return injectedHooks; return injectedHooks;
} }
static class HookInfo
{
String fieldName;
String clazz;
Method method;
boolean before;
Number getter;
}
} }

View File

@@ -49,18 +49,16 @@ import org.slf4j.LoggerFactory;
public class InjectHookMethod public class InjectHookMethod
{ {
private static final Logger logger = LoggerFactory.getLogger(InjectHookMethod.class);
public static final String HOOKS = "net/runelite/client/callback/Hooks"; public static final String HOOKS = "net/runelite/client/callback/Hooks";
private static final Logger logger = LoggerFactory.getLogger(InjectHookMethod.class);
private final Inject inject; private final Inject inject;
public InjectHookMethod(Inject inject) InjectHookMethod(Inject inject)
{ {
this.inject = inject; this.inject = inject;
} }
public void process(Method method) throws InjectionException void process(Method method) throws InjectionException
{ {
Annotations an = method.getAnnotations(); Annotations an = method.getAnnotations();
if (an == null) if (an == null)

View File

@@ -51,7 +51,7 @@ import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class InjectInvoker class InjectInvoker
{ {
private static final Logger logger = LoggerFactory.getLogger(InjectInvoker.class); private static final Logger logger = LoggerFactory.getLogger(InjectInvoker.class);
@@ -59,7 +59,7 @@ public class InjectInvoker
private int injectedInvokers; private int injectedInvokers;
public InjectInvoker(Inject inject) InjectInvoker(Inject inject)
{ {
this.inject = inject; this.inject = inject;
} }
@@ -73,7 +73,7 @@ public class InjectInvoker
* @param implementingClass Java class for the API interface the class * @param implementingClass Java class for the API interface the class
* will implement * will implement
*/ */
public void process(Method m, ClassFile other, java.lang.Class<?> implementingClass) void process(Method m, ClassFile other, java.lang.Class<?> implementingClass)
{ {
Annotations an = m.getAnnotations(); Annotations an = m.getAnnotations();
@@ -284,7 +284,7 @@ public class InjectInvoker
clazz.addMethod(invokerMethodSignature); clazz.addMethod(invokerMethodSignature);
} }
public int getInjectedInvokers() int getInjectedInvokers()
{ {
return injectedInvokers; return injectedInvokers;
} }

View File

@@ -45,17 +45,14 @@ import org.apache.maven.plugins.annotations.Parameter;
) )
public class InjectMojo extends AbstractMojo public class InjectMojo extends AbstractMojo
{ {
private final Log log = getLog();
@Parameter(defaultValue = "${project.build.outputDirectory}") @Parameter(defaultValue = "${project.build.outputDirectory}")
private File outputDirectory; private File outputDirectory;
@Parameter(defaultValue = "./runescape-client/target/rs-client-${project.version}.jar", readonly = true, required = true) @Parameter(defaultValue = "./runescape-client/target/rs-client-${project.version}.jar", readonly = true, required = true)
private String rsClientPath; private String rsClientPath;
@Parameter(defaultValue = "${net.runelite.rs:vanilla:jar}", readonly = true, required = true) @Parameter(defaultValue = "${net.runelite.rs:vanilla:jar}", readonly = true, required = true)
private String vanillaPath; private String vanillaPath;
private final Log log = getLog();
@Override @Override
public void execute() throws MojoExecutionException, MojoFailureException public void execute() throws MojoExecutionException, MojoFailureException
{ {

View File

@@ -45,7 +45,7 @@ import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class InjectSetter class InjectSetter
{ {
private static final Logger logger = LoggerFactory.getLogger(InjectSetter.class); private static final Logger logger = LoggerFactory.getLogger(InjectSetter.class);
@@ -53,7 +53,7 @@ public class InjectSetter
private int injectedSetters; private int injectedSetters;
public InjectSetter(Inject inject) InjectSetter(Inject inject)
{ {
this.inject = inject; this.inject = inject;
} }
@@ -67,9 +67,8 @@ public class InjectSetter
* setter declared * setter declared
* @param field Field of vanilla that will be set * @param field Field of vanilla that will be set
* @param exportedName exported name of field * @param exportedName exported name of field
* @param setter
*/ */
public void injectSetter(ClassFile targetClass, Class<?> targetApiClass, Field field, String exportedName, Number setter) void injectSetter(ClassFile targetClass, Class<?> targetApiClass, Field field, String exportedName, Number setter)
{ {
java.lang.reflect.Method method = inject.findImportMethodOnApi(targetApiClass, exportedName, true); java.lang.reflect.Method method = inject.findImportMethodOnApi(targetApiClass, exportedName, true);
if (method == null) if (method == null)
@@ -152,7 +151,7 @@ public class InjectSetter
ins.add(new VReturn(instructions)); ins.add(new VReturn(instructions));
} }
public int getInjectedSetters() int getInjectedSetters()
{ {
return injectedSetters; return injectedSetters;
} }

View File

@@ -0,0 +1,130 @@
package net.runelite.injector;
import net.runelite.asm.ClassFile;
import net.runelite.asm.Field;
import net.runelite.asm.Method;
import net.runelite.asm.signature.Signature;
import net.runelite.deob.DeobAnnotations;
public class InjectUtil
{
public static Method findStaticObMethod(Inject inject, String name) throws InjectionException
{
for (ClassFile c : inject.getVanilla().getClasses())
{
for (Method m : c.getMethods())
{
if (!m.getName().equals(name))
{
continue;
}
return m;
}
}
throw new InjectionException(String.format("Method \"%s\" could not be found.", name));
}
public static Method findMethod(Inject inject, String name) throws InjectionException
{
for (ClassFile c : inject.getDeobfuscated().getClasses())
{
for (Method m : c.getMethods())
{
if (!m.getName().equals(name))
{
continue;
}
String obfuscatedName = DeobAnnotations.getObfuscatedName(m.getAnnotations());
Signature obfuscatedSignature = DeobAnnotations.getObfuscatedSignature(m);
ClassFile c2 = inject.toObClass(c);
return c2.findMethod(obfuscatedName, (obfuscatedSignature != null) ? obfuscatedSignature : m.getDescriptor());
}
}
throw new InjectionException("Couldn't find method " + name);
}
public static Method findStaticMethod(Inject inject, String name) throws InjectionException
{
for (ClassFile c : inject.getDeobfuscated().getClasses())
{
for (Method m : c.getMethods())
{
if (!m.isStatic() || !m.getName().equals(name))
{
continue;
}
String obfuscatedName = DeobAnnotations.getObfuscatedName(m.getAnnotations());
Signature obfuscatedSignature = DeobAnnotations.getObfuscatedSignature(m);
ClassFile c2 = inject.toObClass(c);
return c2.findMethod(obfuscatedName, (obfuscatedSignature != null) ? obfuscatedSignature : m.getDescriptor());
}
}
throw new InjectionException("Couldn't find static method " + name);
}
public static Field findObField(Inject inject, String name) throws InjectionException
{
for (ClassFile c : inject.getVanilla().getClasses())
{
for (Field f : c.getFields())
{
if (!f.getName().equals(name))
{
continue;
}
return f;
}
}
throw new InjectionException(String.format("Field \"%s\" could not be found.", name));
}
public static Field findDeobField(Inject inject, String name) throws InjectionException
{
for (ClassFile c : inject.getDeobfuscated().getClasses())
{
for (Field f : c.getFields())
{
if (!f.getName().equals(name))
{
continue;
}
String obfuscatedName = DeobAnnotations.getObfuscatedName(f.getAnnotations());
ClassFile c2 = inject.toObClass(c);
return c2.findField(obfuscatedName);
}
}
throw new InjectionException(String.format("Mapped field \"%s\" could not be found.", name));
}
public static Field findDeobFieldButUseless(Inject inject, String name) throws InjectionException
{
for (ClassFile c : inject.getDeobfuscated().getClasses())
{
for (Field f : c.getFields())
{
if (!f.getName().equals(name))
{
continue;
}
return f;
}
}
throw new InjectionException(String.format("Mapped field \"%s\" could not be found.", name));
}
}

View File

@@ -39,17 +39,6 @@ public class Injector
this.vanilla = vanilla; this.vanilla = vanilla;
} }
public void inject() throws InjectionException
{
Inject instance = new Inject(deobfuscated, vanilla);
instance.run();
}
public void save(File out) throws IOException
{
JarUtil.saveJar(vanilla, out);
}
public static void main(String[] args) throws IOException, InjectionException public static void main(String[] args) throws IOException, InjectionException
{ {
if (args.length < 3) if (args.length < 3)
@@ -72,5 +61,16 @@ public class Injector
u.save(new File(args[2])); u.save(new File(args[2]));
} }
public void inject() throws InjectionException
{
Inject instance = new Inject(deobfuscated, vanilla);
instance.run();
}
private void save(File out) throws IOException
{
JarUtil.saveJar(vanilla, out);
}
} }

View File

@@ -39,7 +39,7 @@ import org.slf4j.LoggerFactory;
* *
* @author Adam * @author Adam
*/ */
public class InjectorValidator class InjectorValidator
{ {
private static final Logger logger = LoggerFactory.getLogger(InjectorValidator.class); private static final Logger logger = LoggerFactory.getLogger(InjectorValidator.class);
@@ -49,12 +49,12 @@ public class InjectorValidator
private int error, missing, okay; private int error, missing, okay;
public InjectorValidator(ClassGroup group) InjectorValidator(ClassGroup group)
{ {
this.group = group; this.group = group;
} }
public void validate() void validate()
{ {
for (ClassFile cf : group.getClasses()) for (ClassFile cf : group.getClasses())
{ {
@@ -131,17 +131,17 @@ public class InjectorValidator
} }
} }
public int getError() int getError()
{ {
return error; return error;
} }
public int getMissing() int getMissing()
{ {
return missing; return missing;
} }
public int getOkay() int getOkay()
{ {
return okay; return okay;
} }

View File

@@ -87,7 +87,7 @@ public class MixinInjector
// Use net.runelite.asm.pool.Field instead of Field because the pool version has hashcode implemented // Use net.runelite.asm.pool.Field instead of Field because the pool version has hashcode implemented
private final Map<net.runelite.asm.pool.Field, Field> shadowFields = new HashMap<>(); private final Map<net.runelite.asm.pool.Field, Field> shadowFields = new HashMap<>();
public MixinInjector(Inject inject) MixinInjector(Inject inject)
{ {
this.inject = inject; this.inject = inject;
} }
@@ -165,9 +165,6 @@ public class MixinInjector
/** /**
* Finds fields that are marked @Inject and inject them into the target * Finds fields that are marked @Inject and inject them into the target
*
* @param mixinClasses
* @throws InjectionException
*/ */
private void injectFields(Map<Class<?>, List<ClassFile>> mixinClasses) throws InjectionException private void injectFields(Map<Class<?>, List<ClassFile>> mixinClasses) throws InjectionException
{ {
@@ -245,9 +242,6 @@ public class MixinInjector
/** /**
* Find fields which are marked @Shadow, and what they shadow * Find fields which are marked @Shadow, and what they shadow
*
* @param mixinClasses
* @throws InjectionException
*/ */
private void findShadowFields(Map<Class<?>, List<ClassFile>> mixinClasses) throws InjectionException private void findShadowFields(Map<Class<?>, List<ClassFile>> mixinClasses) throws InjectionException
{ {
@@ -287,7 +281,7 @@ public class MixinInjector
else else
{ {
// Shadow a field already in the gamepack // Shadow a field already in the gamepack
Field shadowField = findDeobField(shadowName); Field shadowField = InjectUtil.findDeobFieldButUseless(inject, shadowName);
if (shadowField == null) if (shadowField == null)
{ {
@@ -316,21 +310,6 @@ public class MixinInjector
} }
} }
private Field findDeobField(String name)
{
for (ClassFile cf : inject.getDeobfuscated().getClasses())
{
for (Field f : cf.getFields())
{
if (f.getName().equals(name) && f.isStatic())
{
return f;
}
}
}
return null;
}
private void injectMethods(ClassFile mixinCf, ClassFile cf, Map<net.runelite.asm.pool.Field, Field> shadowFields) private void injectMethods(ClassFile mixinCf, ClassFile cf, Map<net.runelite.asm.pool.Field, Field> shadowFields)
throws InjectionException throws InjectionException
{ {
@@ -901,7 +880,7 @@ public class MixinInjector
if (targetField == null) if (targetField == null)
{ {
// first try non static fields, then static // first try non static fields, then static
targetField = findDeobField(hookName); targetField = InjectUtil.findDeobFieldButUseless(inject, hookName);
} }
if (targetField == null) if (targetField == null)
@@ -909,6 +888,13 @@ public class MixinInjector
throw new InjectionException("Field hook for nonexistent field " + hookName + " on " + method); throw new InjectionException("Field hook for nonexistent field " + hookName + " on " + method);
} }
Annotation an = targetField.getAnnotations().find(DeobAnnotations.OBFUSCATED_GETTER);
Number getter = null;
if (an != null)
{
getter = (Number) an.getElement().getValue();
}
Field obField = inject.toObField(targetField); Field obField = inject.toObField(targetField);
if (method.isStatic() != targetField.isStatic()) if (method.isStatic() != targetField.isStatic())
@@ -922,6 +908,7 @@ public class MixinInjector
hookInfo.fieldName = hookName; hookInfo.fieldName = hookName;
hookInfo.method = method; hookInfo.method = method;
hookInfo.before = before; hookInfo.before = before;
hookInfo.getter = getter;
injectHook.hook(obField, hookInfo); injectHook.hook(obField, hookInfo);
} }
} }

View File

@@ -11,8 +11,8 @@ import net.runelite.asm.attributes.code.instructions.InvokeStatic;
import net.runelite.asm.attributes.code.instructions.LDC; import net.runelite.asm.attributes.code.instructions.LDC;
import net.runelite.asm.pool.Class; import net.runelite.asm.pool.Class;
import net.runelite.asm.signature.Signature; import net.runelite.asm.signature.Signature;
import net.runelite.deob.DeobAnnotations;
import net.runelite.injector.Inject; import net.runelite.injector.Inject;
import net.runelite.injector.InjectUtil;
import net.runelite.injector.InjectionException; import net.runelite.injector.InjectionException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -39,7 +39,7 @@ public class ClearColorBuffer
private void injectColorBufferHooks() throws InjectionException private void injectColorBufferHooks() throws InjectionException
{ {
net.runelite.asm.pool.Method fillRectangle = findStaticMethod("Rasterizer2D_fillRectangle").getPoolMethod(); net.runelite.asm.pool.Method fillRectangle = InjectUtil.findStaticMethod(inject, "Rasterizer2D_fillRectangle").getPoolMethod();
int count = 0; int count = 0;
int replaced = 0; int replaced = 0;
@@ -119,28 +119,4 @@ public class ClearColorBuffer
} }
} }
} }
private Method findStaticMethod(String name) throws InjectionException
{
for (ClassFile c : inject.getDeobfuscated().getClasses())
{
for (Method m : c.getMethods())
{
if (!m.getName().equals(name))
{
continue;
}
String obfuscatedName = DeobAnnotations.getObfuscatedName(m.getAnnotations());
Signature obfuscatedSignature = DeobAnnotations.getObfuscatedSignature(m);
ClassFile c2 = inject.toObClass(c);
return c2.findMethod(obfuscatedName, (obfuscatedSignature != null) ? obfuscatedSignature : m.getDescriptor());
}
}
throw new InjectionException("Couldn't find static method " + name);
}
} }

View File

@@ -38,9 +38,9 @@ import net.runelite.asm.attributes.code.instructions.GetStatic;
import net.runelite.asm.attributes.code.instructions.IMul; import net.runelite.asm.attributes.code.instructions.IMul;
import net.runelite.asm.attributes.code.instructions.InvokeStatic; import net.runelite.asm.attributes.code.instructions.InvokeStatic;
import net.runelite.asm.signature.Signature; import net.runelite.asm.signature.Signature;
import net.runelite.deob.DeobAnnotations;
import net.runelite.injector.Inject; import net.runelite.injector.Inject;
import static net.runelite.injector.InjectHookMethod.HOOKS; import static net.runelite.injector.InjectHookMethod.HOOKS;
import static net.runelite.injector.InjectUtil.findStaticMethod;
import net.runelite.injector.InjectionException; import net.runelite.injector.InjectionException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -107,7 +107,7 @@ public class DrawAfterWidgets
boolean injected = false; boolean injected = false;
Method noClip = findStaticMethod("Rasterizer2D_resetClip"); // !!!!! Method noClip = findStaticMethod(inject, "Rasterizer2D_resetClip"); // !!!!!
if (noClip == null) if (noClip == null)
{ {
@@ -261,27 +261,4 @@ public class DrawAfterWidgets
throw new InjectionException("injectDrawAfterWidgets failed to inject!"); throw new InjectionException("injectDrawAfterWidgets failed to inject!");
} }
} }
private Method findStaticMethod(String name)
{
for (ClassFile c : inject.getDeobfuscated().getClasses())
{
for (Method m : c.getMethods())
{
if (!m.getName().equals(name))
{
continue;
}
String obfuscatedName = DeobAnnotations.getObfuscatedName(m.getAnnotations());
Signature obfuscatedSignature = DeobAnnotations.getObfuscatedSignature(m);
ClassFile c2 = inject.toObClass(c);
return c2.findMethod(obfuscatedName, (obfuscatedSignature != null) ? obfuscatedSignature : m.getDescriptor());
}
}
return null;
}
} }

View File

@@ -1,50 +1,50 @@
/*
package net.runelite.injector.raw; package net.runelite.injector.raw;
import com.google.common.base.Strings; import java.util.ListIterator;
import java.util.HashSet;
import java.util.Set;
import net.runelite.asm.ClassFile; import net.runelite.asm.ClassFile;
import net.runelite.asm.Method; import net.runelite.asm.Method;
import net.runelite.asm.Type;
import net.runelite.asm.attributes.Annotations;
import net.runelite.asm.attributes.Code; import net.runelite.asm.attributes.Code;
import net.runelite.asm.attributes.annotation.Annotation;
import net.runelite.asm.attributes.code.Instruction; import net.runelite.asm.attributes.code.Instruction;
import net.runelite.asm.attributes.code.Instructions; import net.runelite.asm.attributes.code.Instructions;
import net.runelite.asm.attributes.code.Label; import net.runelite.asm.attributes.code.Label;
import net.runelite.asm.attributes.code.instruction.types.ComparisonInstruction;
import net.runelite.asm.attributes.code.instruction.types.JumpingInstruction; import net.runelite.asm.attributes.code.instruction.types.JumpingInstruction;
import net.runelite.asm.attributes.code.instruction.types.ReturnInstruction;
import net.runelite.asm.attributes.code.instructions.GetStatic; import net.runelite.asm.attributes.code.instructions.GetStatic;
import net.runelite.asm.attributes.code.instructions.IfACmpEq;
import net.runelite.asm.attributes.code.instructions.IfACmpNe;
import net.runelite.asm.attributes.code.instructions.IfEq; import net.runelite.asm.attributes.code.instructions.IfEq;
import net.runelite.asm.attributes.code.instructions.IfNe; import net.runelite.asm.attributes.code.instructions.IfNe;
import net.runelite.asm.attributes.code.instructions.InvokeStatic; import net.runelite.asm.attributes.code.instructions.InvokeStatic;
import net.runelite.asm.execution.Execution;
import net.runelite.asm.execution.InstructionContext;
import net.runelite.asm.pool.Class; import net.runelite.asm.pool.Class;
import net.runelite.asm.pool.Field; import net.runelite.asm.pool.Field;
import net.runelite.asm.signature.Signature; import net.runelite.asm.signature.Signature;
import net.runelite.deob.DeobAnnotations;
import net.runelite.injector.Inject; import net.runelite.injector.Inject;
import static net.runelite.injector.InjectUtil.findDeobField;
import static net.runelite.injector.InjectUtil.findStaticMethod;
import net.runelite.injector.InjectionException; import net.runelite.injector.InjectionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class DrawMenu public class DrawMenu
{ {
private final Logger log = LoggerFactory.getLogger(DrawMenu.class);
private final Inject inject; private final Inject inject;
private static final Field isMenuOpen = new Field(
new Class("Client"),
"isMenuOpen",
Type.BOOLEAN
);
private static final net.runelite.asm.pool.Method hook = new net.runelite.asm.pool.Method( private static final net.runelite.asm.pool.Method hook = new net.runelite.asm.pool.Method(
new Class("net.runelite.client.callback.Hooks"), new Class("net.runelite.client.callback.Hooks"),
"drawMenu", "drawMenu",
new Signature("()Z") new Signature("()Z")
); );
//Label Getstatic client.isMenuOpen
//Ifne -> Label Drawmenu
//Jump -> Label Drawtext
//Label drawtext
//Ldc xxx
//Getstatic client. something with viewport size?
//Imul
//Iconst_m1
//Ifne -> Label after draw menu <- info we need
//Getstatic / LDC (same getstatic and LDC before)
//Getstatic / LDC
public DrawMenu(Inject inject) public DrawMenu(Inject inject)
{ {
this.inject = inject; this.inject = inject;
@@ -52,142 +52,84 @@ public class DrawMenu
public void inject() throws InjectionException public void inject() throws InjectionException
{ {
Method drawLoggedIn = findDeobThing("drawLoggedIn", "Client", false); Field isMenuOpen = findDeobField(inject, "isMenuOpen").getPoolField();
Instructions ins = drawLoggedIn.getCode().getInstructions(); net.runelite.asm.pool.Method topLeftText = findStaticMethod(inject, "drawMenuActionTextAt").getPoolMethod();
int menuOpenIdx = -1; for (ClassFile cf : inject.getVanilla().getClasses())
Field field = toObField(isMenuOpen).getPoolField();
for (Instruction i : ins.getInstructions())
{
if (!(i instanceof GetStatic))
{
continue;
}
if (((GetStatic) i).getField().equals(field))
{
menuOpenIdx = ins.getInstructions().indexOf(i);
}
}
if (menuOpenIdx == -1)
{
throw new InjectionException("Couldn't find the isMenuOpen check!");
}
// This is where the IFEQ or IFNE will be
final Instruction jump = ins.getInstructions().get(menuOpenIdx + 1);
// We want to inject if it's false so
if (jump instanceof IfEq)
{
// Not this one, but we gotta find out where the paths will intersect
Set<Label> labels = getLabels(jump);
}
}
private Set<Label> getLabels(Instruction i)
{
Set<Label> labels = new HashSet<>();
Execution ex = new Execution(inject.getVanilla());
ex.addMethod(i.getInstructions().getCode().getMethod());
ex.noInvoke = true;
ex.addExecutionVisitor((InstructionContext ic) ->
{
Instruction in = ic.getInstruction();
Instructions ins = in.getInstructions();
Code code = ins.getCode();
Method method = code.getMethod();
//ic.
});
}
private Set<Label> findLabels(Instructions ins, int idx)
{
Set<Label> labels = new HashSet<>();
Instruction i = null;
while (labels.size() < 10 || !(i instanceof ReturnInstruction))
{
i = ins.getInstructions().get(idx);
if (i instanceof JumpingInstruction)
{
Label cur = ((JumpingInstruction) i).getJumps().get(0);
labels.add((Label) cur);
idx = ins.getInstructions().indexOf(cur) + 1;
}
}
return labels;
}
private Method findDeobThing(String name, String hint, boolean isStatic) throws InjectionException
{
if (!Strings.isNullOrEmpty(hint))
{
ClassFile hintCf = inject.getDeobfuscated().findClass(hint);
if (hintCf != null)
{
for (Method m : hintCf.getMethods())
{
if (isStatic != m.isStatic())
{
continue;
}
if (!m.getName().equals(name))
{
continue;
}
Annotations an = m.getAnnotations();
if (an == null || an.find(DeobAnnotations.EXPORT) == null)
{
continue; // not an exported field
}
String obfuscatedName = DeobAnnotations.getObfuscatedName(an);
return inject.toObClass(hintCf).findMethod(obfuscatedName);
}
}
}
for (ClassFile cf : inject.getDeobfuscated().getClasses())
{ {
for (Method m : cf.getMethods()) for (Method m : cf.getMethods())
{ {
if (isStatic != m.isStatic()) Code c = m.getCode();
if (c == null)
{ {
continue; continue;
} }
Annotations an = m.getAnnotations(); Instructions ins = c.getInstructions();
if (an == null || an.find(DeobAnnotations.EXPORT) == null) ListIterator<Instruction> it = ins.getInstructions().listIterator();
int injectIndex = -1;
Label after = null;
boolean foundBefore = false;
boolean foundAfter = false;
while (it.hasNext())
{ {
continue; // not an exported field Instruction i = it.next();
if (!(i instanceof GetStatic) && !(i instanceof InvokeStatic))
{
continue;
} }
String obfuscatedName = DeobAnnotations.getObfuscatedName(an); if (!foundBefore && i instanceof GetStatic)
return inject.toObClass(cf).findMethod(obfuscatedName); {
if (!((GetStatic) i).getField().equals(isMenuOpen))
{
continue;
}
i = it.next();
if (!(i instanceof IfEq) && !(i instanceof IfNe))
{
continue;
}
if (i instanceof IfEq)
{
injectIndex = it.nextIndex();
}
else
{
injectIndex = ins.getInstructions().indexOf(((IfNe) i).getJumps().get(0)) + 1;
}
foundBefore = true;
}
else if (!foundAfter && i instanceof InvokeStatic
&& ((InvokeStatic) i).getMethod().equals(topLeftText))
{
i = it.next();
assert i instanceof JumpingInstruction;
after = ((JumpingInstruction) i).getJumps().get(0);
foundAfter = true;
}
if (foundBefore && foundAfter)
{
break;
} }
} }
throw new InjectionException("Method not found!"); if (!foundBefore || !foundAfter || injectIndex == -1)
{
continue;
} }
private net.runelite.asm.Field toObField(Field field) throws InjectionException ins.addInstruction(injectIndex, new IfNe(ins, after));
{ ins.addInstruction(injectIndex, new InvokeStatic(ins, hook));
ClassFile cf = inject.getDeobfuscated().findClass(field.getClazz().getName()); log.info("Injected drawmenu hook in {} at index {}", m, injectIndex);
for (net.runelite.asm.Field f : cf.getFields()) return;
{
if (f.getPoolField().equals(field))
{
return inject.toObField(f);
} }
} }
throw new InjectionException("Field not found!");
} }
} }
*/

View File

@@ -4,7 +4,6 @@ import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import net.runelite.asm.ClassFile;
import net.runelite.asm.Field; import net.runelite.asm.Field;
import net.runelite.asm.Method; import net.runelite.asm.Method;
import net.runelite.asm.attributes.Code; import net.runelite.asm.attributes.Code;
@@ -27,8 +26,9 @@ import net.runelite.asm.execution.Execution;
import net.runelite.asm.execution.InstructionContext; import net.runelite.asm.execution.InstructionContext;
import net.runelite.asm.pool.Class; import net.runelite.asm.pool.Class;
import net.runelite.asm.signature.Signature; import net.runelite.asm.signature.Signature;
import net.runelite.deob.DeobAnnotations;
import net.runelite.injector.Inject; import net.runelite.injector.Inject;
import static net.runelite.injector.InjectUtil.findDeobField;
import static net.runelite.injector.InjectUtil.findStaticMethod;
import net.runelite.injector.InjectionException; import net.runelite.injector.InjectionException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -101,8 +101,8 @@ public class RasterizerHook
private void runR3DAlpha(String methodName, int req, String fieldName) throws InjectionException private void runR3DAlpha(String methodName, int req, String fieldName) throws InjectionException
{ {
Method meth = findStaticMethod(methodName); Method meth = findStaticMethod(inject, methodName);
Field field = findDeobField(fieldName); Field field = findDeobField(inject, fieldName);
Instructions ins = meth.getCode().getInstructions(); Instructions ins = meth.getCode().getInstructions();
int varIdx = 0; // This is obviously dumb but I cba making this better int varIdx = 0; // This is obviously dumb but I cba making this better
int added = 0; int added = 0;
@@ -118,8 +118,6 @@ public class RasterizerHook
throw new InjectionException("Couldn't find hook location in " + methodName); throw new InjectionException("Couldn't find hook location in " + methodName);
} }
int oldCount = count;
for (int i : indices) for (int i : indices)
{ {
for (int codeIndex = i + added; codeIndex < ins.getInstructions().size(); codeIndex++) for (int codeIndex = i + added; codeIndex < ins.getInstructions().size(); codeIndex++)
@@ -146,8 +144,8 @@ public class RasterizerHook
private void runAlpha(String methodName, int req, int extraArg, int varIndex) throws InjectionException private void runAlpha(String methodName, int req, int extraArg, int varIndex) throws InjectionException
{ {
final net.runelite.asm.pool.Field pixels = findDeobField("Rasterizer2D_pixels").getPoolField(); final net.runelite.asm.pool.Field pixels = findDeobField(inject, "Rasterizer2D_pixels").getPoolField();
Method meth = findStaticMethod(methodName); Method meth = findStaticMethod(inject, methodName);
if (meth == null) if (meth == null)
{ {
throw new InjectionException(methodName + " couldnt be found"); throw new InjectionException(methodName + " couldnt be found");
@@ -215,8 +213,7 @@ public class RasterizerHook
private void runFontAlpha(String methodName, int req, int extraArg) throws InjectionException private void runFontAlpha(String methodName, int req, int extraArg) throws InjectionException
{ {
final net.runelite.asm.pool.Field pixels = findDeobField("Rasterizer2D_pixels").getPoolField(); Method meth = findStaticMethod(inject, methodName);
Method meth = findStaticMethod(methodName);
Instructions ins = meth.getCode().getInstructions(); Instructions ins = meth.getCode().getInstructions();
int varIdx = 0; // This is obviously dumb but I cba making this better int varIdx = 0; // This is obviously dumb but I cba making this better
int added = 0; int added = 0;
@@ -252,13 +249,9 @@ public class RasterizerHook
} }
} }
if (count - oldCount > req) if (count - req != oldCount)
{ {
throw new InjectionException("Too many drawAlpha's were injected into " + methodName); throw new InjectionException(req != oldCount ? req > count - oldCount ? "Not enough" : "Too many" : "No" + " drawAlpha's were injected into " + methodName);
}
if (count == oldCount)
{
throw new InjectionException("Couldn't find any drawAlpha positions in " + methodName);
} }
} }
@@ -282,7 +275,7 @@ public class RasterizerHook
private void run() throws InjectionException private void run() throws InjectionException
{ {
final int startCount = count; // Cause you can't just count shit ty final int startCount = count; // Cause you can't just count shit ty
final net.runelite.asm.pool.Field pixels = findDeobField("Rasterizer2D_pixels").getPoolField(); final net.runelite.asm.pool.Field pixels = findDeobField(inject, "Rasterizer2D_pixels").getPoolField();
Execution ex = new Execution(inject.getVanilla()); Execution ex = new Execution(inject.getVanilla());
ex.populateInitialMethods(); ex.populateInitialMethods();
@@ -341,7 +334,7 @@ public class RasterizerHook
private void runOnMethodWithVar(String meth, int varIndex) throws InjectionException private void runOnMethodWithVar(String meth, int varIndex) throws InjectionException
{ {
Method method = findStaticMethod(meth); Method method = findStaticMethod(inject, meth);
Instructions ins = method.getCode().getInstructions(); Instructions ins = method.getCode().getInstructions();
List<Integer> indices = new ArrayList<>(); List<Integer> indices = new ArrayList<>();
@@ -374,48 +367,4 @@ public class RasterizerHook
logger.info("Added {} instructions in {}. {} total", added >>> 1, meth, count); logger.info("Added {} instructions in {}. {} total", added >>> 1, meth, count);
} }
private Method findStaticMethod(String name) throws InjectionException
{
for (ClassFile c : inject.getDeobfuscated().getClasses())
{
for (Method m : c.getMethods())
{
if (!m.getName().equals(name))
{
continue;
}
String obfuscatedName = DeobAnnotations.getObfuscatedName(m.getAnnotations());
Signature obfuscatedSignature = DeobAnnotations.getObfuscatedSignature(m);
ClassFile c2 = inject.toObClass(c);
return c2.findMethod(obfuscatedName, (obfuscatedSignature != null) ? obfuscatedSignature : m.getDescriptor());
}
}
throw new InjectionException("Couldn't find static method " + name);
}
private Field findDeobField(String name) throws InjectionException
{
for (ClassFile c : inject.getDeobfuscated().getClasses())
{
for (Field f : c.getFields())
{
if (!f.getName().equals(name))
{
continue;
}
String obfuscatedName = DeobAnnotations.getObfuscatedName(f.getAnnotations());
ClassFile c2 = inject.toObClass(c);
return c2.findField(obfuscatedName);
}
}
throw new InjectionException(String.format("Mapped field \"%s\" could not be found.", name));
}
} }

View File

@@ -2,7 +2,6 @@ package net.runelite.injector.raw;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import net.runelite.asm.ClassFile;
import net.runelite.asm.attributes.code.Instruction; import net.runelite.asm.attributes.code.Instruction;
import net.runelite.asm.attributes.code.Instructions; import net.runelite.asm.attributes.code.Instructions;
import net.runelite.asm.attributes.code.instructions.InvokeStatic; import net.runelite.asm.attributes.code.instructions.InvokeStatic;
@@ -10,8 +9,8 @@ import net.runelite.asm.attributes.code.instructions.InvokeVirtual;
import net.runelite.asm.pool.Class; import net.runelite.asm.pool.Class;
import net.runelite.asm.pool.Method; import net.runelite.asm.pool.Method;
import net.runelite.asm.signature.Signature; import net.runelite.asm.signature.Signature;
import net.runelite.deob.DeobAnnotations;
import net.runelite.injector.Inject; import net.runelite.injector.Inject;
import static net.runelite.injector.InjectUtil.findMethod;
import net.runelite.injector.InjectionException; import net.runelite.injector.InjectionException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -38,8 +37,8 @@ public class RenderDraw
private void injectColorBufferHooks() throws InjectionException private void injectColorBufferHooks() throws InjectionException
{ {
net.runelite.asm.Method obmethod = findObMethod("drawTile"); net.runelite.asm.Method obmethod = findMethod(inject, "drawTile");
Method renderDraw = findObMethod("renderDraw").getPoolMethod(); Method renderDraw = findMethod(inject, "renderDraw").getPoolMethod();
Instructions ins = obmethod.getCode().getInstructions(); Instructions ins = obmethod.getCode().getInstructions();
replace(ins, renderDraw); replace(ins, renderDraw);
} }
@@ -69,24 +68,4 @@ public class RenderDraw
ins.replace(i, invoke); ins.replace(i, invoke);
} }
} }
private net.runelite.asm.Method findObMethod(String name) throws InjectionException
{
for (ClassFile cf : inject.getDeobfuscated().getClasses())
{
for (net.runelite.asm.Method m : cf.getMethods())
{
if (!m.getName().equals(name))
{
continue;
}
String obfuscatedName = DeobAnnotations.getObfuscatedName(m.getAnnotations());
ClassFile c2 = inject.toObClass(cf);
return c2.findMethod(obfuscatedName);
}
}
throw new InjectionException(String.format("Method \"%s\" could not be found.", name));
}
} }

View File

@@ -28,7 +28,6 @@ import java.util.HashSet;
import java.util.ListIterator; import java.util.ListIterator;
import java.util.Set; import java.util.Set;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import net.runelite.asm.ClassFile;
import net.runelite.asm.Field; import net.runelite.asm.Field;
import net.runelite.asm.Method; import net.runelite.asm.Method;
import net.runelite.asm.Type; import net.runelite.asm.Type;
@@ -54,6 +53,9 @@ import net.runelite.asm.execution.MethodContext;
import net.runelite.asm.execution.StackContext; import net.runelite.asm.execution.StackContext;
import net.runelite.deob.DeobAnnotations; import net.runelite.deob.DeobAnnotations;
import net.runelite.injector.Inject; import net.runelite.injector.Inject;
import net.runelite.injector.InjectUtil;
import static net.runelite.injector.InjectUtil.findDeobField;
import static net.runelite.injector.InjectUtil.findObField;
import net.runelite.injector.InjectionException; import net.runelite.injector.InjectionException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -104,12 +106,12 @@ public class ScriptVM
*/ */
String scriptObName = DeobAnnotations.getObfuscatedName(inject.getDeobfuscated().findClass("Script").getAnnotations()); String scriptObName = DeobAnnotations.getObfuscatedName(inject.getDeobfuscated().findClass("Script").getAnnotations());
Method runScript = findObMethod("copy$runScript0"); Method runScript = InjectUtil.findStaticObMethod(inject, "copy$runScript0");
Method vmExecuteOpcode = findObMethod("vmExecuteOpcode"); Method vmExecuteOpcode = InjectUtil.findStaticObMethod(inject, "vmExecuteOpcode");
Field scriptInstructions = findDeobField("opcodes"); Field scriptInstructions = findDeobField(inject, "opcodes");
Field scriptStatePC = findDeobField("pc"); Field scriptStatePC = findDeobField(inject, "pc");
Field currentScriptField = findObField("currentScript"); Field currentScriptField = findObField(inject, "currentScript");
Field currentScriptPCField = findObField("currentScriptPC"); Field currentScriptPCField = findObField(inject, "currentScriptPC");
Execution e = new Execution(inject.getVanilla()); Execution e = new Execution(inject.getVanilla());
e.addMethod(runScript); e.addMethod(runScript);
@@ -295,59 +297,4 @@ public class ScriptVM
instrs.addInstruction(istorepc + 2, new InvokeStatic(instrs, vmExecuteOpcode.getPoolMethod())); instrs.addInstruction(istorepc + 2, new InvokeStatic(instrs, vmExecuteOpcode.getPoolMethod()));
instrs.addInstruction(istorepc + 3, new IfNe(instrs, nextIteration)); instrs.addInstruction(istorepc + 3, new IfNe(instrs, nextIteration));
} }
private Method findObMethod(String name) throws InjectionException
{
for (ClassFile c : inject.getVanilla().getClasses())
{
for (Method m : c.getMethods())
{
if (!m.getName().equals(name))
{
continue;
}
return m;
}
}
throw new InjectionException(String.format("Method \"%s\" could not be found.", name));
}
private Field findObField(String name) throws InjectionException
{
for (ClassFile c : inject.getVanilla().getClasses())
{
for (Field f : c.getFields())
{
if (!f.getName().equals(name))
{
continue;
}
return f;
}
}
throw new InjectionException(String.format("Field \"%s\" could not be found.", name));
}
private Field findDeobField(String name) throws InjectionException
{
for (ClassFile c : inject.getDeobfuscated().getClasses())
{
for (Field f : c.getFields())
{
if (!f.getName().equals(name))
{
continue;
}
String obfuscatedName = DeobAnnotations.getObfuscatedName(f.getAnnotations());
ClassFile c2 = inject.toObClass(c);
return c2.findField(obfuscatedName);
}
}
throw new InjectionException(String.format("Mapped field \"%s\" could not be found.", name));
}
} }

View File

@@ -35,11 +35,6 @@ import static org.mockito.Mockito.when;
public class InjectConstructTest public class InjectConstructTest
{ {
interface APIClass
{
APIClass create();
}
@Test @Test
public void testInjectConstruct() throws Exception public void testInjectConstruct() throws Exception
{ {
@@ -60,4 +55,9 @@ public class InjectConstructTest
assertNotNull(targetClass.findMethod("create")); assertNotNull(targetClass.findMethod("create"));
} }
interface APIClass
{
APIClass create();
}
} }

View File

@@ -44,13 +44,6 @@ import static org.mockito.Mockito.when;
public class InjectSetterTest public class InjectSetterTest
{ {
interface APIClass
{
void setTest(int i);
void setTestObject(Object str);
}
@Test @Test
public void testInjectSetterInt() throws NoSuchMethodException public void testInjectSetterInt() throws NoSuchMethodException
{ {
@@ -113,4 +106,11 @@ public class InjectSetterTest
.isPresent()); .isPresent());
} }
interface APIClass
{
void setTest(int i);
void setTestObject(Object str);
}
} }

View File

@@ -53,6 +53,9 @@ import static org.objectweb.asm.Opcodes.ACC_STATIC;
@ObfuscatedName("net/runelite/injector/VanillaTarget") @ObfuscatedName("net/runelite/injector/VanillaTarget")
class DeobTarget class DeobTarget
{ {
@ObfuscatedName("ob_foo4")
private static int foo4;
@ObfuscatedName("ob_foo3") @ObfuscatedName("ob_foo3")
@ObfuscatedSignature( @ObfuscatedSignature(
signature = "(I)V", signature = "(I)V",
@@ -63,13 +66,12 @@ class DeobTarget
// De-obfuscated foo3 // De-obfuscated foo3
System.out.println("foo3"); System.out.println("foo3");
} }
@ObfuscatedName("ob_foo4")
private static int foo4;
} }
class VanillaTarget class VanillaTarget
{ {
private static int ob_foo4;
private void ob_foo3(int garbageValue) private void ob_foo3(int garbageValue)
{ {
// Obfuscated foo3 // Obfuscated foo3
@@ -79,14 +81,14 @@ class VanillaTarget
} }
System.out.println("foo3"); System.out.println("foo3");
} }
private static int ob_foo4;
} }
abstract class Source abstract class Source
{ {
@net.runelite.api.mixins.Inject @net.runelite.api.mixins.Inject
private static int foo; private static int foo;
@Shadow("foo4")
private static int foo4;
@net.runelite.api.mixins.Inject @net.runelite.api.mixins.Inject
private void foo2() private void foo2()
@@ -103,9 +105,6 @@ abstract class Source
System.out.println(foo4); System.out.println(foo4);
foo3(); foo3();
} }
@Shadow("foo4")
private static int foo4;
} }
// Test shadowing the "foo" field injected by Source // Test shadowing the "foo" field injected by Source

View File

@@ -173,7 +173,7 @@ public final class AnimationID
public static final int VORKATH_DEATH = 7949; public static final int VORKATH_DEATH = 7949;
public static final int VORKATH_SLASH_ATTACK = 7951; public static final int VORKATH_SLASH_ATTACK = 7951;
public static final int VORKATH_ATTACK = 7952; public static final int VORKATH_ATTACK = 7952;
public static final int VORKATH_FIRE_BOMB_ATTACK = 7960; public static final int VORKATH_FIRE_BOMB_OR_SPAWN_ATTACK = 7960;
public static final int VORKATH_ACID_ATTACK = 7957; public static final int VORKATH_ACID_ATTACK = 7957;
public static final int BLACKJACK_KO = 838; public static final int BLACKJACK_KO = 838;
public static final int VETION_EARTHQUAKE = 5507; public static final int VETION_EARTHQUAKE = 5507;
@@ -251,4 +251,21 @@ public final class AnimationID
public static final int HYDRA_RANGED_4 = 8255; public static final int HYDRA_RANGED_4 = 8255;
public static final int HYDRA_4_1 = 8257; public static final int HYDRA_4_1 = 8257;
public static final int HYDRA_4_2 = 8258; public static final int HYDRA_4_2 = 8258;
// INFERNO animations
public static final int JAL_NIB = 7574;
public static final int JAL_MEJRAH = 7578;
public static final int JAL_AK_RANGE_ATTACK = 7581;
public static final int JAL_AK_MELEE_ATTACK = 7582;
public static final int JAL_AK_MAGIC_ATTACK = 7583;
public static final int JAL_IMKOT = 7597;
public static final int JAL_XIL_MELEE_ATTACK = 7604;
public static final int JAL_XIL_RANGE_ATTACK = 7605;
public static final int JAL_ZEK_MAGE_ATTACK = 7610;
public static final int JAL_ZEK_MELEE_ATTACK = 7612;
public static final int JALTOK_JAD_MELEE_ATTACK = 7590;
public static final int JALTOK_JAD_MAGE_ATTACK = 7592;
public static final int JALTOK_JAD_RANGE_ATTACK = 7593;
public static final int TZKAL_ZUK = 7566;
public static final int JAL_MEJJAK = 2858;
} }

View File

@@ -1653,4 +1653,7 @@ public interface Client extends GameShell
void setPrintMenuActions(boolean b); void setPrintMenuActions(boolean b);
String getSelectedSpellName();
boolean getIsSpellSelected();
} }

View File

@@ -93,7 +93,7 @@ public class ProjectileID
public static final int VORKATH_MAGIC = 1479; public static final int VORKATH_MAGIC = 1479;
public static final int VORKATH_PRAYER_DISABLE = 1471; public static final int VORKATH_PRAYER_DISABLE = 1471;
public static final int VORKATH_VENOM = 1470; public static final int VORKATH_VENOM = 1470;
public static final int VORKATH_ICE = 350; public static final int VORKATH_ICE = 395;
public static final int HYDRA_MAGIC = 1662; public static final int HYDRA_MAGIC = 1662;
public static final int HYDRA_RANGED = 1663; public static final int HYDRA_RANGED = 1663;

View File

@@ -83,7 +83,7 @@ import org.slf4j.LoggerFactory;
@Slf4j @Slf4j
public class RuneLite public class RuneLite
{ {
public static final String RUNELIT_VERSION = "0.1.2"; public static final String RUNELIT_VERSION = "2.0.0";
public static final File RUNELITE_DIR = new File(System.getProperty("user.home"), ".runelite"); public static final File RUNELITE_DIR = new File(System.getProperty("user.home"), ".runelite");
public static final File PROFILES_DIR = new File(RUNELITE_DIR, "profiles"); public static final File PROFILES_DIR = new File(RUNELITE_DIR, "profiles");
public static final File PLUGIN_DIR = new File(RUNELITE_DIR, "plugins"); public static final File PLUGIN_DIR = new File(RUNELITE_DIR, "plugins");
@@ -243,7 +243,7 @@ public class RuneLite
System.exit(0); System.exit(0);
} }
final boolean developerMode = true; final boolean developerMode = options.has("developer-mode");
if (developerMode) if (developerMode)
{ {
@@ -290,7 +290,7 @@ public class RuneLite
injector = Guice.createInjector(new RuneLiteModule( injector = Guice.createInjector(new RuneLiteModule(
options.valueOf(updateMode), options.valueOf(updateMode),
developerMode)); true));
injector.getInstance(RuneLite.class).start(); injector.getInstance(RuneLite.class).start();
splashScreen.setProgress(1, 5); splashScreen.setProgress(1, 5);

View File

@@ -94,7 +94,7 @@ public class SessionManager
// Check if session is still valid // Check if session is still valid
AccountClient accountClient = new AccountClient(session.getUuid()); AccountClient accountClient = new AccountClient(session.getUuid());
if (!accountClient.sesssionCheck()) if (!accountClient.sessionCheck())
{ {
log.debug("Loaded session {} is invalid", session.getUuid()); log.debug("Loaded session {} is invalid", session.getUuid());
return; return;

View File

@@ -29,7 +29,6 @@ import com.google.common.base.Preconditions;
import com.google.common.collect.HashMultimap; import com.google.common.collect.HashMultimap;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
@@ -93,6 +92,7 @@ public class MenuManager
private final Set<ComparableEntry> priorityEntries = new HashSet<>(); private final Set<ComparableEntry> priorityEntries = new HashSet<>();
private final Set<MenuEntry> currentPriorityEntries = new HashSet<>(); private final Set<MenuEntry> currentPriorityEntries = new HashSet<>();
private final Set<ComparableEntry> hiddenEntries = new HashSet<>();
private final Map<ComparableEntry, ComparableEntry> swaps = new HashMap<>(); private final Map<ComparableEntry, ComparableEntry> swaps = new HashMap<>();
private final Set<MenuEntry> originalTypes = new HashSet<>(); private final Set<MenuEntry> originalTypes = new HashSet<>();
@@ -192,7 +192,7 @@ public class MenuManager
} }
// Make a copy of the menu entries, cause you can't remove from Arrays.asList() // Make a copy of the menu entries, cause you can't remove from Arrays.asList()
List<MenuEntry> copy = new ArrayList<>(Arrays.asList(menuEntries)); List<MenuEntry> copy = Lists.newArrayList(menuEntries);
// If there are entries we want to prioritize, we have to remove the rest // If there are entries we want to prioritize, we have to remove the rest
if (!currentPriorityEntries.isEmpty()) if (!currentPriorityEntries.isEmpty())
@@ -253,6 +253,21 @@ public class MenuManager
} }
} }
boolean isHidden = false;
for (ComparableEntry p : hiddenEntries)
{
if (p.matches(newestEntry))
{
isHidden = true;
break;
}
}
if (isHidden)
{
copy.remove(newestEntry);
}
client.setMenuEntries(copy.toArray(new MenuEntry[0])); client.setMenuEntries(copy.toArray(new MenuEntry[0]));
} }
@@ -599,19 +614,7 @@ public class MenuManager
ComparableEntry entry = new ComparableEntry(option, target); ComparableEntry entry = new ComparableEntry(option, target);
Set<ComparableEntry> toRemove = new HashSet<>(); priorityEntries.removeIf(entry::equals);
for (ComparableEntry priorityEntry : priorityEntries)
{
if (entry.equals(priorityEntry))
{
toRemove.add(entry);
}
}
for (ComparableEntry e : toRemove)
{
priorityEntries.remove(e);
}
} }
@@ -634,19 +637,7 @@ public class MenuManager
ComparableEntry entry = new ComparableEntry(option, "", false); ComparableEntry entry = new ComparableEntry(option, "", false);
Set<ComparableEntry> toRemove = new HashSet<>(); priorityEntries.removeIf(entry::equals);
for (ComparableEntry priorityEntry : priorityEntries)
{
if (entry.equals(priorityEntry))
{
toRemove.add(entry);
}
}
for (ComparableEntry e : toRemove)
{
priorityEntries.remove(e);
}
} }
/** /**
@@ -757,36 +748,12 @@ public class MenuManager
ComparableEntry swapFrom = new ComparableEntry(option, target, id, type, false, false); ComparableEntry swapFrom = new ComparableEntry(option, target, id, type, false, false);
ComparableEntry swapTo = new ComparableEntry(option2, target2, id2, type2, false, false); ComparableEntry swapTo = new ComparableEntry(option2, target2, id2, type2, false, false);
Set<ComparableEntry> toRemove = new HashSet<>(); swaps.entrySet().removeIf(e -> e.getKey().equals(swapFrom) && e.getValue().equals(swapTo));
for (Map.Entry<ComparableEntry, ComparableEntry> e : swaps.entrySet())
{
if (e.getKey().equals(swapFrom) && e.getValue().equals(swapTo))
{
toRemove.add(e.getKey());
}
}
for (ComparableEntry entry : toRemove)
{
swaps.remove(entry);
}
} }
public void removeSwap(ComparableEntry swapFrom, ComparableEntry swapTo) public void removeSwap(ComparableEntry swapFrom, ComparableEntry swapTo)
{ {
Set<ComparableEntry> toRemove = new HashSet<>(); swaps.entrySet().removeIf(e -> e.getKey().equals(swapFrom) && e.getValue().equals(swapTo));
for (Map.Entry<ComparableEntry, ComparableEntry> e : swaps.entrySet())
{
if (e.getKey().equals(swapFrom) && e.getValue().equals(swapTo))
{
toRemove.add(e.getKey());
}
}
for (ComparableEntry entry : toRemove)
{
swaps.remove(entry);
}
} }
/** /**
@@ -794,21 +761,89 @@ public class MenuManager
*/ */
public void removeSwaps(String withTarget) public void removeSwaps(String withTarget)
{ {
withTarget = Text.standardize(withTarget); final String target = Text.standardize(withTarget);
Set<ComparableEntry> toRemove = new HashSet<>(); swaps.keySet().removeIf(e -> e.getTarget().equals(target));
for (ComparableEntry e : swaps.keySet())
{
if (e.getTarget().equals(withTarget))
{
toRemove.add(e);
}
} }
for (ComparableEntry entry : toRemove) /**
* Adds to the set of menu entries which when present, will be hidden from the menu
*/
public void addHiddenEntry(String option, String target)
{ {
swaps.remove(entry); option = Text.standardize(option);
} target = Text.standardize(target);
ComparableEntry entry = new ComparableEntry(option, target);
hiddenEntries.add(entry);
}
public void removeHiddenEntry(String option, String target)
{
option = Text.standardize(option);
target = Text.standardize(target);
ComparableEntry entry = new ComparableEntry(option, target);
hiddenEntries.removeIf(entry::equals);
}
/**
* Adds to the set of menu entries which when present, will be hidden from the menu
* This method will add one with strict option, but not-strict target (contains for target, equals for option)
*/
public void addHiddenEntry(String option)
{
option = Text.standardize(option);
ComparableEntry entry = new ComparableEntry(option, "", false);
hiddenEntries.add(entry);
}
public void removeHiddenEntry(String option)
{
option = Text.standardize(option);
ComparableEntry entry = new ComparableEntry(option, "", false);
hiddenEntries.removeIf(entry::equals);
}
/**
* Adds to the set of hidden entries.
*/
public void addHiddenEntry(String option, String target, boolean strictOption, boolean strictTarget)
{
option = Text.standardize(option);
target = Text.standardize(target);
ComparableEntry entry = new ComparableEntry(option, target, -1, -1, strictOption, strictTarget);
hiddenEntries.add(entry);
}
public void removeHiddenEntry(String option, String target, boolean strictOption, boolean strictTarget)
{
option = Text.standardize(option);
target = Text.standardize(target);
ComparableEntry entry = new ComparableEntry(option, target, -1, -1, strictOption, strictTarget);
hiddenEntries.remove(entry);
}
/**
* Adds to the set of hidden entries - Pre-baked Abstract entry
*/
public void addHiddenEntry(ComparableEntry entry)
{
hiddenEntries.add(entry);
}
public void removeHiddenEntry(ComparableEntry entry)
{
hiddenEntries.remove(entry);
} }
} }

View File

@@ -37,10 +37,12 @@ public enum AoeProjectileInfo
LIZARDMAN_SHAMAN_AOE(ProjectileID.LIZARDMAN_SHAMAN_AOE, 5), LIZARDMAN_SHAMAN_AOE(ProjectileID.LIZARDMAN_SHAMAN_AOE, 5),
CRAZY_ARCHAEOLOGIST_AOE(ProjectileID.CRAZY_ARCHAEOLOGIST_AOE, 3), CRAZY_ARCHAEOLOGIST_AOE(ProjectileID.CRAZY_ARCHAEOLOGIST_AOE, 3),
ICE_DEMON_RANGED_AOE(ProjectileID.ICE_DEMON_RANGED_AOE, 3), ICE_DEMON_RANGED_AOE(ProjectileID.ICE_DEMON_RANGED_AOE, 3),
/** /**
* When you don't have pray range on ice demon does an ice barrage * When you don't have pray range on ice demon does an ice barrage
*/ */
ICE_DEMON_ICE_BARRAGE_AOE(ProjectileID.ICE_DEMON_ICE_BARRAGE_AOE, 3), ICE_DEMON_ICE_BARRAGE_AOE(ProjectileID.ICE_DEMON_ICE_BARRAGE_AOE, 3),
/** /**
* The AOE when vasa first starts * The AOE when vasa first starts
*/ */
@@ -62,6 +64,9 @@ public enum AoeProjectileInfo
GALVEK_MINE(ProjectileID.GALVEK_MINE, 3), GALVEK_MINE(ProjectileID.GALVEK_MINE, 3),
GALVEK_BOMB(ProjectileID.GALVEK_BOMB, 3), GALVEK_BOMB(ProjectileID.GALVEK_BOMB, 3),
/**
* the AOEs of Grotesque Guardians
*/
DAWN_FREEZE(ProjectileID.DAWN_FREEZE, 3), DAWN_FREEZE(ProjectileID.DAWN_FREEZE, 3),
DUSK_CEILING(ProjectileID.DUSK_CEILING, 3), DUSK_CEILING(ProjectileID.DUSK_CEILING, 3),
@@ -78,7 +83,6 @@ public enum AoeProjectileInfo
/** /**
* the AOE of the Corporeal Beast * the AOE of the Corporeal Beast
*/ */
CORPOREAL_BEAST(ProjectileID.CORPOREAL_BEAST_AOE, 1), CORPOREAL_BEAST(ProjectileID.CORPOREAL_BEAST_AOE, 1),
CORPOREAL_BEAST_DARK_CORE(ProjectileID.CORPOREAL_BEAST_DARK_CORE_AOE, 3), CORPOREAL_BEAST_DARK_CORE(ProjectileID.CORPOREAL_BEAST_DARK_CORE_AOE, 3),
@@ -114,7 +118,12 @@ public enum AoeProjectileInfo
/** /**
* Cerbs fire * Cerbs fire
*/ */
CERB_FIRE(ProjectileID.CERB_FIRE, 2); CERB_FIRE(ProjectileID.CERB_FIRE, 2),
/**
* Demonic gorilla
*/
DEMONIC_GORILLA_BOULDER(ProjectileID.DEMONIC_GORILLA_BOULDER, 1);
private static final Map<Integer, AoeProjectileInfo> map = new HashMap<>(); private static final Map<Integer, AoeProjectileInfo> map = new HashMap<>();

View File

@@ -818,4 +818,41 @@ public interface AoeWarningConfig extends Config
{ {
return false; return false;
} }
@ConfigItem(
keyName = "demonicGorillaStub",
name = "Demonic Gorilla",
description = "",
position = 64,
parent = "npcStub"
)
default Stub demonicGorillaStub()
{
return new Stub();
}
@ConfigItem(
keyName = "demonicGorilla",
name = "Demonic Gorilla",
description = "Configures if Demonic Gorilla boulder tile markers are displayed",
parent = "demonicGorillaStub",
position = 65
)
default boolean isDemonicGorillaEnabled()
{
return true;
}
@ConfigItem(
keyName = "demonicGorillaNotify",
name = "Demonic Gorilla Notify",
description = "Configures whether or not AoE Projectile Warnings for Demonic Gorilla boulders should trigger a notification",
parent = "demonicGorillaStub",
position = 66,
hide = "aoeNotifyAll"
)
default boolean isDemonicGorillaNotifyEnabled()
{
return false;
}
} }

View File

@@ -330,6 +330,8 @@ public class AoeWarningPlugin extends Plugin
return notify ? config.isDrakeNotifyEnabled() : config.isDrakeEnabled(); return notify ? config.isDrakeNotifyEnabled() : config.isDrakeEnabled();
case CERB_FIRE: case CERB_FIRE:
return notify ? config.isCerbFireNotifyEnabled() : config.isCerbFireEnabled(); return notify ? config.isCerbFireNotifyEnabled() : config.isCerbFireEnabled();
case DEMONIC_GORILLA_BOULDER:
return notify ? config.isDemonicGorillaNotifyEnabled() : config.isDemonicGorillaEnabled();
} }
return false; return false;

View File

@@ -98,7 +98,7 @@ public class AnagramClue extends ClueScroll implements TextClueScroll, NpcClueSc
new AnagramClue("HE DO POSE. IT IS CULTRRL, MK?", "Riki the sculptor's model", new WorldPoint(2904, 10206, 0), "East Keldagrim, south of kebab seller."), new AnagramClue("HE DO POSE. IT IS CULTRRL, MK?", "Riki the sculptor's model", new WorldPoint(2904, 10206, 0), "East Keldagrim, south of kebab seller."),
new AnagramClue("HEORIC", "Eohric", new WorldPoint(2900, 3565, 0), "Top floor of Burthorpe Castle", "36"), new AnagramClue("HEORIC", "Eohric", new WorldPoint(2900, 3565, 0), "Top floor of Burthorpe Castle", "36"),
new AnagramClue("HIS PHOR", "Horphis", new WorldPoint(1639, 3812, 0), "Arceuus Library, Zeah", "1"), new AnagramClue("HIS PHOR", "Horphis", new WorldPoint(1639, 3812, 0), "Arceuus Library, Zeah", "1"),
new AnagramClue("I AM SIR", "Marisi", new WorldPoint(1813, 3488, 0), "Allotment patch, South coast Zeah", "5"), new AnagramClue("I AM SIR", "Marisi", new WorldPoint(1737, 3557, 0), "Allotment patch, South of Hosidius chapel", "5"),
new AnagramClue("ICY FE", "Fycie", new WorldPoint(2630, 2997, 0), "East Feldip Hills"), new AnagramClue("ICY FE", "Fycie", new WorldPoint(2630, 2997, 0), "East Feldip Hills"),
new AnagramClue("I DOOM ICON INN", "Dominic Onion", new WorldPoint(2609, 3116, 0), "Nightmare Zone", "9,500"), new AnagramClue("I DOOM ICON INN", "Dominic Onion", new WorldPoint(2609, 3116, 0), "Nightmare Zone", "9,500"),
new AnagramClue("I EAT ITS CHART HINTS DO U", "Shiratti the Custodian", new WorldPoint(3427, 2927, 0), "North of fountain, Nardah"), new AnagramClue("I EAT ITS CHART HINTS DO U", "Shiratti the Custodian", new WorldPoint(3427, 2927, 0), "North of fountain, Nardah"),

View File

@@ -166,6 +166,7 @@ public class CoordinateClue extends ClueScroll implements TextClueScroll, Locati
.put(new WorldPoint(3380, 3963, 0), "Wilderness. North of Volcano.") .put(new WorldPoint(3380, 3963, 0), "Wilderness. North of Volcano.")
.put(new WorldPoint(3051, 3736, 0), "East of the Wilderness Obelisk in 28 Wilderness.") .put(new WorldPoint(3051, 3736, 0), "East of the Wilderness Obelisk in 28 Wilderness.")
.put(new WorldPoint(2316, 3814, 0), "West of Neitiznot, near the bridge.") .put(new WorldPoint(2316, 3814, 0), "West of Neitiznot, near the bridge.")
.put(new WorldPoint(2872, 3937, 0), "Weiss.")
// Master // Master
.put(new WorldPoint(2178, 3209, 0), "South of Elf Camp.") .put(new WorldPoint(2178, 3209, 0), "South of Elf Camp.")
.put(new WorldPoint(2155, 3100, 0), "South of Port Tyras (BJS).") .put(new WorldPoint(2155, 3100, 0), "South of Port Tyras (BJS).")
@@ -181,7 +182,7 @@ public class CoordinateClue extends ClueScroll implements TextClueScroll, Locati
.put(new WorldPoint(3085, 3569, 0), "Wilderness. Obelisk of Air.") .put(new WorldPoint(3085, 3569, 0), "Wilderness. Obelisk of Air.")
.put(new WorldPoint(2934, 2727, 0), "Eastern shore of Crash Island.") .put(new WorldPoint(2934, 2727, 0), "Eastern shore of Crash Island.")
.put(new WorldPoint(1451, 3695, 0), "West side of Lizardman Canyon with Lizardman shaman.") .put(new WorldPoint(1451, 3695, 0), "West side of Lizardman Canyon with Lizardman shaman.")
.put(new WorldPoint(2538, 3739, 0), "Waterbirth Island.") .put(new WorldPoint(2538, 3739, 0), "Waterbirth Island. Bring a pet rock and rune thrownaxe.")
.put(new WorldPoint(1698, 3792, 0), "Arceuus church.") .put(new WorldPoint(1698, 3792, 0), "Arceuus church.")
.put(new WorldPoint(2951, 3820, 0), "Wilderness. Chaos Temple (level 38).") .put(new WorldPoint(2951, 3820, 0), "Wilderness. Chaos Temple (level 38).")
.put(new WorldPoint(2202, 3825, 0), "Pirates' Cove, between Lunar Isle and Rellekka.") .put(new WorldPoint(2202, 3825, 0), "Pirates' Cove, between Lunar Isle and Rellekka.")

View File

@@ -62,7 +62,7 @@ public class SceneOverlay extends Overlay
private static final int MAP_SQUARE_SIZE = CHUNK_SIZE * CHUNK_SIZE; // 64 private static final int MAP_SQUARE_SIZE = CHUNK_SIZE * CHUNK_SIZE; // 64
private static final int CULL_CHUNK_BORDERS_RANGE = 16; private static final int CULL_CHUNK_BORDERS_RANGE = 16;
private static final int STROKE_WIDTH = 4; private static final int STROKE_WIDTH = 4;
private static final int CULL_LINE_OF_SIGHT_RANGE = 10; private static final int CULL_LINE_OF_SIGHT_RANGE = 20;
private static final int INTERACTING_SHIFT = -16; private static final int INTERACTING_SHIFT = -16;
private static final Polygon ARROW_HEAD = new Polygon( private static final Polygon ARROW_HEAD = new Polygon(

View File

@@ -53,7 +53,7 @@ enum DiscordGameEventType
TRAINING_COOKING(Skill.COOKING), TRAINING_COOKING(Skill.COOKING),
TRAINING_WOODCUTTING(Skill.WOODCUTTING), TRAINING_WOODCUTTING(Skill.WOODCUTTING),
TRAINING_FLETCHING(Skill.FLETCHING), TRAINING_FLETCHING(Skill.FLETCHING),
TRAINING_FISHING(Skill.FISHING), TRAINING_FISHING(Skill.FISHING, 1),
TRAINING_FIREMAKING(Skill.FIREMAKING), TRAINING_FIREMAKING(Skill.FIREMAKING),
TRAINING_CRAFTING(Skill.CRAFTING), TRAINING_CRAFTING(Skill.CRAFTING),
TRAINING_SMITHING(Skill.SMITHING), TRAINING_SMITHING(Skill.SMITHING),

View File

@@ -0,0 +1,53 @@
package net.runelite.client.plugins.implings;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.util.Map;
import javax.inject.Inject;
import net.runelite.api.Client;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.components.table.TableAlignment;
import net.runelite.client.ui.overlay.components.table.TableComponent;
import net.runelite.client.ui.overlay.components.PanelComponent;
public class ImplingCounterOverlay extends Overlay
{
private final Client client;
private final ImplingsPlugin plugin;
private final ImplingsConfig config;
private final PanelComponent panelComponent = new PanelComponent();
@Inject
public ImplingCounterOverlay(Client client, ImplingsConfig config, ImplingsPlugin plugin)
{
this.client = client;
this.config = config;
this.plugin = plugin;
setPosition(OverlayPosition.TOP_LEFT);
}
@Override
public Dimension render(Graphics2D graphics)
{
if (!config.showCounter() || plugin.getImplings().isEmpty())
return null;
panelComponent.getChildren().clear();
TableComponent tableComponent = new TableComponent();
tableComponent.setColumnAlignments(TableAlignment.LEFT, TableAlignment.RIGHT);
for (Map.Entry<ImplingType, Integer> entry : plugin.getImplingCounterMap().entrySet())
{
if (plugin.showImplingType(entry.getKey()) && entry.getValue() != 0)
{
tableComponent.addRow(entry.getKey().getName(), entry.getValue().toString());
}
}
panelComponent.getChildren().add(tableComponent);
return panelComponent.render(graphics);
}
}

View File

@@ -320,4 +320,15 @@ public interface ImplingsConfig extends Config
{ {
return Color.WHITE; return Color.WHITE;
} }
@ConfigItem(
position = 26,
keyName = "showCounter",
name = "Show impling counter overlay",
description = "Shows how many of each impling there is nearby"
)
default boolean showCounter()
{
return false;
}
} }

View File

@@ -30,11 +30,13 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.HashMap;
import javax.inject.Inject; import javax.inject.Inject;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.Getter; import lombok.Getter;
import net.runelite.api.GameState; import net.runelite.api.GameState;
import net.runelite.api.NPC; import net.runelite.api.NPC;
import net.runelite.api.events.GameTick;
import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.GameStateChanged;
import net.runelite.api.events.NpcDespawned; import net.runelite.api.events.NpcDespawned;
import net.runelite.api.events.NpcSpawned; import net.runelite.api.events.NpcSpawned;
@@ -58,6 +60,9 @@ public class ImplingsPlugin extends Plugin
private static final int DYNAMIC_SPAWN_ECLECTIC = 1633; private static final int DYNAMIC_SPAWN_ECLECTIC = 1633;
private static final int DYNAMIC_SPAWN_BABY_ESSENCE = 1634; private static final int DYNAMIC_SPAWN_BABY_ESSENCE = 1634;
@Getter
private Map<ImplingType, Integer> implingCounterMap = new HashMap<>();
@Getter(AccessLevel.PACKAGE) @Getter(AccessLevel.PACKAGE)
private final List<NPC> implings = new ArrayList<>(); private final List<NPC> implings = new ArrayList<>();
@@ -67,6 +72,10 @@ public class ImplingsPlugin extends Plugin
@Inject @Inject
private ImplingsOverlay overlay; private ImplingsOverlay overlay;
@Inject
private ImplingCounterOverlay implingCounterOverlay;
@Inject @Inject
private OverlayManager overlayManager; private OverlayManager overlayManager;
@@ -91,6 +100,7 @@ public class ImplingsPlugin extends Plugin
overlayManager.add(overlay); overlayManager.add(overlay);
overlayManager.add(minimapOverlay); overlayManager.add(minimapOverlay);
overlayManager.add(implingCounterOverlay);
} }
@Override @Override
@@ -98,6 +108,27 @@ public class ImplingsPlugin extends Plugin
{ {
overlayManager.remove(overlay); overlayManager.remove(overlay);
overlayManager.remove(minimapOverlay); overlayManager.remove(minimapOverlay);
overlayManager.remove(implingCounterOverlay);
}
@Subscribe
public void onGameTick(GameTick event)
{
implingCounterMap.clear();
for (NPC npc : implings)
{
Impling impling = Impling.findImpling(npc.getId());
ImplingType type = impling.getImplingType();
if (implingCounterMap.containsKey(type))
{
implingCounterMap.put(type, implingCounterMap.get(type) + 1);
}
else
{
implingCounterMap.put(type, 1);
}
}
} }
@Subscribe @Subscribe
@@ -118,6 +149,7 @@ public class ImplingsPlugin extends Plugin
if (event.getGameState() == GameState.LOGIN_SCREEN || event.getGameState() == GameState.HOPPING) if (event.getGameState() == GameState.LOGIN_SCREEN || event.getGameState() == GameState.HOPPING)
{ {
implings.clear(); implings.clear();
implingCounterMap.clear();
} }
} }
@@ -131,6 +163,7 @@ public class ImplingsPlugin extends Plugin
NPC npc = npcDespawned.getNpc(); NPC npc = npcDespawned.getNpc();
implings.remove(npc); implings.remove(npc);
} }
boolean showNpc(NPC npc) boolean showNpc(NPC npc)
@@ -183,7 +216,12 @@ public class ImplingsPlugin extends Plugin
return null; return null;
} }
switch (impling.getImplingType()) return typeToColor(impling.getImplingType());
}
Color typeToColor(ImplingType type)
{
switch (type)
{ {
case BABY: case BABY:

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018, https://runelitepl.us * Copyright (c) 2019, Jacky <liangj97@gmail.com>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -22,18 +22,34 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package net.runelite.client.plugins.vorkath; package net.runelite.client.plugins.inferno;
import lombok.Getter; import net.runelite.client.config.Config;
import net.runelite.api.NPC; import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
class ZombifiedSpawn @ConfigGroup("inferno")
public interface InfernoConfig extends Config
{ {
@Getter @ConfigItem(
private NPC npc; position = 0,
keyName = "Nibbler Overlay",
ZombifiedSpawn(NPC npc) name = "Nibbler Overlay",
description = "Shows if there are any Nibblers left"
)
default boolean displayNibblerOverlay()
{ {
this.npc = npc; return false;
}
@ConfigItem(
position = 1,
keyName = "Prayer Helper",
name = "Prayer Helper",
description = "Tells you what to flick in how many ticks"
)
default boolean showPrayerHelp()
{
return false;
} }
} }

View File

@@ -0,0 +1,78 @@
/*
* Copyright (c) 2019, Jacky <liangj97@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.plugins.inferno;
import java.awt.Dimension;
import java.awt.Graphics2D;
import javax.inject.Inject;
import net.runelite.api.Client;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.components.table.TableAlignment;
import net.runelite.client.ui.overlay.components.table.TableComponent;
import net.runelite.client.ui.overlay.components.PanelComponent;
public class InfernoInfobox extends Overlay
{
private final Client client;
private final InfernoPlugin plugin;
private final InfernoConfig config;
private final PanelComponent panelComponent = new PanelComponent();
@Inject
public InfernoInfobox(Client client, InfernoConfig config, InfernoPlugin plugin)
{
this.client = client;
this.config = config;
this.plugin = plugin;
setPosition(OverlayPosition.TOP_LEFT);
}
@Override
public Dimension render(Graphics2D graphics)
{
if (!config.showPrayerHelp() || client.getMapRegions()[0] != 9043) return null;
panelComponent.getChildren().clear();
TableComponent tableComponent = new TableComponent();
tableComponent.setColumnAlignments(TableAlignment.LEFT, TableAlignment.RIGHT);
for (int i = plugin.getPriorityNPC().length; i > 0; i--)
{
if (plugin.getPriorityNPC()[i - 1] == null)
{
tableComponent.addRow(Integer.toString(i), "-");
}
else
{
tableComponent.addRow(plugin.getPriorityNPC()[i - 1].getName(), plugin.getPriorityNPC()[i - 1 ].getAttackstyle().getName());
}
}
panelComponent.getChildren().add(tableComponent);
return panelComponent.render(graphics);
}
}

View File

@@ -0,0 +1,185 @@
/*
* Copyright (c) 2019, Jacky <liangj97@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.plugins.inferno;
import java.awt.Color;
import lombok.Getter;
import lombok.Setter;
import net.runelite.api.NPC;
import net.runelite.api.NpcID;
public class InfernoNPC
{
public enum Attackstyle
{
MAGE("Mage", Color.CYAN),
RANGE("Range", Color.GREEN),
MELEE("Melee", Color.WHITE),
RANDOM("Random", Color.ORANGE);
@Getter
private String name = "";
@Getter
private Color color;
Attackstyle(String s, Color c)
{
this.name = s;
this.color = c;
}
}
@Getter
private NPC npc;
@Getter
private String name;
@Getter
@Setter
private Attackstyle attackstyle;
@Getter
private int attackTicks;
@Getter
private int priority;
@Getter
@Setter
private int ticksTillAttack = -1;
@Getter
@Setter
private boolean attacking = false;
@Getter
private int attackAnimation;
@Getter
private boolean isMidAttack = false;
@Getter
@Setter
private int distanceToPlayer = 0;
@Getter
int textLocHeight;
public InfernoNPC(NPC npc)
{
this.npc = npc;
textLocHeight = npc.getLogicalHeight() + 40;
switch (npc.getId())
{
case NpcID.JALAKREKKET:
attackTicks = 4;
name = "lil mel";
attackAnimation = 7582;
attackstyle = Attackstyle.MELEE;
priority = 7;
break;
case NpcID.JALAKREKXIL:
attackTicks = 4;
name = "lil range";
attackAnimation = 7583;
attackstyle = Attackstyle.RANGE;
priority = 6;
break;
case NpcID.JALAKREKMEJ:
attackTicks = 4;
name = "lil mage";
attackAnimation = 7581;
attackstyle = Attackstyle.MAGE;
priority = 5;
break;
case NpcID.JALMEJRAH:
attackTicks = 3;
name = "bat";
attackAnimation = 7578;
attackstyle = Attackstyle.RANGE;
priority = 4;
break;
case NpcID.JALAK:
attackTicks = 6;
name = "blob";
attackAnimation = 7583; // also 7581
attackstyle = Attackstyle.RANDOM;
priority = 3;
break;
case NpcID.JALIMKOT:
attackTicks = 4;
name = "meleer";
attackAnimation = 7597;
attackstyle = Attackstyle.MELEE;
priority = 2;
break;
case NpcID.JALXIL:
attackTicks = 4;
name = "ranger";
attackAnimation = 7605;
attackstyle = Attackstyle.RANGE;
priority = 1;
break;
case NpcID.JALZEK:
attackTicks = 4;
name = "mager";
attackAnimation = 7610;
attackstyle = Attackstyle.MAGE;
priority = 0;
break;
default:
attackTicks = 0;
}
}
public String info()
{
String info = "";
if (attacking)
{
info += ticksTillAttack;
}
//info += " D: " + distanceToPlayer;
return info;
}
public void attacked()
{
ticksTillAttack = attackTicks;
attacking = true;
}
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright (c) 2019, Jacky <liangj97@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.plugins.inferno;
import java.awt.Dimension;
import java.awt.Graphics2D;
import javax.inject.Inject;
import net.runelite.api.Client;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.components.PanelComponent;
import net.runelite.client.ui.overlay.components.table.TableAlignment;
import net.runelite.client.ui.overlay.components.table.TableComponent;
public class InfernoNibblerOverlay extends Overlay
{
private final Client client;
private final InfernoPlugin plugin;
private final InfernoConfig config;
private final PanelComponent panelComponent = new PanelComponent();
@Inject
public InfernoNibblerOverlay(Client client, InfernoConfig config, InfernoPlugin plugin)
{
this.client = client;
this.config = config;
this.plugin = plugin;
setPosition(OverlayPosition.TOP_LEFT);
}
@Override
public Dimension render(Graphics2D graphics)
{
if (!config.displayNibblerOverlay() || plugin.getNibblers().size() == 0 || client.getMapRegions()[0] != 9043)
return null;
panelComponent.getChildren().clear();
TableComponent tableComponent = new TableComponent();
tableComponent.setColumnAlignments(TableAlignment.LEFT, TableAlignment.RIGHT);
tableComponent.addRow("Nibblers Left: ", Integer.toString(plugin.getNibblers().size()));
panelComponent.getChildren().add(tableComponent);
return panelComponent.render(graphics);
}
}

View File

@@ -0,0 +1,109 @@
/*
* Copyright (c) 2019, Jacky <liangj97@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.plugins.inferno;
import com.google.common.base.Strings;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics2D;
import javax.inject.Inject;
import net.runelite.api.Client;
import net.runelite.api.NPC;
import net.runelite.api.Perspective;
import net.runelite.api.Point;
import net.runelite.api.coords.LocalPoint;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayLayer;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.components.PanelComponent;
public class InfernoOverlay extends Overlay
{
private final Client client;
private final InfernoPlugin plugin;
private final InfernoConfig config;
private final PanelComponent panelComponent = new PanelComponent();
@Inject
public InfernoOverlay(Client client, InfernoConfig config, InfernoPlugin plugin)
{
setPosition(OverlayPosition.DYNAMIC);
setLayer(OverlayLayer.ABOVE_SCENE);
this.client = client;
this.config = config;
this.plugin = plugin;
}
@Override
public Dimension render(Graphics2D graphics)
{
if (!client.isInInstancedRegion() || client.getMapRegions()[0] != 9043) return null;
for (InfernoNPC monster : plugin.getMonsters().values())
{
NPC npc = monster.getNpc();
//if (npc == null || !config.showPrayer()) return;
LocalPoint lp = npc.getLocalLocation();
if (lp != null)
{
Point point = Perspective.localToCanvas(client, lp, client.getPlane(), npc.getLogicalHeight());
if (point != null)
{
if (monster.getTicksTillAttack() == 1 || (monster.getName().equals("blob") && monster.getTicksTillAttack() <= 3))
{
renderTextLocation(graphics, monster, monster.info(), Color.GREEN);
}
else
{
renderTextLocation(graphics, monster, monster.info(), Color.RED);
}
}
}
}
return null;
}
// renders text location
public static void renderTextLocation(Graphics2D graphics, InfernoNPC actor, String text, Color color)
{
graphics.setFont(new Font("Arial", Font.BOLD, 15));
Point textLocation = actor.getNpc().getCanvasTextLocation(graphics, text, actor.textLocHeight + 40);
if (Strings.isNullOrEmpty(text))
{
return;
}
int x = textLocation.getX();
int y = textLocation.getY();
graphics.setColor(Color.BLACK);
graphics.drawString(text, x + 1, y + 1);
graphics.setColor(color);
graphics.drawString(text, x, y);
}
}

View File

@@ -0,0 +1,275 @@
/*
* Copyright (c) 2019, Jacky <liangj97@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.plugins.inferno;
import com.google.inject.Provides;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import lombok.Getter;
import net.runelite.api.Client;
import net.runelite.api.HeadIcon;
import net.runelite.api.NPC;
import net.runelite.api.NpcID;
import net.runelite.api.events.GameTick;
import net.runelite.api.events.NpcDespawned;
import net.runelite.api.events.NpcSpawned;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.plugins.PluginType;
import net.runelite.client.ui.overlay.OverlayManager;
@PluginDescriptor(
name = "Inferno",
description = "Inferno helper",
tags = {"combat", "overlay", "pve", "pvm"},
type = PluginType.PVM
)
public class InfernoPlugin extends Plugin
{
@Inject
private Client client;
@Inject
private OverlayManager overlayManager;
@Inject
private InfernoOverlay infernoOverlay;
@Inject
private InfernoInfobox infernoInfobox;
@Inject
private InfernoNibblerOverlay nibblerOverlay;
@Inject
private InfernoConfig config;
@Getter
private Map<NPC, InfernoNPC> monsters;
@Getter
private Map<Integer, ArrayList<InfernoNPC>> monsterCurrentAttackMap;
@Getter
private List<NPC> nibblers;
@Getter
private InfernoNPC[] priorityNPC;
@Provides
InfernoConfig provideConfig(ConfigManager configManager)
{
return configManager.getConfig(InfernoConfig.class);
}
@Override
protected void startUp() throws Exception
{
overlayManager.add(infernoOverlay);
overlayManager.add(infernoInfobox);
overlayManager.add(nibblerOverlay);
monsters = new HashMap<>();
monsterCurrentAttackMap = new HashMap<>(6);
for (int i = 1; i <= 6; i++)
{
monsterCurrentAttackMap.put(i, new ArrayList<>());
}
nibblers = new ArrayList<>();
priorityNPC = new InfernoNPC[4];
}
@Override
protected void shutDown() throws Exception
{
overlayManager.remove(infernoInfobox);
overlayManager.remove(infernoOverlay);
overlayManager.remove(nibblerOverlay);
}
@Subscribe
public void onNpcSpawned(NpcSpawned event)
{
if (client.getMapRegions()[0] != 9043) return;
NPC npc = event.getNpc();
if (isValidInfernoMob(npc))
{
monsters.put(npc, new InfernoNPC(npc));
System.out.println(monsters.size());
}
if (npc.getId() == NpcID.JALNIB)
{
nibblers.add(npc);
}
}
@Subscribe
public void onNpcDespawned(NpcDespawned event)
{
if (client.getMapRegions()[0] != 9043) return;
NPC npc = event.getNpc();
if (monsters.containsKey(npc))
{
monsters.remove(npc);
System.out.println(monsters.size());
}
if (npc.getId() == NpcID.JALNIB)
{
nibblers.remove(npc);
}
}
@Subscribe
public void onGameTick(GameTick event)
{
if (client.getMapRegions()[0] != 9043) return;
clearMapAndPriority();
for (InfernoNPC monster : monsters.values())
{
calculateDistanceToPlayer(monster);
NPC npc = monster.getNpc();
// if they are not attacking but are still attacking
if (monster.isAttacking())
{
monster.setTicksTillAttack(monster.getTicksTillAttack() - 1);
// sets the blobs attack style
if (monster.getName().equals("blob") && monster.getTicksTillAttack() == 3 && monster.getDistanceToPlayer() <= 15)
{
if (client.getLocalPlayer().getOverheadIcon() == null)
{
monster.setAttackstyle(InfernoNPC.Attackstyle.RANDOM);
}
else if (client.getLocalPlayer().getOverheadIcon().equals(HeadIcon.MAGIC))
{
monster.setAttackstyle(InfernoNPC.Attackstyle.RANGE);
}
else if (client.getLocalPlayer().getOverheadIcon().equals(HeadIcon.RANGED))
{
monster.setAttackstyle(InfernoNPC.Attackstyle.MAGE);
}
}
// we know the monster is not attacking because it should have attacked and is idling
if (monster.getTicksTillAttack() == 0)
{
if (npc.getAnimation() == -1)
{
monster.setAttacking(false);
}
else
{
// want to reset the monsters attack back to attacking
monster.attacked();
}
}
}
else
{
// they've just attacked
if (npc.getAnimation() == monster.getAttackAnimation() || npc.getAnimation() == 7581) // special case for blob
{
monster.attacked();
}
}
if (monster.getTicksTillAttack() >= 1)
{
monsterCurrentAttackMap.get(monster.getTicksTillAttack()).add(monster);
}
}
calculatePriorityNPC();
}
private void calculatePriorityNPC()
{
for (int i = 0; i < priorityNPC.length; i++)
{
ArrayList<InfernoNPC> monsters = monsterCurrentAttackMap.get(i + 1);
if ( monsters.size() == 0) continue;
int priority = monsters.get(0).getPriority();
InfernoNPC infernoNPC = monsters.get(0);
for (InfernoNPC npc : monsters)
{
if (npc.getPriority() < priority)
{
priority = npc.getPriority();
infernoNPC = npc;
}
}
priorityNPC[i] = infernoNPC;
System.out.println("i: " + i + " " + infernoNPC.getName());
}
}
// TODO: blob calculator
private void calculateDistanceToPlayer(InfernoNPC monster)
{
monster.setDistanceToPlayer(client.getLocalPlayer().getWorldLocation().distanceTo(monster.getNpc().getWorldArea()));
}
private void clearMapAndPriority()
{
for (List<InfernoNPC> l : monsterCurrentAttackMap.values())
{
l.clear();
}
for (int i = 0; i < priorityNPC.length; i++)
{
priorityNPC[i] = null;
}
}
public boolean isValidInfernoMob(NPC npc)
{
// we only want the bat, blob, melee, ranger and mager
if (npc.getId() == NpcID.JALMEJRAH ||
npc.getId() == NpcID.JALAK ||
npc.getId() == NpcID.JALIMKOT ||
npc.getId() == NpcID.JALXIL ||
npc.getId() == NpcID.JALZEK) return true;
return false;
}
}

View File

@@ -107,7 +107,10 @@ class KeyRemappingListener extends MouseAdapter implements KeyListener
} }
} }
if (config.fkeyRemap()) // In addition to the above checks, the F-key remapping shouldn't
// activate when dialogs are open which listen for number keys
// to select options
if (config.fkeyRemap() && !plugin.isDialogOpen())
{ {
if (ONE.matches(e)) if (ONE.matches(e))
{ {
@@ -188,23 +191,18 @@ class KeyRemappingListener extends MouseAdapter implements KeyListener
switch (e.getKeyCode()) switch (e.getKeyCode())
{ {
case KeyEvent.VK_ENTER: case KeyEvent.VK_ENTER:
case KeyEvent.VK_ESCAPE:
plugin.setTyping(false); plugin.setTyping(false);
clientThread.invoke(plugin::lockChat); clientThread.invoke(plugin::lockChat);
break; break;
case KeyEvent.VK_ESCAPE:
plugin.setTyping(false);
clientThread.invoke(() ->
{
client.setVar(VarClientStr.CHATBOX_TYPED_TEXT, "");
plugin.lockChat();
});
break;
case KeyEvent.VK_BACK_SPACE: case KeyEvent.VK_BACK_SPACE:
// Only lock chat on backspace when the typed text is now empty
if (Strings.isNullOrEmpty(client.getVar(VarClientStr.CHATBOX_TYPED_TEXT))) if (Strings.isNullOrEmpty(client.getVar(VarClientStr.CHATBOX_TYPED_TEXT)))
{ {
plugin.setTyping(false); plugin.setTyping(false);
clientThread.invoke(plugin::lockChat); clientThread.invoke(plugin::lockChat);
} }
break;
} }
} }
} }

View File

@@ -135,6 +135,26 @@ public class KeyRemappingPlugin extends Plugin
return true; return true;
} }
/**
* Check if a dialog is open that will grab numerical input, to prevent F-key remapping
* from triggering.
*
* @return
*/
boolean isDialogOpen()
{
// Most chat dialogs with numerical input are added without the chatbox or its key listener being removed,
// so chatboxFocused() is true. The chatbox onkey script uses the following logic to ignore key presses,
// so we will use it too to not remap F-keys.
return isHidden(WidgetInfo.CHATBOX_MESSAGES) || isHidden(WidgetInfo.CHATBOX_TRANSPARENT_LINES);
}
private boolean isHidden(WidgetInfo widgetInfo)
{
Widget w = client.getWidget(widgetInfo);
return w == null || w.isSelfHidden();
}
@Subscribe @Subscribe
public void onScriptCallbackEvent(ScriptCallbackEvent scriptCallbackEvent) public void onScriptCallbackEvent(ScriptCallbackEvent scriptCallbackEvent)
{ {
@@ -162,22 +182,17 @@ public class KeyRemappingPlugin extends Plugin
} }
void lockChat() void lockChat()
{
Widget chatboxParent = client.getWidget(WidgetInfo.CHATBOX_PARENT);
if (chatboxParent != null && chatboxParent.getOnKeyListener() != null)
{ {
Widget chatboxInput = client.getWidget(WidgetInfo.CHATBOX_INPUT); Widget chatboxInput = client.getWidget(WidgetInfo.CHATBOX_INPUT);
if (chatboxInput != null) if (chatboxInput != null)
{ {
chatboxInput.setText(getPlayerNameWithIcon() + ": " + PRESS_ENTER_TO_CHAT); chatboxInput.setText(getPlayerNameWithIcon() + ": " + PRESS_ENTER_TO_CHAT);
} // Typed text can be non-empty on plugin start, so clear it now
client.setVar(VarClientStr.CHATBOX_TYPED_TEXT, "");
} }
} }
void unlockChat() void unlockChat()
{
Widget chatboxParent = client.getWidget(WidgetInfo.CHATBOX_PARENT);
if (chatboxParent != null)
{ {
Widget chatboxInput = client.getWidget(WidgetInfo.CHATBOX_INPUT); Widget chatboxInput = client.getWidget(WidgetInfo.CHATBOX_INPUT);
if (chatboxInput != null) if (chatboxInput != null)
@@ -190,7 +205,6 @@ public class KeyRemappingPlugin extends Plugin
} }
} }
} }
}
private String getPlayerNameWithIcon() private String getPlayerNameWithIcon()
{ {

View File

@@ -43,6 +43,8 @@ import static net.runelite.api.ObjectID.ROCKS_11374;
import static net.runelite.api.ObjectID.ROCKS_11375; import static net.runelite.api.ObjectID.ROCKS_11375;
import static net.runelite.api.ObjectID.ROCKS_11376; import static net.runelite.api.ObjectID.ROCKS_11376;
import static net.runelite.api.ObjectID.ROCKS_11377; import static net.runelite.api.ObjectID.ROCKS_11377;
import static net.runelite.api.ObjectID.ROCKS_11386;
import static net.runelite.api.ObjectID.ROCKS_11387;
enum Rock enum Rock
{ {
@@ -65,7 +67,9 @@ enum Rock
} }
}, },
SILVER(Duration.ofMinutes(1), ROCKS_11369), SILVER(Duration.ofMinutes(1), ROCKS_11369),
SANDSTONE(Duration.ofMillis(5400), ROCKS_11386),
GOLD(Duration.ofMinutes(1), ROCKS_11370, ROCKS_11371), GOLD(Duration.ofMinutes(1), ROCKS_11370, ROCKS_11371),
GRANITE(Duration.ofMillis(5400), ROCKS_11387),
MITHRIL(Duration.ofMinutes(2), ROCKS_11372, ROCKS_11373) MITHRIL(Duration.ofMinutes(2), ROCKS_11372, ROCKS_11373)
{ {
@Override @Override

View File

@@ -32,7 +32,7 @@ import javax.inject.Inject;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client; import net.runelite.api.Client;
import net.runelite.api.events.ConfigChanged; import net.runelite.api.events.ConfigChanged;
import net.runelite.api.events.WidgetLoaded; import net.runelite.api.events.ScriptCallbackEvent;
import net.runelite.api.widgets.WidgetID; import net.runelite.api.widgets.WidgetID;
import net.runelite.api.widgets.WidgetInfo; import net.runelite.api.widgets.WidgetInfo;
import net.runelite.client.RuneLiteProperties; import net.runelite.client.RuneLiteProperties;
@@ -46,7 +46,6 @@ import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.plugins.PluginType; import net.runelite.client.plugins.PluginType;
import net.runelite.client.ui.ClientUI; import net.runelite.client.ui.ClientUI;
import org.apache.commons.lang3.ArrayUtils;
@PluginDescriptor( @PluginDescriptor(
loadWhenOutdated = true, // prevent users from disabling loadWhenOutdated = true, // prevent users from disabling
@@ -66,7 +65,7 @@ public class RuneLitePlusPlugin extends Plugin
@Override @Override
public void keyTyped(KeyEvent keyEvent) public void keyTyped(KeyEvent keyEvent)
{ {
if (!isNumber(keyEvent)) if (!Character.isDigit(keyEvent.getKeyChar()))
{ {
return; return;
} }
@@ -92,12 +91,6 @@ public class RuneLitePlusPlugin extends Plugin
public void keyReleased(KeyEvent keyEvent) public void keyReleased(KeyEvent keyEvent)
{ {
} }
private boolean isNumber(KeyEvent keyEvent)
{
char character = keyEvent.getKeyChar();
return ArrayUtils.contains(numbers, character);
}
} }
/* Can't feed this as args to runscript? /* Can't feed this as args to runscript?
@@ -126,7 +119,6 @@ public class RuneLitePlusPlugin extends Plugin
public static boolean customPresenceEnabled = false; public static boolean customPresenceEnabled = false;
public static final String rlPlusDiscordApp = "560644885250572289"; public static final String rlPlusDiscordApp = "560644885250572289";
public static final String rlDiscordApp = "409416265891971072"; public static final String rlDiscordApp = "409416265891971072";
private static final char[] numbers = "0123456789".toCharArray();
@Inject @Inject
public RuneLitePlusConfig config; public RuneLitePlusConfig config;
@@ -155,6 +147,7 @@ public class RuneLitePlusPlugin extends Plugin
private RuneLitePlusKeyListener keyListener = new RuneLitePlusKeyListener(); private RuneLitePlusKeyListener keyListener = new RuneLitePlusKeyListener();
private int entered = -1; private int entered = -1;
private int enterIdx; private int enterIdx;
private boolean expectInput;
@Override @Override
protected void startUp() throws Exception protected void startUp() throws Exception
@@ -170,6 +163,7 @@ public class RuneLitePlusPlugin extends Plugin
entered = -1; entered = -1;
enterIdx = 0; enterIdx = 0;
expectInput = false;
} }
@Subscribe @Subscribe
@@ -202,8 +196,9 @@ public class RuneLitePlusPlugin extends Plugin
else if (!config.keyboardPin()) else if (!config.keyboardPin())
{ {
entered = -1; entered = 0;
enterIdx = 0; enterIdx = 0;
expectInput = false;
keyManager.unregisterKeyListener(keyListener); keyManager.unregisterKeyListener(keyListener);
} }
} }
@@ -211,33 +206,41 @@ public class RuneLitePlusPlugin extends Plugin
@Override @Override
protected void shutDown() throws Exception protected void shutDown() throws Exception
{ {
entered = -1; entered = 0;
enterIdx = 0; enterIdx = 0;
expectInput = false;
keyManager.unregisterKeyListener(keyListener); keyManager.unregisterKeyListener(keyListener);
} }
@Subscribe @Subscribe
public void onWidgetLoaded(WidgetLoaded event) private void onScriptCallbackEvent(ScriptCallbackEvent e)
{ {
if (!config.keyboardPin()) if (e.getEventName().equals("bankpin"))
{ {
return; int[] intStack = client.getIntStack();
} int intStackSize = client.getIntStackSize();
if (event.getGroupId() == WidgetID.BANK_GROUP_ID) // This'll be anywhere from -1 to 3
// 0 = first number, 1 second, etc
// Anything other than 0123 means the bankpin interface closes
int enterIdx = intStack[intStackSize - 1];
if (enterIdx < 0 || enterIdx > 3)
{ {
// log.debug("Bank opened, removing key listener");
keyManager.unregisterKeyListener(keyListener); keyManager.unregisterKeyListener(keyListener);
this.enterIdx = 0;
this.entered = 0;
expectInput = false;
return; return;
} }
else if (event.getGroupId() != WidgetID.BANK_PIN_GROUP_ID) else if (enterIdx == 0)
//|| !Text.standardize(client.getWidget(WidgetInfo.BANK_PIN_TOP_LEFT_TEXT).getText()).equals("bank of gielinor"))
{ {
return; keyManager.registerKeyListener(keyListener);
} }
// log.debug("Registering key listener"); this.enterIdx = enterIdx;
keyManager.registerKeyListener(keyListener); expectInput = true;
}
} }
private void handleKey(char c) private void handleKey(char c)
@@ -245,37 +248,38 @@ public class RuneLitePlusPlugin extends Plugin
if (client.getWidget(WidgetID.BANK_PIN_GROUP_ID, 0) == null if (client.getWidget(WidgetID.BANK_PIN_GROUP_ID, 0) == null
|| !client.getWidget(WidgetInfo.BANK_PIN_TOP_LEFT_TEXT).getText().equals("Bank of Gielinor")) || !client.getWidget(WidgetInfo.BANK_PIN_TOP_LEFT_TEXT).getText().equals("Bank of Gielinor"))
{ {
// log.debug("Key was pressed, but widget wasn't open"); entered = 0;
entered = -1;
enterIdx = 0; enterIdx = 0;
expectInput = false;
keyManager.unregisterKeyListener(keyListener); keyManager.unregisterKeyListener(keyListener);
return; return;
} }
if (!expectInput)
{
return;
}
int num = Character.getNumericValue(c); int num = Character.getNumericValue(c);
// We gotta copy this cause enteridx changes while the script is executing
int oldEnterIdx = enterIdx;
// Script 685 will call 653, which in turn will set expectInput to true
expectInput = false;
client.runScript(685, num, enterIdx, entered, 13959181, 13959183, 13959184, 13959186, 13959188, 13959190, 13959192, 13959194, 13959196, 13959198, 13959200, 13959202, 13959171, 13959172, 13959173, 13959174, 13959178); client.runScript(685, num, enterIdx, entered, 13959181, 13959183, 13959184, 13959186, 13959188, 13959190, 13959192, 13959194, 13959196, 13959198, 13959200, 13959202, 13959171, 13959172, 13959173, 13959174, 13959178);
if (enterIdx == 0) if (oldEnterIdx == 0)
{ {
entered = num * 1000; entered = num * 1000;
enterIdx++;
} }
else if (enterIdx == 1) else if (oldEnterIdx == 1)
{ {
entered += num * 100; entered += num * 100;
enterIdx++;
} }
else if (enterIdx == 2) else if (oldEnterIdx == 2)
{ {
entered += num * 10; entered += num * 10;
enterIdx++;
}
else if (enterIdx == 3)
{
entered = -1;
enterIdx = 0;
keyManager.unregisterKeyListener(keyListener);
} }
} }
} }

View File

@@ -448,9 +448,7 @@ public class SpellbookPlugin extends Plugin
} }
// CHECKSTYLE:OFF // CHECKSTYLE:OFF
Collection<Spell> gson = GSON.fromJson(cfg, new TypeToken<List<Spell>>() Collection<Spell> gson = GSON.fromJson(cfg, new TypeToken<List<Spell>>() {}.getType());
{
}.getType());
// CHECKSTYLE:ON // CHECKSTYLE:ON
gson.stream().filter(Objects::nonNull).forEach(s -> spells.put(s.getWidget(), s)); gson.stream().filter(Objects::nonNull).forEach(s -> spells.put(s.getWidget(), s));
@@ -465,7 +463,7 @@ public class SpellbookPlugin extends Plugin
private void saveSpells() private void saveSpells()
{ {
if (spells.isEmpty()) if (spells.isEmpty() || tmp == null || tmp.isEmpty())
{ {
return; return;
} }

View File

@@ -1,5 +1,7 @@
/* /*
* Copyright (c) 2018, https://runelitepl.us * Copyright (c) 2018, https://runelitepl.us
* Copyright (c) 2019, Infinitay <https://github.com/Infinitay>
*
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -24,45 +26,85 @@
*/ */
package net.runelite.client.plugins.vorkath; package net.runelite.client.plugins.vorkath;
import lombok.Getter; import lombok.Data;
import lombok.Setter; import lombok.extern.slf4j.Slf4j;
import net.runelite.api.NPC; import net.runelite.api.NPC;
@Data
@Slf4j
public class Vorkath public class Vorkath
{ {
static final int ATTACKS_PER_SWITCH = 6; static final int ATTACKS_PER_SWITCH = 6;
static final int FIRE_BALL_ATTACKS = 25;
enum AttackStyle private NPC vorkath;
private VorkathAttack lastAttack;
private Phase currentPhase;
private Phase nextPhase;
private Phase lastPhase;
private int attacksLeft;
enum Phase
{ {
MAGERANGE, UNKNOWN,
ICE,
ACID, ACID,
SPECIAL FIRE_BALL,
SPAWN
} }
@Getter public Vorkath(NPC vorkath)
private NPC npc;
@Getter
@Setter
private int phase;
@Getter
@Setter
private int attacksUntilSwitch;
@Getter
@Setter
private int lastTickAnimation;
@Getter
@Setter
private boolean icePhaseAttack;
public Vorkath(NPC npc)
{ {
this.npc = npc; this.vorkath = vorkath;
this.attacksUntilSwitch = ATTACKS_PER_SWITCH; this.attacksLeft = ATTACKS_PER_SWITCH;
this.phase = 0; this.currentPhase = Phase.UNKNOWN;
this.nextPhase = Phase.UNKNOWN;
this.lastPhase = Phase.UNKNOWN;
log.debug("[Vorkath] Created Vorkath: {}", this);
}
/**
* Updates the existing Vorkath object depending on the new phase it is currently on
*
* @param newPhase the new phase Vorkath is current on
*/
public void updatePhase(Phase newPhase)
{
Phase oldLastPhase = this.lastPhase;
Phase oldCurrentPhase = this.currentPhase;
Phase oldNextPhase = this.currentPhase;
int oldAttacksLeft = this.attacksLeft;
this.lastPhase = this.currentPhase;
this.currentPhase = newPhase;
switch (newPhase)
{
case ACID:
this.nextPhase = Phase.FIRE_BALL;
break;
case FIRE_BALL:
this.nextPhase = Phase.SPAWN;
break;
case SPAWN:
this.nextPhase = Phase.ACID;
break;
default:
this.nextPhase = Phase.UNKNOWN;
break;
}
if (this.currentPhase == Phase.FIRE_BALL)
{
this.attacksLeft = FIRE_BALL_ATTACKS;
}
else
{
this.attacksLeft = ATTACKS_PER_SWITCH;
}
log.debug("[Vorkath] Update! Last Phase: {}->{}, Current Phase: {}->{}, Next Phase: {}->{}, Attacks: {}->{}",
oldLastPhase, this.lastPhase, oldCurrentPhase, this.currentPhase, oldNextPhase, this.nextPhase, oldAttacksLeft, this.attacksLeft);
} }
} }

View File

@@ -0,0 +1,133 @@
/*
* Copyright (c) 2019, Infinitay <https://github.com/Infinitay>
*
* 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.plugins.vorkath;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
import lombok.AllArgsConstructor;
import lombok.Getter;
import net.runelite.api.AnimationID;
import net.runelite.api.ProjectileID;
@AllArgsConstructor
@Getter
public enum VorkathAttack
{
/**
* Vorkath's melee attack (see VorkathPlugin#onAnimationChanged)
*/
SLASH_ATTACK(AnimationID.VORKATH_SLASH_ATTACK, -1),
/**
* Vorkath's dragon breath attack
*/
FIRE_BREATH(AnimationID.VORKATH_ATTACK, ProjectileID.VORKATH_DRAGONBREATH),
/**
* Vorkath's dragon breath attack causing the player's active prayers to be deactivated
*/
PRAYER_BREATH(AnimationID.VORKATH_ATTACK, ProjectileID.VORKATH_PRAYER_DISABLE),
/**
* Vorkath's dragon breath attack causing the player to become poisoned with venom
*/
VENOM_BREATH(AnimationID.VORKATH_ATTACK, ProjectileID.VORKATH_VENOM),
/**
* Vorkath's ranged attack
*/
SPIKE(AnimationID.VORKATH_ATTACK, ProjectileID.VORKATH_RANGED),
/**
* Vorkath's magic attack
*/
ICE(AnimationID.VORKATH_ATTACK, ProjectileID.VORKATH_MAGIC),
/**
* Vorkath's aoe fire bomb attack (3x3 from where player was originally standing)
*/
FIRE_BOMB(AnimationID.VORKATH_FIRE_BOMB_OR_SPAWN_ATTACK, ProjectileID.VORKATH_BOMB_AOE),
/**
* Vorkath's aoe acid attacking, spewing acid across the instance
*/
ACID(AnimationID.VORKATH_ACID_ATTACK, ProjectileID.VORKATH_POISON_POOL_AOE),
/**
* Vorkath's fire ball attack that is fired during the acid phase, almost every tick for 25(?) attacks total
*/
FIRE_BALL(AnimationID.VORKATH_ACID_ATTACK, ProjectileID.VORKATH_TICK_FIRE_AOE),
/**
* Vorkath's dragon breath attack causing the player to be frozen during Zombified Spawn phase
*/
FREEZE_BREATH(AnimationID.VORKATH_ATTACK, ProjectileID.VORKATH_ICE),
/**
* Vorkath's spawning of a Zombified Spawn
*/
ZOMBIFIED_SPAWN(AnimationID.VORKATH_FIRE_BOMB_OR_SPAWN_ATTACK, ProjectileID.VORKATH_SPAWN_AOE);
private final int vorkathAnimationID;
private final int projectileID;
private static final Map<Integer, VorkathAttack> VORKATH_ATTACKS;
private static final Map<Integer, VorkathAttack> VORKATH_BASIC_ATTACKS;
static
{
ImmutableMap.Builder<Integer, VorkathAttack> builder = new ImmutableMap.Builder<>();
for (VorkathAttack vorkathAttack : values())
{
builder.put(vorkathAttack.getProjectileID(), vorkathAttack);
}
VORKATH_ATTACKS = builder.build();
}
static
{
ImmutableMap.Builder<Integer, VorkathAttack> builder = new ImmutableMap.Builder<>();
builder.put(FIRE_BREATH.getProjectileID(), FIRE_BREATH)
.put(PRAYER_BREATH.getProjectileID(), PRAYER_BREATH)
.put(VENOM_BREATH.getProjectileID(), VENOM_BREATH)
.put(SPIKE.getProjectileID(), SPIKE)
.put(ICE.getProjectileID(), ICE)
.put(FIRE_BOMB.getProjectileID(), FIRE_BOMB)
.put(FIRE_BALL.getProjectileID(), FIRE_BALL);
// FIRE_BOMB and FIRE_BALL are also basic attacks
// Although SLASH_ATTACK is a basic attack, we're going to handle it differently
VORKATH_BASIC_ATTACKS = builder.build();
}
/**
* @param projectileID id of projectile
* @return {@link VorkathAttack} associated with the specified projectile
*/
public static VorkathAttack getVorkathAttack(int projectileID)
{
return VORKATH_ATTACKS.get(projectileID);
}
/**
* @param projectileID
* @return true if the projectile id matches a {@link VorkathAttack#getProjectileID()} within {@link VorkathAttack#VORKATH_BASIC_ATTACKS},
* false otherwise
*/
public static boolean isBasicAttack(int projectileID)
{
return VORKATH_BASIC_ATTACKS.get(projectileID) != null;
}
}

View File

@@ -1,5 +1,7 @@
/* /*
* Copyright (c) 2018, https://runelitepl.us * Copyright (c) 2018, https://runelitepl.us
* Copyright (c) 2019, Infinitay <https://github.com/Infinitay>
*
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -59,20 +61,6 @@ public class VorkathOverlay extends Overlay
this.plugin = plugin; this.plugin = plugin;
} }
private BufferedImage getIcon(Vorkath.AttackStyle attackStyle)
{
switch (attackStyle)
{
case MAGERANGE:
return VorkathPlugin.MAGERANGE;
case ICE:
return VorkathPlugin.ICE;
case ACID:
return VorkathPlugin.ACID;
}
return null;
}
@Override @Override
public Dimension render(Graphics2D graphics) public Dimension render(Graphics2D graphics)
{ {
@@ -80,29 +68,17 @@ public class VorkathOverlay extends Overlay
{ {
Vorkath vorkath = plugin.getVorkath(); Vorkath vorkath = plugin.getVorkath();
LocalPoint localLocation = vorkath.getNpc().getLocalLocation(); LocalPoint localLocation = vorkath.getVorkath().getLocalLocation();
if (localLocation != null) if (localLocation != null)
{ {
Point point = Perspective.localToCanvas(client, localLocation, client.getPlane(), vorkath.getNpc().getLogicalHeight() + 16); Point point = Perspective.localToCanvas(client, localLocation, client.getPlane(), vorkath.getVorkath().getLogicalHeight() + 16);
if (point != null) if (point != null)
{ {
point = new Point(point.getX(), point.getY()); point = new Point(point.getX(), point.getY());
BufferedImage icon = null; BufferedImage currentPhaseIcon = getIcon(vorkath);
if (vorkath.getPhase() == 0)
{
icon = getIcon(Vorkath.AttackStyle.MAGERANGE);
}
else if (vorkath.getPhase() == 1)
{
icon = getIcon(Vorkath.AttackStyle.ACID);
}
else if (vorkath.getPhase() == 2)
{
icon = getIcon(Vorkath.AttackStyle.ICE);
}
int totalWidth = icon.getWidth() * OVERLAY_ICON_MARGIN; int totalWidth = currentPhaseIcon.getWidth() * OVERLAY_ICON_MARGIN;
int bgPadding = 8; int bgPadding = 8;
int currentPosX = 0; int currentPosX = 0;
@@ -110,32 +86,31 @@ public class VorkathOverlay extends Overlay
graphics.setColor(COLOR_ICON_BACKGROUND); graphics.setColor(COLOR_ICON_BACKGROUND);
graphics.fillOval( graphics.fillOval(
point.getX() - totalWidth / 2 + currentPosX - bgPadding, point.getX() - totalWidth / 2 + currentPosX - bgPadding,
point.getY() - icon.getHeight() / 2 - OVERLAY_ICON_DISTANCE - bgPadding, point.getY() - currentPhaseIcon.getHeight() / 2 - OVERLAY_ICON_DISTANCE - bgPadding,
icon.getWidth() + bgPadding * 2, currentPhaseIcon.getWidth() + bgPadding * 2,
icon.getHeight() + bgPadding * 2); currentPhaseIcon.getHeight() + bgPadding * 2);
graphics.setColor(COLOR_ICON_BORDER); graphics.setColor(COLOR_ICON_BORDER);
graphics.drawOval( graphics.drawOval(
point.getX() - totalWidth / 2 + currentPosX - bgPadding, point.getX() - totalWidth / 2 + currentPosX - bgPadding,
point.getY() - icon.getHeight() / 2 - OVERLAY_ICON_DISTANCE - bgPadding, point.getY() - currentPhaseIcon.getHeight() / 2 - OVERLAY_ICON_DISTANCE - bgPadding,
icon.getWidth() + bgPadding * 2, currentPhaseIcon.getWidth() + bgPadding * 2,
icon.getHeight() + bgPadding * 2); currentPhaseIcon.getHeight() + bgPadding * 2);
graphics.drawImage( graphics.drawImage(
icon, currentPhaseIcon,
point.getX() - totalWidth / 2 + currentPosX, point.getX() - totalWidth / 2 + currentPosX,
point.getY() - icon.getHeight() / 2 - OVERLAY_ICON_DISTANCE, point.getY() - currentPhaseIcon.getHeight() / 2 - OVERLAY_ICON_DISTANCE,
null); null);
graphics.setColor(COLOR_ICON_BORDER_FILL); graphics.setColor(COLOR_ICON_BORDER_FILL);
Arc2D.Double arc = new Arc2D.Double( Arc2D.Double arc = new Arc2D.Double(
point.getX() - totalWidth / 2 + currentPosX - bgPadding, point.getX() - totalWidth / 2 + currentPosX - bgPadding,
point.getY() - icon.getHeight() / 2 - OVERLAY_ICON_DISTANCE - bgPadding, point.getY() - currentPhaseIcon.getHeight() / 2 - OVERLAY_ICON_DISTANCE - bgPadding,
icon.getWidth() + bgPadding * 2, currentPhaseIcon.getWidth() + bgPadding * 2,
icon.getHeight() + bgPadding * 2, currentPhaseIcon.getHeight() + bgPadding * 2,
90.0, 90.0,
-360.0 * (Vorkath.ATTACKS_PER_SWITCH - -360.0 * getAttacksLeftProgress(),
vorkath.getAttacksUntilSwitch()) / Vorkath.ATTACKS_PER_SWITCH,
Arc2D.OPEN); Arc2D.OPEN);
graphics.draw(arc); graphics.draw(arc);
} }
@@ -144,4 +119,39 @@ public class VorkathOverlay extends Overlay
return null; return null;
} }
/**
* @param vorkath Vorkath object
* @return image of the current phase Vorkath is on
*/
private BufferedImage getIcon(Vorkath vorkath)
{
switch (vorkath.getCurrentPhase())
{
case UNKNOWN:
return VorkathPlugin.UNKNOWN;
case ACID:
return VorkathPlugin.ACID;
case FIRE_BALL:
return VorkathPlugin.FIRE_BALL;
case SPAWN:
return VorkathPlugin.SPAWN;
}
return null;
}
/**
* @return number of attacks Vorkath has left in the current phase
*/
private double getAttacksLeftProgress()
{
if (plugin.getVorkath().getCurrentPhase() != Vorkath.Phase.FIRE_BALL)
{
return (double) (Vorkath.ATTACKS_PER_SWITCH - plugin.getVorkath().getAttacksLeft()) / Vorkath.ATTACKS_PER_SWITCH;
}
else
{
return (double) (Vorkath.FIRE_BALL_ATTACKS - plugin.getVorkath().getAttacksLeft()) / Vorkath.FIRE_BALL_ATTACKS;
}
}
} }

View File

@@ -1,5 +1,7 @@
/* /*
* Copyright (c) 2018, https://runelitepl.us * Copyright (c) 2018, https://runelitepl.us
* Copyright (c) 2019, Infinitay <https://github.com/Infinitay>
*
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -24,25 +26,24 @@
*/ */
package net.runelite.client.plugins.vorkath; package net.runelite.client.plugins.vorkath;
import com.google.inject.Inject;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import javax.inject.Inject;
import lombok.Getter; import lombok.Getter;
import net.runelite.api.AnimationID; import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client; import net.runelite.api.Client;
import net.runelite.api.GameState;
import net.runelite.api.NPC; import net.runelite.api.NPC;
import net.runelite.api.NpcID; import net.runelite.api.NpcID;
import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.AnimationChanged;
import net.runelite.api.events.GameTick;
import net.runelite.api.events.NpcDespawned; import net.runelite.api.events.NpcDespawned;
import net.runelite.api.events.NpcSpawned; import net.runelite.api.events.NpcSpawned;
import net.runelite.client.callback.ClientThread; import net.runelite.api.events.ProjectileMoved;
import net.runelite.client.eventbus.Subscribe; import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.plugins.PluginType; import net.runelite.client.plugins.PluginType;
import net.runelite.client.ui.overlay.OverlayManager; import net.runelite.client.ui.overlay.OverlayManager;
import net.runelite.client.util.ImageUtil; import net.runelite.client.util.ImageUtil;
import org.apache.commons.lang3.ArrayUtils;
@PluginDescriptor( @PluginDescriptor(
name = "Vorkath Helper", name = "Vorkath Helper",
@@ -51,9 +52,11 @@ import net.runelite.client.util.ImageUtil;
type = PluginType.PVM, type = PluginType.PVM,
enabledByDefault = false enabledByDefault = false
) )
@Slf4j
public class VorkathPlugin extends Plugin public class VorkathPlugin extends Plugin
{ {
private static final int VORKATH_REGION = 9023;
@Inject @Inject
private Client client; private Client client;
@@ -66,156 +69,177 @@ public class VorkathPlugin extends Plugin
@Inject @Inject
private ZombifiedSpawnOverlay SpawnOverlay; private ZombifiedSpawnOverlay SpawnOverlay;
@Inject
private ClientThread clientThread;
@Getter @Getter
private Vorkath vorkath; private Vorkath vorkath;
@Getter @Getter
private ZombifiedSpawn spawn; private NPC zombifiedSpawn;
/**
* The last projectile's starting movement cycle
*/
private int lastProjectileCycle;
static final BufferedImage UNKNOWN;
static final BufferedImage ACID; static final BufferedImage ACID;
static final BufferedImage ICE; static final BufferedImage FIRE_BALL;
static final BufferedImage MAGERANGE; static final BufferedImage SPAWN;
static static
{ {
UNKNOWN = ImageUtil.getResourceStreamFromClass(VorkathPlugin.class, "magerange.png");
ACID = ImageUtil.getResourceStreamFromClass(VorkathPlugin.class, "acid.png"); ACID = ImageUtil.getResourceStreamFromClass(VorkathPlugin.class, "acid.png");
ICE = ImageUtil.getResourceStreamFromClass(VorkathPlugin.class, "ice.png"); FIRE_BALL = ImageUtil.getResourceStreamFromClass(VorkathPlugin.class, "fire_strike.png");
MAGERANGE = ImageUtil.getResourceStreamFromClass(VorkathPlugin.class, "magerange.png"); SPAWN = ImageUtil.getResourceStreamFromClass(VorkathPlugin.class, "ice.png");
}
@Override
protected void startUp()
{
overlayManager.add(overlay);
overlayManager.add(SpawnOverlay);
clientThread.invoke(this::reset);
}
@Override
protected void shutDown()
{
overlayManager.remove(overlay);
overlayManager.remove(SpawnOverlay);
}
private void reset()
{
this.vorkath = null;
for (NPC npc : client.getNpcs())
{
if (isNpcVorkath(npc.getId()))
{
this.vorkath = new Vorkath(npc);
}
else if (isNpcZombifiedSpawn(npc.getId()))
{
this.spawn = new ZombifiedSpawn(npc);
}
}
}
private static boolean isNpcVorkath(int npcId)
{
return npcId == NpcID.VORKATH ||
npcId == NpcID.VORKATH_8058 ||
npcId == NpcID.VORKATH_8059 ||
npcId == NpcID.VORKATH_8060 ||
npcId == NpcID.VORKATH_8061;
}
private static boolean isNpcZombifiedSpawn(int id)
{
return id == NpcID.ZOMBIFIED_SPAWN ||
id == NpcID.ZOMBIFIED_SPAWN_8063;
} }
@Subscribe @Subscribe
public void onNpcSpawned(NpcSpawned event) public void onNpcSpawned(NpcSpawned event)
{ {
NPC npc = event.getNpc(); if (isAtVorkath())
if (isNpcVorkath(npc.getId()))
{ {
this.vorkath = new Vorkath(npc); if (isVorkath(event.getNpc().getId()))
{
vorkath = new Vorkath(event.getNpc());
lastProjectileCycle = -1;
overlayManager.add(overlay);
} }
else if (isNpcZombifiedSpawn(npc.getId())) else if (isZombifiedSpawn(event.getNpc().getId()))
{ {
this.spawn = new ZombifiedSpawn(npc); zombifiedSpawn = event.getNpc();
overlayManager.add(SpawnOverlay);
}
} }
} }
@Subscribe @Subscribe
public void onNpcDespawned(NpcDespawned npcDespawned) public void onNpcDespawned(NpcDespawned event)
{ {
final NPC npc = npcDespawned.getNpc(); if (isAtVorkath())
if (this.vorkath != null)
{ {
if (npc.getId() == this.vorkath.getNpc().getId()) if (isVorkath(event.getNpc().getId()))
{ {
this.vorkath = null; vorkath = null;
reset(); lastProjectileCycle = -1;
overlayManager.remove(overlay);
} }
} else if (isZombifiedSpawn(event.getNpc().getId()))
if (this.spawn != null)
{ {
if (npc.getId() == this.spawn.getNpc().getId()) zombifiedSpawn = null;
{ overlayManager.remove(SpawnOverlay);
this.spawn = null;
} }
} }
} }
@Subscribe
public void onGameStateChanged(GameStateChanged event)
{
GameState gs = event.getGameState();
if (gs == GameState.LOGGING_IN ||
gs == GameState.CONNECTION_LOST ||
gs == GameState.HOPPING)
{
reset();
}
}
@Subscribe @Subscribe
public void onGameTick(GameTick event) public void onProjectileMoved(ProjectileMoved event)
{ {
if (vorkath != null) // Only capture initial projectile
if (!isAtVorkath() || event.getProjectile().getStartMovementCycle() == lastProjectileCycle)
{ {
int animationId = vorkath.getNpc().getAnimation(); return;
}
if (animationId != vorkath.getLastTickAnimation()) VorkathAttack vorkathAttack = VorkathAttack.getVorkathAttack(event.getProjectile().getId());
if (vorkathAttack != null)
{ {
if (animationId == AnimationID.VORKATH_ACID_ATTACK) /*log.debug("[Projectile ({})] Game Tick: {}, Game Cycle: {}, Starting Cyle: {} Last Cycle: {}, Initial Projectile?: {}",
vorkathAttack, client.getTickCount(), client.getGameCycle(), event.getProjectile().getStartMovementCycle(),
lastProjectileCycle, event.getProjectile().getStartMovementCycle() == client.getGameCycle());*/
if (VorkathAttack.isBasicAttack(vorkathAttack.getProjectileID()) && vorkath.getAttacksLeft() > 0)
{ {
vorkath.setPhase(2); vorkath.setAttacksLeft(vorkath.getAttacksLeft() - 1);
vorkath.setAttacksUntilSwitch(Vorkath.ATTACKS_PER_SWITCH);
} }
else if (animationId == AnimationID.VORKATH_ATTACK && vorkath.getAttacksUntilSwitch() == 0) else if (vorkathAttack == VorkathAttack.ACID)
{ {
vorkath.setPhase(1); vorkath.updatePhase(Vorkath.Phase.ACID);
vorkath.setAttacksUntilSwitch(Vorkath.ATTACKS_PER_SWITCH); // Sets the phase's progress indicator to done
//Vorkath does a bomb animation after the ice dragon breathe, we need to account for it vorkath.setAttacksLeft(0);
vorkath.setIcePhaseAttack(true);
} }
else if (animationId == AnimationID.VORKATH_ATTACK || animationId == AnimationID.VORKATH_FIRE_BOMB_ATTACK) else if (vorkathAttack == VorkathAttack.FIRE_BALL)
{ {
if (vorkath.isIcePhaseAttack()) vorkath.updatePhase(Vorkath.Phase.FIRE_BALL);
// Decrement to account for this fire ball
vorkath.setAttacksLeft(vorkath.getAttacksLeft() - 1);
}
else if (vorkathAttack == VorkathAttack.FREEZE_BREATH && vorkath.getLastAttack() != VorkathAttack.ZOMBIFIED_SPAWN)
{ {
vorkath.setIcePhaseAttack(false); // Filters out second invisible freeze attack that is immediately after the Zombified Spawn
vorkath.updatePhase(Vorkath.Phase.SPAWN);
// Sets progress of the phase to half
vorkath.setAttacksLeft(vorkath.getAttacksLeft() - (vorkath.getAttacksLeft() / 2));
}
else if (vorkathAttack == VorkathAttack.ZOMBIFIED_SPAWN || (vorkath.getLastAttack() == VorkathAttack.ZOMBIFIED_SPAWN))
{
// Also consumes the second invisible freeze attack that is immediately after the Zombified Spawn
// Sets progress of the phase to done as there are no more attacks within this phase
vorkath.setAttacksLeft(0);
} }
else else
{ {
vorkath.setAttacksUntilSwitch(vorkath.getAttacksUntilSwitch() - 1); // Vorkath fired a basic attack AND there are no more attacks left, typically after phases are over
vorkath.updatePhase(vorkath.getNextPhase());
// Decrement to account for this basic attack
vorkath.setAttacksLeft(vorkath.getAttacksLeft() - 1);
} }
log.debug("[Vorkath ({})] {}", vorkathAttack, vorkath);
vorkath.setLastAttack(vorkathAttack);
lastProjectileCycle = event.getProjectile().getStartMovementCycle();
} }
} }
vorkath.setLastTickAnimation(animationId); @Subscribe
public void onAnimationChanged(AnimationChanged event)
{
if (isAtVorkath() && vorkath != null && event.getActor().equals(vorkath.getVorkath())
&& event.getActor().getAnimation() == VorkathAttack.SLASH_ATTACK.getVorkathAnimationID())
{
if (vorkath.getAttacksLeft() > 0)
{
vorkath.setAttacksLeft(vorkath.getAttacksLeft() - 1);
}
else
{
// No more attacks left, typically after phases are over
vorkath.updatePhase(vorkath.getNextPhase());
// Decrement to account for this basic attack
vorkath.setAttacksLeft(vorkath.getAttacksLeft() - 1);
}
log.debug("[Vorkath (SLASH_ATTACK)] {}", vorkath);
} }
} }
/**
* @return true if the player is in the Vorkath region, false otherwise
*/
private boolean isAtVorkath()
{
return ArrayUtils.contains(client.getMapRegions(), VORKATH_REGION);
}
/**
* @param npcID
* @return true if the npc is Vorkath, false otherwise
*/
private boolean isVorkath(int npcID)
{
// Could be done with a a simple name check instead...
return npcID == NpcID.VORKATH ||
npcID == NpcID.VORKATH_8058 ||
npcID == NpcID.VORKATH_8059 ||
npcID == NpcID.VORKATH_8060 ||
npcID == NpcID.VORKATH_8061;
}
/**
* @param npcID
* @return true if the npc is a Zombified Spawn, otherwise false
*/
private boolean isZombifiedSpawn(int npcID)
{
// Could be done with a a simple name check instead...
return npcID == NpcID.ZOMBIFIED_SPAWN ||
npcID == NpcID.ZOMBIFIED_SPAWN_8063;
}
} }

View File

@@ -48,10 +48,9 @@ public class ZombifiedSpawnOverlay extends Overlay
@Override @Override
public Dimension render(Graphics2D graphics) public Dimension render(Graphics2D graphics)
{ {
if (plugin.getSpawn() != null) if (plugin.getZombifiedSpawn() != null)
{ {
ZombifiedSpawn spawn = plugin.getSpawn(); OverlayUtil.renderActorOverlayImage(graphics, plugin.getZombifiedSpawn(), VorkathPlugin.SPAWN, Color.green, 10);
OverlayUtil.renderActorOverlayImage(graphics, spawn.getNpc(), VorkathPlugin.ICE, Color.green, 10);
} }
return null; return null;

View File

@@ -54,7 +54,9 @@ import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import static net.runelite.client.RuneLite.RUNELITE_DIR; import static net.runelite.client.RuneLite.RUNELITE_DIR;
import static net.runelite.client.rs.ClientUpdateCheckMode.AUTO;
import static net.runelite.client.rs.ClientUpdateCheckMode.CUSTOM; import static net.runelite.client.rs.ClientUpdateCheckMode.CUSTOM;
import static net.runelite.client.rs.ClientUpdateCheckMode.VANILLA;
import net.runelite.http.api.RuneLiteAPI; import net.runelite.http.api.RuneLiteAPI;
import okhttp3.Request; import okhttp3.Request;
import okhttp3.Response; import okhttp3.Response;
@@ -63,7 +65,8 @@ import okhttp3.Response;
@Singleton @Singleton
public class ClientLoader public class ClientLoader
{ {
private static final File CUSTOMFILE = new File("./injected-client/target/injected-client-1.0-SNAPSHOT.jar"); private static final File LOCAL_INJECTED_CLIENT = new File("./injected-client/target/injected-client-" + RuneLiteAPI.getVersion() + ".jar");
private static final File INJECTED_CLIENT = new File(RUNELITE_DIR + "/injected-client.jar");
private final ClientConfigLoader clientConfigLoader; private final ClientConfigLoader clientConfigLoader;
private ClientUpdateCheckMode updateCheckMode; private ClientUpdateCheckMode updateCheckMode;
public static boolean useLocalInjected = false; public static boolean useLocalInjected = false;
@@ -79,7 +82,6 @@ public class ClientLoader
public Applet load() public Applet load()
{ {
updateCheckMode = CUSTOM;
try try
{ {
Manifest manifest = new Manifest(); Manifest manifest = new Manifest();
@@ -87,6 +89,8 @@ public class ClientLoader
RSConfig config = clientConfigLoader.fetch(); RSConfig config = clientConfigLoader.fetch();
Map<String, byte[]> zipFile = new HashMap<>(); Map<String, byte[]> zipFile = new HashMap<>();
if (updateCheckMode == VANILLA)
{ {
Certificate[] jagexCertificateChain = getJagexCertificateChain(); Certificate[] jagexCertificateChain = getJagexCertificateChain();
String codebase = config.getCodeBase(); String codebase = config.getCodeBase();
@@ -140,61 +144,27 @@ public class ClientLoader
} }
} }
} }
else if (updateCheckMode == CUSTOM || useLocalInjected)
if (updateCheckMode == CUSTOM) {
log.info("Loading injected client from {}", LOCAL_INJECTED_CLIENT.getAbsolutePath());
loadJar(zipFile, LOCAL_INJECTED_CLIENT);
}
else if (updateCheckMode == AUTO)
{ {
URL url = new URL("https://raw.githubusercontent.com/runelite-extended/maven-repo/master/live/injected-client.jar"); URL url = new URL("https://raw.githubusercontent.com/runelite-extended/maven-repo/master/live/injected-client.jar");
ReadableByteChannel readableByteChannel = Channels.newChannel(url.openStream()); ReadableByteChannel readableByteChannel = Channels.newChannel(url.openStream());
File LOCAL_INJECTED_CLIENT = new File("./injected-client/target/injected-client-" + RuneLiteAPI.getVersion() + ".jar");
File INJECTED_CLIENT = new File(RUNELITE_DIR + "/injected-client.jar");
INJECTED_CLIENT.mkdirs(); INJECTED_CLIENT.mkdirs();
if (INJECTED_CLIENT.exists())
{ if (!INJECTED_CLIENT.exists() || getFileSize(INJECTED_CLIENT.toURI().toURL()) != getFileSize(url))
if (getFileSize(INJECTED_CLIENT.toURI().toURL()) != getFileSize(url))
{ {
log.info("{} injected client", INJECTED_CLIENT.exists() ? "Updating" : "Initializing");
INJECTED_CLIENT.delete(); INJECTED_CLIENT.delete();
INJECTED_CLIENT.createNewFile(); INJECTED_CLIENT.createNewFile();
System.out.println("Updating Injected Client");
updateInjectedClient(readableByteChannel); updateInjectedClient(readableByteChannel);
} }
}
else
{
INJECTED_CLIENT.createNewFile();
System.out.println("Initializing Inject Client");
updateInjectedClient(readableByteChannel);
}
JarInputStream fis;
if (useLocalInjected)
{
fis = new JarInputStream(new FileInputStream(LOCAL_INJECTED_CLIENT));
}
else
{
fis = new JarInputStream(new FileInputStream(INJECTED_CLIENT));
}
byte[] tmp = new byte[4096];
ByteArrayOutputStream buffer = new ByteArrayOutputStream(756 * 1024);
for (; ; )
{
JarEntry metadata = fis.getNextJarEntry();
if (metadata == null)
{
break;
}
buffer.reset(); log.info("Loading injected client from {}", INJECTED_CLIENT.getAbsolutePath());
for (; ; ) loadJar(zipFile, INJECTED_CLIENT);
{
int n = fis.read(tmp);
if (n <= -1)
{
break;
}
buffer.write(tmp, 0, n);
}
zipFile.replace(metadata.getName(), buffer.toByteArray());
}
} }
String initialClass = config.getInitialClass(); String initialClass = config.getInitialClass();
@@ -222,7 +192,7 @@ public class ClientLoader
if (rs instanceof Client) if (rs instanceof Client)
{ {
log.info("client-patch {}", "420 blaze it RL pricks"); log.info("client-patch 420 blaze it RL pricks");
} }
return rs; return rs;
@@ -241,7 +211,7 @@ public class ClientLoader
} }
} }
private static int getFileSize(URL url) private static int getFileSize(URL url) throws IOException
{ {
URLConnection conn = null; URLConnection conn = null;
try try
@@ -254,10 +224,6 @@ public class ClientLoader
conn.getInputStream(); conn.getInputStream();
return conn.getContentLength(); return conn.getContentLength();
} }
catch (IOException e)
{
throw new RuntimeException(e);
}
finally finally
{ {
if (conn instanceof HttpURLConnection) if (conn instanceof HttpURLConnection)
@@ -267,19 +233,11 @@ public class ClientLoader
} }
} }
private void updateInjectedClient(ReadableByteChannel readableByteChannel) private void updateInjectedClient(ReadableByteChannel readableByteChannel) throws IOException
{
File INJECTED_CLIENT = new File(RUNELITE_DIR, "injected-client.jar");
try
{ {
FileOutputStream fileOutputStream = new FileOutputStream(INJECTED_CLIENT); FileOutputStream fileOutputStream = new FileOutputStream(INJECTED_CLIENT);
fileOutputStream.getChannel() fileOutputStream.getChannel()
.transferFrom(readableByteChannel, 0, Long.MAX_VALUE); .transferFrom(readableByteChannel, 0, Integer.MAX_VALUE);
}
catch (IOException e)
{
e.printStackTrace();
}
} }
private static Certificate[] getJagexCertificateChain() throws CertificateException private static Certificate[] getJagexCertificateChain() throws CertificateException
@@ -288,4 +246,31 @@ public class ClientLoader
Collection<? extends Certificate> certificates = certificateFactory.generateCertificates(ClientLoader.class.getResourceAsStream("jagex.crt")); Collection<? extends Certificate> certificates = certificateFactory.generateCertificates(ClientLoader.class.getResourceAsStream("jagex.crt"));
return certificates.toArray(new Certificate[0]); return certificates.toArray(new Certificate[0]);
} }
private static void loadJar(Map<String, byte[]> toMap, File fromFile) throws IOException
{
JarInputStream fis = new JarInputStream(new FileInputStream(fromFile));
byte[] tmp = new byte[4096];
ByteArrayOutputStream buffer = new ByteArrayOutputStream(756 * 1024);
for (; ; )
{
JarEntry metadata = fis.getNextJarEntry();
if (metadata == null)
{
break;
}
buffer.reset();
for (; ; )
{
int n = fis.read(tmp);
if (n <= -1)
{
break;
}
buffer.write(tmp, 0, n);
}
toMap.put(metadata.getName(), buffer.toByteArray());
}
}
} }

View File

@@ -130,7 +130,7 @@ public class RuneLiteSplashScreen
panel.add(version, versionConstraints); panel.add(version, versionConstraints);
// version // version
final JLabel litVersion = new JLabel("Plus Version : PRE-" + RuneLite.RUNELIT_VERSION); final JLabel litVersion = new JLabel("Plus Version : " + RuneLite.RUNELIT_VERSION);
litVersion.setForeground(Color.GREEN); litVersion.setForeground(Color.GREEN);
litVersion.setFont(FontManager.getRunescapeSmallFont()); litVersion.setFont(FontManager.getRunescapeSmallFont());
litVersion.setForeground(litVersion.getForeground().darker()); litVersion.setForeground(litVersion.getForeground().darker());

View File

@@ -1,10 +1,9 @@
package net.runelite.client.util.bootstrap; package net.runelite.client.util.bootstrap;
public class Artifact { public class Artifact
{
String hash; String hash;
String name; String name;
String path; String path;
String size; String size;
} }

View File

@@ -1,24 +1,19 @@
package net.runelite.client.util.bootstrap; package net.runelite.client.util.bootstrap;
import net.runelite.http.api.RuneLiteAPI;
import sun.misc.BASE64Encoder;
import javax.xml.bind.DatatypeConverter;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.ObjectOutputStream; import java.io.ObjectOutputStream;
import java.io.Serializable; import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.security.DigestInputStream; import java.security.DigestInputStream;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import javax.xml.bind.DatatypeConverter;
import net.runelite.http.api.RuneLiteAPI;
public class Bootstrap { public class Bootstrap
{
Artifact[] artifacts = getArtifacts(); Artifact[] artifacts = getArtifacts();
Client client = new Client(); Client client = new Client();
String[] clientJvm9Arguments = new String[]{ String[] clientJvm9Arguments = new String[]{
@@ -49,10 +44,75 @@ public class Bootstrap {
"-XX:+UseParNewGC", "-XX:+UseParNewGC",
"-Djna.nosys=true"}; "-Djna.nosys=true"};
public Bootstrap(){} public Bootstrap()
{
}
public Artifact[] getArtifacts() { public static String getChecksumObject(Serializable object) throws IOException, NoSuchAlgorithmException
try { {
ByteArrayOutputStream baos = null;
ObjectOutputStream oos = null;
try
{
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
oos.writeObject(object);
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] thedigest = md.digest(baos.toByteArray());
return DatatypeConverter.printHexBinary(thedigest);
}
finally
{
oos.close();
baos.close();
}
}
private static String getChecksumFile(String filepath) throws IOException
{
System.out.println("Generating Hash for " + filepath);
MessageDigest md = null;
try
{
md = MessageDigest.getInstance("SHA-256");
}
catch (Exception e)
{
e.printStackTrace();
}
try (DigestInputStream dis = new DigestInputStream(new FileInputStream(filepath), md))
{
while (dis.read() != -1)
{
//empty loop to clear the data
}
md = dis.getMessageDigest();
}
catch (Exception e)
{
e.printStackTrace();
}
return bytesToHex(md.digest());
}
private static String bytesToHex(byte[] hashInBytes)
{
StringBuilder sb = new StringBuilder();
for (byte b : hashInBytes)
{
sb.append(String.format("%02x", b));
}
return sb.toString();
}
public Artifact[] getArtifacts()
{
try
{
artifacts = new Artifact[42]; artifacts = new Artifact[42];
//Static artifacts //Static artifacts
@@ -268,59 +328,16 @@ public class Bootstrap {
artifacts[37].hash = getChecksumFile("./http-api/target/" + artifacts[37].name); artifacts[37].hash = getChecksumFile("./http-api/target/" + artifacts[37].name);
artifacts[37].path = "https://raw.githubusercontent.com/runelite-extended/maven-repo/master/live/" + artifacts[37].name; artifacts[37].path = "https://raw.githubusercontent.com/runelite-extended/maven-repo/master/live/" + artifacts[37].name;
artifacts[37].size = Long.toString(getFileSize("./http-api/target/" + artifacts[37].name)); artifacts[37].size = Long.toString(getFileSize("./http-api/target/" + artifacts[37].name));
} catch (IOException e) { }
catch (IOException e)
{
e.printStackTrace(); e.printStackTrace();
} }
return artifacts; return artifacts;
} }
private long getFileSize(String fileLocation)
{
public static String getChecksumObject(Serializable object) throws IOException, NoSuchAlgorithmException {
ByteArrayOutputStream baos = null;
ObjectOutputStream oos = null;
try {
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
oos.writeObject(object);
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] thedigest = md.digest(baos.toByteArray());
return DatatypeConverter.printHexBinary(thedigest);
} finally {
oos.close();
baos.close();
}
}
private static String getChecksumFile(String filepath) throws IOException {
System.out.println("Generating Hash for "+filepath);
MessageDigest md = null;
try {
md = MessageDigest.getInstance("SHA-256");
} catch (Exception e) {
e.printStackTrace();
}
try (DigestInputStream dis = new DigestInputStream(new FileInputStream(filepath), md)) {
while (dis.read() != -1) ; //empty loop to clear the data
md = dis.getMessageDigest();
} catch (Exception e) {
e.printStackTrace();
}
return bytesToHex(md.digest());
}
private static String bytesToHex(byte[] hashInBytes) {
StringBuilder sb = new StringBuilder();
for (byte b : hashInBytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
private long getFileSize(String fileLocation) {
File f = new File(fileLocation); File f = new File(fileLocation);
return f.length(); return f.length();
} }

View File

@@ -2,22 +2,22 @@ package net.runelite.client.util.bootstrap;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException;
public class Bootstrapper { public class Bootstrapper
{
public static void main(String[] args) { public static void main(String[] args)
{
Gson gson = new GsonBuilder().disableHtmlEscaping().setPrettyPrinting().create(); Gson gson = new GsonBuilder().disableHtmlEscaping().setPrettyPrinting().create();
try { try
{
FileWriter fw = new FileWriter("./bootstrap.json"); FileWriter fw = new FileWriter("./bootstrap.json");
gson.toJson(new Bootstrap(), fw); gson.toJson(new Bootstrap(), fw);
fw.close(); fw.close();
} catch (Exception e) { }
catch (Exception e)
{
e.printStackTrace(); e.printStackTrace();
} }

View File

@@ -1,6 +1,7 @@
package net.runelite.client.util.bootstrap; package net.runelite.client.util.bootstrap;
public class Client { public class Client
{
String artifactId = "client"; String artifactId = "client";
String classifier = ""; String classifier = "";

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 B

View File

@@ -322,8 +322,11 @@ LABEL241:
iconst 0 ; iconst 0 ;
sconst "blockChatInput" ; sconst "blockChatInput" ;
runelite_callback ; runelite_callback ;
if_icmpeq LABEL247 ; don't add to input varcstr if_icmpeq SKIPSETVARC ; skip setting varc with input
set_varc_string 335 set_varc_string 335
jump LABEL247 ; jump over SKIPSETVARC
SKIPSETVARC:
pop_string ; pop message
LABEL247: LABEL247:
invoke 223 invoke 223
return return

View File

@@ -0,0 +1 @@
2A73E4C408881BB0EBDDE9BB05910C55F0313FA90BA907B722859E0183A713E7

View File

@@ -0,0 +1,492 @@
.id 653
.int_stack_count 19
.string_stack_count 0
.int_var_count 22
.string_var_count 0
iload 0
sconst "bankpin"
runelite_callback
iconst 3
if_icmpeq LABEL4
jump LABEL20
LABEL4:
sconst "Finally, the FOURTH digit."
iload 18
if_settext
sconst "*"
iload 14
if_settext
sconst "*"
iload 15
if_settext
sconst "*"
iload 16
if_settext
sconst "?"
iload 17
if_settext
jump LABEL128
LABEL20:
iload 0
iconst 2
if_icmpeq LABEL24
jump LABEL40
LABEL24:
sconst "Time for the THIRD digit."
iload 18
if_settext
sconst "*"
iload 14
if_settext
sconst "*"
iload 15
if_settext
sconst "?"
iload 16
if_settext
sconst "?"
iload 17
if_settext
jump LABEL128
LABEL40:
iload 0
iconst 1
if_icmpeq LABEL44
jump LABEL60
LABEL44:
sconst "Now click the SECOND digit."
iload 18
if_settext
sconst "*"
iload 14
if_settext
sconst "?"
iload 15
if_settext
sconst "?"
iload 16
if_settext
sconst "?"
iload 17
if_settext
jump LABEL128
LABEL60:
iload 0
iconst 0
if_icmpeq LABEL64
jump LABEL80
LABEL64:
sconst "First click the FIRST digit."
iload 18
if_settext
sconst "?"
iload 14
if_settext
sconst "?"
iload 15
if_settext
sconst "?"
iload 16
if_settext
sconst "?"
iload 17
if_settext
jump LABEL128
LABEL80:
sconst "Submitting..."
iload 18
if_settext
sconst "*"
iload 14
if_settext
sconst "*"
iload 15
if_settext
sconst "*"
iload 16
if_settext
sconst "*"
iload 17
if_settext
iload 4
cc_deleteall
iload 5
cc_deleteall
iload 6
cc_deleteall
iload 7
cc_deleteall
iload 8
cc_deleteall
iload 9
cc_deleteall
iload 10
cc_deleteall
iload 11
cc_deleteall
iload 12
cc_deleteall
iload 13
cc_deleteall
iconst -1
sconst ""
iload 2
if_setonop
iload 2
if_clearops
iconst -1
sconst ""
iload 3
if_setonop
iload 3
if_clearops
return
LABEL128:
iconst 10
define_array 73
iconst 0
iload 4
set_array_int
iconst 1
iload 5
set_array_int
iconst 2
iload 6
set_array_int
iconst 3
iload 7
set_array_int
iconst 4
iload 8
set_array_int
iconst 5
iload 9
set_array_int
iconst 6
iload 10
set_array_int
iconst 7
iload 11
set_array_int
iconst 8
iload 12
set_array_int
iconst 9
iload 13
set_array_int
iconst 0
istore 19
iconst -1
istore 20
iconst 20
istore 21
LABEL166:
iload 21
iconst 0
if_icmpgt LABEL170
jump LABEL188
LABEL170:
iload 21
iconst 1
sub
istore 21
iconst 9
random
istore 19
iconst 9
get_array_int
istore 20
iconst 9
iload 19
get_array_int
set_array_int
iload 19
iload 20
set_array_int
jump LABEL166
LABEL188:
iconst 0
get_array_int
iconst 0
iload 0
iload 1
iload 2
iload 3
iload 4
iload 5
iload 6
iload 7
iload 8
iload 9
iload 10
iload 11
iload 12
iload 13
iload 14
iload 15
iload 16
iload 17
iload 18
invoke 679
iconst 1
get_array_int
iconst 1
iload 0
iload 1
iload 2
iload 3
iload 4
iload 5
iload 6
iload 7
iload 8
iload 9
iload 10
iload 11
iload 12
iload 13
iload 14
iload 15
iload 16
iload 17
iload 18
invoke 679
iconst 2
get_array_int
iconst 2
iload 0
iload 1
iload 2
iload 3
iload 4
iload 5
iload 6
iload 7
iload 8
iload 9
iload 10
iload 11
iload 12
iload 13
iload 14
iload 15
iload 16
iload 17
iload 18
invoke 679
iconst 3
get_array_int
iconst 3
iload 0
iload 1
iload 2
iload 3
iload 4
iload 5
iload 6
iload 7
iload 8
iload 9
iload 10
iload 11
iload 12
iload 13
iload 14
iload 15
iload 16
iload 17
iload 18
invoke 679
iconst 4
get_array_int
iconst 4
iload 0
iload 1
iload 2
iload 3
iload 4
iload 5
iload 6
iload 7
iload 8
iload 9
iload 10
iload 11
iload 12
iload 13
iload 14
iload 15
iload 16
iload 17
iload 18
invoke 679
iconst 5
get_array_int
iconst 5
iload 0
iload 1
iload 2
iload 3
iload 4
iload 5
iload 6
iload 7
iload 8
iload 9
iload 10
iload 11
iload 12
iload 13
iload 14
iload 15
iload 16
iload 17
iload 18
invoke 679
iconst 6
get_array_int
iconst 6
iload 0
iload 1
iload 2
iload 3
iload 4
iload 5
iload 6
iload 7
iload 8
iload 9
iload 10
iload 11
iload 12
iload 13
iload 14
iload 15
iload 16
iload 17
iload 18
invoke 679
iconst 7
get_array_int
iconst 7
iload 0
iload 1
iload 2
iload 3
iload 4
iload 5
iload 6
iload 7
iload 8
iload 9
iload 10
iload 11
iload 12
iload 13
iload 14
iload 15
iload 16
iload 17
iload 18
invoke 679
iconst 8
get_array_int
iconst 8
iload 0
iload 1
iload 2
iload 3
iload 4
iload 5
iload 6
iload 7
iload 8
iload 9
iload 10
iload 11
iload 12
iload 13
iload 14
iload 15
iload 16
iload 17
iload 18
invoke 679
iconst 9
get_array_int
iconst 9
iload 0
iload 1
iload 2
iload 3
iload 4
iload 5
iload 6
iload 7
iload 8
iload 9
iload 10
iload 11
iload 12
iload 13
iload 14
iload 15
iload 16
iload 17
iload 18
invoke 679
iconst 1
iload 2
if_gettext
iload 2
if_setop
iconst 686
iconst 12345
iload 2
iload 3
iload 4
iload 5
iload 6
iload 7
iload 8
iload 9
iload 10
iload 11
iload 12
iload 13
iload 14
iload 15
iload 16
iload 17
iload 18
sconst "iIIIIIIIIIIIIIIIII"
iload 2
if_setonop
iconst 1
iload 3
if_gettext
iload 3
if_setop
iconst 686
iconst 54321
iload 2
iload 3
iload 4
iload 5
iload 6
iload 7
iload 8
iload 9
iload 10
iload 11
iload 12
iload 13
iload 14
iload 15
iload 16
iload 17
iload 18
sconst "iIIIIIIIIIIIIIIIII"
iload 3
if_setonop
return

View File

@@ -1,12 +1,9 @@
package net.runelite.mixins; package net.runelite.mixins;
import net.runelite.api.Model;
import net.runelite.api.Perspective;
import net.runelite.api.mixins.Inject; import net.runelite.api.mixins.Inject;
import net.runelite.api.mixins.Mixin; import net.runelite.api.mixins.Mixin;
import net.runelite.api.mixins.Shadow; import net.runelite.api.mixins.Shadow;
import net.runelite.rs.api.RSClient; import net.runelite.rs.api.RSClient;
import net.runelite.rs.api.RSModel;
/** /**
* Class to check clickboxes of models. Mostly refactored code from the client. * Class to check clickboxes of models. Mostly refactored code from the client.
@@ -14,19 +11,40 @@ import net.runelite.rs.api.RSModel;
@Mixin(RSClient.class) @Mixin(RSClient.class)
public abstract class ClickboxMixin implements RSClient public abstract class ClickboxMixin implements RSClient
{ {
@Shadow("client")
private static RSClient client;
private static final int MAX_ENTITES_AT_MOUSE = 1000; private static final int MAX_ENTITES_AT_MOUSE = 1000;
private static final int CLICKBOX_CLOSE = 50; private static final int CLICKBOX_CLOSE = 50;
private static final int CLICKBOX_FAR = 10000; private static final int CLICKBOX_FAR = 10000;
private static final int OBJECT_INTERACTION_FAR = 100; // Max distance, in tiles, from camera private static final int OBJECT_INTERACTION_FAR = 100; // Max distance, in tiles, from camera
@Inject @Inject
private static final int[] rl$modelViewportXs = new int[4700]; private static final int[] rl$modelViewportXs = new int[4700];
@Inject @Inject
private static final int[] rl$modelViewportYs = new int[4700]; private static final int[] rl$modelViewportYs = new int[4700];
@Shadow("client")
private static RSClient client;
@Inject
private static int rl$rot1(int var0, int var1, int var2, int var3)
{
return var0 * var2 + var3 * var1 >> 16;
}
@Inject
private static int rl$rot2(int var0, int var1, int var2, int var3)
{
return var2 * var1 - var3 * var0 >> 16;
}
@Inject
private static int rl$rot3(int var0, int var1, int var2, int var3)
{
return var0 * var2 - var3 * var1 >> 16;
}
@Inject
private static int rl$rot4(int var0, int var1, int var2, int var3)
{
return var3 * var0 + var2 * var1 >> 16;
}
@Inject @Inject
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) 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)
@@ -118,11 +136,8 @@ public abstract class ClickboxMixin implements RSClient
int n28 = rl$modelViewportXs[n12]; int n28 = rl$modelViewportXs[n12];
int n29 = rl$modelViewportXs[n10]; int n29 = rl$modelViewportXs[n10];
int n30 = rl$modelViewportXs[n24]; int n30 = rl$modelViewportXs[n24];
if (n25 != -5000 && n26 != -5000 && n27 != -5000 && (bl5 = (n23 = (n22 = rSModel.isClickable() ? 20 if (n25 != -5000 && n26 != -5000 && n27 != -5000 && (bl5 = ((n23 = (n22 = rSModel.isClickable() ? 20
: 5) + n11) < n28 && n23 < n29 && n23 < n30 ? false : 5) + n11) >= n28 || n23 >= n29 || n23 >= n30) && (((n23 = n11 - n22) <= n28 || n23 <= n29 || n23 <= n30) && (((n23 = n22 + n14) >= n25 || n23 >= n26 || n23 >= n27) && ((n23 = n14 - n22) <= n25 || n23 <= n26 || n23 <= n27)))))
: ((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); this.addHashAtMouse(l2);
return; return;
@@ -211,34 +226,6 @@ public abstract class ClickboxMixin implements RSClient
{ {
return false; return false;
} }
if (Math.abs(n39 * n23 - n38 * n24) <= n33 * n26 + n32 * n27) return Math.abs(n39 * n23 - n38 * n24) <= n33 * n26 + n32 * n27;
{
return true;
}
return false;
}
@Inject
private static int rl$rot1(int var0, int var1, int var2, int var3)
{
return var0 * var2 + var3 * var1 >> 16;
}
@Inject
private static int rl$rot2(int var0, int var1, int var2, int var3)
{
return var2 * var1 - var3 * var0 >> 16;
}
@Inject
private static int rl$rot3(int var0, int var1, int var2, int var3)
{
return var0 * var2 - var3 * var1 >> 16;
}
@Inject
private static int rl$rot4(int var0, int var1, int var2, int var3)
{
return var3 * var0 + var2 * var1 >> 16;
} }
} }

View File

@@ -24,21 +24,21 @@
*/ */
package net.runelite.mixins; package net.runelite.mixins;
import net.runelite.api.Model;
import net.runelite.api.Perspective;
import net.runelite.api.Point;
import net.runelite.api.model.Jarvis;
import net.runelite.api.model.Triangle;
import net.runelite.api.model.Vertex;
import java.awt.Polygon; import java.awt.Polygon;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import net.runelite.api.Model;
import net.runelite.api.Perspective;
import net.runelite.api.Point;
import net.runelite.api.mixins.Copy; import net.runelite.api.mixins.Copy;
import net.runelite.api.mixins.Inject; import net.runelite.api.mixins.Inject;
import net.runelite.api.mixins.MethodHook; import net.runelite.api.mixins.MethodHook;
import net.runelite.api.mixins.Mixin; import net.runelite.api.mixins.Mixin;
import net.runelite.api.mixins.Replace; import net.runelite.api.mixins.Replace;
import net.runelite.api.mixins.Shadow; import net.runelite.api.mixins.Shadow;
import net.runelite.api.model.Jarvis;
import net.runelite.api.model.Triangle;
import net.runelite.api.model.Vertex;
import net.runelite.rs.api.RSAnimation; import net.runelite.rs.api.RSAnimation;
import net.runelite.rs.api.RSClient; import net.runelite.rs.api.RSClient;
import net.runelite.rs.api.RSFrames; import net.runelite.rs.api.RSFrames;
@@ -77,9 +77,112 @@ public abstract class RSModelMixin implements RSModel
} }
@Inject @Inject
public boolean isClickable() { public boolean isClickable()
{
return isClickable; return isClickable;
}; }
@Inject
public void interpolateFrames(RSFrames frames, int frameId, RSFrames nextFrames, int nextFrameId, int interval, int intervalCount)
{
if (getVertexGroups() != null)
{
if (frameId != -1)
{
RSAnimation frame = frames.getFrames()[frameId];
RSSkeleton skin = frame.getSkin();
RSAnimation nextFrame = null;
if (nextFrames != null)
{
nextFrame = nextFrames.getFrames()[nextFrameId];
if (nextFrame.getSkin() != skin)
{
nextFrame = null;
}
}
client.setAnimOffsetX(0);
client.setAnimOffsetY(0);
client.setAnimOffsetZ(0);
interpolateFrames(skin, frame, nextFrame, interval, intervalCount);
resetBounds();
}
}
}
@Override
@Inject
public Polygon getConvexHull(int localX, int localY, int orientation, int tileHeight)
{
List<Vertex> vertices = getVertices();
// rotate vertices
for (int i = 0; i < vertices.size(); ++i)
{
Vertex v = vertices.get(i);
vertices.set(i, v.rotate(orientation));
}
List<Point> points = new ArrayList<Point>();
for (Vertex v : vertices)
{
// Compute canvas location of vertex
Point p = Perspective.localToCanvas(client,
localX - v.getX(),
localY - v.getZ(),
tileHeight + v.getY());
if (p != null)
{
points.add(p);
}
}
// Run Jarvis march algorithm
points = Jarvis.convexHull(points);
if (points == null)
{
return null;
}
// Convert to a polygon
Polygon p = new Polygon();
for (Point point : points)
{
p.addPoint(point.getX(), point.getY());
}
return p;
}
@Inject
@Override
public float[][] getFaceTextureUCoordinates()
{
return rl$faceTextureUCoordinates;
}
@Inject
@Override
public void setFaceTextureUCoordinates(float[][] faceTextureUCoordinates)
{
this.rl$faceTextureUCoordinates = faceTextureUCoordinates;
}
@Inject
@Override
public float[][] getFaceTextureVCoordinates()
{
return rl$faceTextureVCoordinates;
}
@Inject
@Override
public void setFaceTextureVCoordinates(float[][] faceTextureVCoordinates)
{
this.rl$faceTextureVCoordinates = faceTextureVCoordinates;
}
@MethodHook(value = "<init>", end = true) @MethodHook(value = "<init>", end = true)
@Inject @Inject
@@ -174,6 +277,48 @@ public abstract class RSModelMixin implements RSModel
return triangles; return triangles;
} }
@Inject
@Override
public int getSceneId()
{
return rl$sceneId;
}
@Inject
@Override
public void setSceneId(int sceneId)
{
this.rl$sceneId = sceneId;
}
@Inject
@Override
public int getBufferOffset()
{
return rl$bufferOffset;
}
@Inject
@Override
public void setBufferOffset(int bufferOffset)
{
rl$bufferOffset = bufferOffset;
}
@Inject
@Override
public int getUvBufferOffset()
{
return rl$uvBufferOffset;
}
@Inject
@Override
public void setUvBufferOffset(int bufferOffset)
{
rl$uvBufferOffset = bufferOffset;
}
@Copy("contourGround") @Copy("contourGround")
public abstract Model rs$contourGround(int[][] tileHeights, int packedX, int height, int packedY, boolean copy, int contouredGround); public abstract Model rs$contourGround(int[][] tileHeights, int packedX, int height, int packedY, boolean copy, int contouredGround);
@@ -201,36 +346,6 @@ public abstract class RSModelMixin implements RSModel
rsModel.setFaceTextureVCoordinates(rl$faceTextureVCoordinates); rsModel.setFaceTextureVCoordinates(rl$faceTextureVCoordinates);
} }
@Inject
public void interpolateFrames(RSFrames frames, int frameId, RSFrames nextFrames, int nextFrameId, int interval,
int intervalCount)
{
if (getVertexGroups() != null)
{
if (frameId != -1)
{
RSAnimation frame = frames.getFrames()[frameId];
RSSkeleton skin = frame.getSkin();
RSAnimation nextFrame = null;
if (nextFrames != null)
{
nextFrame = nextFrames.getFrames()[nextFrameId];
if (nextFrame.getSkin() != skin)
{
nextFrame = null;
}
}
client.setAnimOffsetX(0);
client.setAnimOffsetY(0);
client.setAnimOffsetZ(0);
interpolateFrames(skin, frame, nextFrame, interval, intervalCount);
resetBounds();
}
}
}
@Inject @Inject
public void interpolateFrames(RSSkeleton skin, RSAnimation frame, RSAnimation nextFrame, int interval, int intervalCount) public void interpolateFrames(RSSkeleton skin, RSAnimation frame, RSAnimation nextFrame, int interval, int intervalCount)
{ {
@@ -334,119 +449,4 @@ public abstract class RSModelMixin implements RSModel
} }
} }
} }
@Override
@Inject
public Polygon getConvexHull(int localX, int localY, int orientation, int tileHeight)
{
List<Vertex> vertices = getVertices();
// rotate vertices
for (int i = 0; i < vertices.size(); ++i)
{
Vertex v = vertices.get(i);
vertices.set(i, v.rotate(orientation));
}
List<Point> points = new ArrayList<Point>();
for (Vertex v : vertices)
{
// Compute canvas location of vertex
Point p = Perspective.localToCanvas(client,
localX - v.getX(),
localY - v.getZ(),
tileHeight + v.getY());
if (p != null)
{
points.add(p);
}
}
// Run Jarvis march algorithm
points = Jarvis.convexHull(points);
if (points == null)
{
return null;
}
// Convert to a polygon
Polygon p = new Polygon();
for (Point point : points)
{
p.addPoint(point.getX(), point.getY());
}
return p;
}
@Inject
@Override
public int getSceneId()
{
return rl$sceneId;
}
@Inject
@Override
public void setSceneId(int sceneId)
{
this.rl$sceneId = sceneId;
}
@Inject
@Override
public int getBufferOffset()
{
return rl$bufferOffset;
}
@Inject
@Override
public void setBufferOffset(int bufferOffset)
{
rl$bufferOffset = bufferOffset;
}
@Inject
@Override
public int getUvBufferOffset()
{
return rl$uvBufferOffset;
}
@Inject
@Override
public void setUvBufferOffset(int bufferOffset)
{
rl$uvBufferOffset = bufferOffset;
}
@Inject
@Override
public float[][] getFaceTextureUCoordinates()
{
return rl$faceTextureUCoordinates;
}
@Inject
@Override
public void setFaceTextureUCoordinates(float[][] faceTextureUCoordinates)
{
this.rl$faceTextureUCoordinates = faceTextureUCoordinates;
}
@Inject
@Override
public float[][] getFaceTextureVCoordinates()
{
return rl$faceTextureVCoordinates;
}
@Inject
@Override
public void setFaceTextureVCoordinates(float[][] faceTextureVCoordinates)
{
this.rl$faceTextureVCoordinates = faceTextureVCoordinates;
}
} }

View File

@@ -29,7 +29,6 @@ import net.runelite.api.Renderable;
import net.runelite.api.SceneTileModel; import net.runelite.api.SceneTileModel;
import net.runelite.api.SceneTilePaint; import net.runelite.api.SceneTilePaint;
import net.runelite.api.Tile; import net.runelite.api.Tile;
import net.runelite.api.coords.LocalPoint;
import net.runelite.api.hooks.DrawCallbacks; import net.runelite.api.hooks.DrawCallbacks;
import net.runelite.api.mixins.Copy; import net.runelite.api.mixins.Copy;
import net.runelite.api.mixins.Inject; import net.runelite.api.mixins.Inject;
@@ -702,26 +701,7 @@ public abstract class RSSceneMixin implements RSScene
@Inject @Inject
static void setTargetTile(int targetX, int targetY) static void setTargetTile(int targetX, int targetY)
{ {
final LocalPoint current = client.getLocalPlayer().getLocalLocation(); client.setSelectedSceneTileX(targetX);
client.setSelectedSceneTileY(targetY);
// Limit walk distance - https://math.stackexchange.com/a/85582
final int a = current.getSceneX();
final int b = current.getSceneY();
final int c = targetX;
final int d = targetY;
final int r = MAX_TARGET_DISTANCE;
final int t = (int) Math.hypot(a - c, b - d) - r;
int x = targetX;
int y = targetY;
if (t > 0)
{
x = (r * c + t * a) / (r + t);
y = (r * d + t * b) / (r + t);
}
client.setSelectedSceneTileX(x);
client.setSelectedSceneTileY(y);
} }
} }

View File

@@ -258,6 +258,11 @@ public abstract class RSWidgetMixin implements RSWidget
for (int i = 0; i < itemIds.length; ++i) for (int i = 0; i < itemIds.length; ++i)
{ {
if (itemIds[i] <= 0)
{
continue;
}
WidgetItem item = getWidgetItem(i); WidgetItem item = getWidgetItem(i);
if (item != null) if (item != null)
@@ -287,19 +292,17 @@ public abstract class RSWidgetMixin implements RSWidget
int itemId = itemIds[index]; int itemId = itemIds[index];
int itemQuantity = itemQuantities[index]; int itemQuantity = itemQuantities[index];
Point widgetCanvasLocation = getCanvasLocation(); if (columns <= 0)
if (itemId <= 0 || itemQuantity <= 0 || columns <= 0)
{ {
return null; return null;
} }
int row = index / columns; int row = index / columns;
int col = index % columns; int col = index % columns;
int itemX = widgetCanvasLocation.getX() + ((ITEM_SLOT_SIZE + xPitch) * col); int itemX = rl$x + ((ITEM_SLOT_SIZE + xPitch) * col);
int itemY = widgetCanvasLocation.getY() + ((ITEM_SLOT_SIZE + yPitch) * row); int itemY = rl$y + ((ITEM_SLOT_SIZE + yPitch) * row);
Rectangle bounds = new Rectangle(itemX - 1, itemY - 1, ITEM_SLOT_SIZE, ITEM_SLOT_SIZE); Rectangle bounds = new Rectangle(itemX, itemY, ITEM_SLOT_SIZE, ITEM_SLOT_SIZE);
return new WidgetItem(itemId - 1, itemQuantity, index, bounds, this); return new WidgetItem(itemId - 1, itemQuantity, index, bounds, this);
} }

View File

@@ -529,11 +529,11 @@ public interface RSClient extends RSGameShell, Client
@Import("mapDotSprites") @Import("mapDotSprites")
RSSprite[] getMapDots(); RSSprite[] getMapDots();
@Import("modIconSprites") @Import("AbstractFont_modIconSprites")
@Override @Override
RSIndexedSprite[] getModIcons(); RSIndexedSprite[] getModIcons();
@Import("modIconSprites") @Import("AbstractFont_modIconSprites")
void setRSModIcons(RSIndexedSprite[] modIcons); void setRSModIcons(RSIndexedSprite[] modIcons);
@Construct @Construct
@@ -995,4 +995,10 @@ public interface RSClient extends RSGameShell, Client
@Import("mouseRecorder") @Import("mouseRecorder")
RSMouseRecorder getMouseRecorder(); RSMouseRecorder getMouseRecorder();
@Import("selectedSpellName")
String getSelectedSpellName();
@Import("isSpellSelected")
boolean getIsSpellSelected();
} }

View File

@@ -18,7 +18,7 @@ public interface RSGroundItemPile extends ItemLayer
@Import("height") @Import("height")
int getHeight(); int getHeight();
@Import("third") @Import("first")
@Override @Override
RSEntity getBottom(); RSEntity getBottom();
@@ -26,7 +26,7 @@ public interface RSGroundItemPile extends ItemLayer
@Override @Override
RSEntity getMiddle(); RSEntity getMiddle();
@Import("first") @Import("third")
@Override @Override
RSEntity getTop(); RSEntity getTop();

View File

@@ -17,7 +17,7 @@ public interface RSItemDefinition extends ItemDefinition
@Override @Override
int getNote(); int getNote();
@Import("notedId") @Import("note")
@Override @Override
int getLinkedNoteId(); int getLinkedNoteId();

View File

@@ -12,19 +12,19 @@ public interface RSMessage extends MessageNode
@Import("type") @Import("type")
int getRSType(); int getRSType();
@Import("prefix") @Import("sender")
@Override @Override
String getName(); String getName();
@Import("prefix") @Import("sender")
@Override @Override
void setName(String name); void setName(String name);
@Import("sender") @Import("prefix")
@Override @Override
String getSender(); String getSender();
@Import("sender") @Import("prefix")
@Override @Override
void setSender(String sender); void setSender(String sender);

View File

@@ -107,7 +107,7 @@ public final class BoundaryObject {
} }
if(var0.equalsIgnoreCase("showcoord")) { if(var0.equalsIgnoreCase("showcoord")) {
class60.worldMap0.__bc = !class60.worldMap0.__bc; class60.worldMap0.showCoord = !class60.worldMap0.showCoord;
} }
if(var0.equalsIgnoreCase("fpson")) { if(var0.equalsIgnoreCase("fpson")) {

View File

@@ -994,8 +994,8 @@ public final class Client extends GameShell implements Usernamed {
@ObfuscatedGetter( @ObfuscatedGetter(
intValue = 1005832199 intValue = 1005832199
) )
@Export("__client_ho") @Export("cameraFollowHeight")
static int __client_ho; static int cameraFollowHeight;
@ObfuscatedName("hc") @ObfuscatedName("hc")
@ObfuscatedGetter( @ObfuscatedGetter(
intValue = -441913785 intValue = -441913785
@@ -1442,7 +1442,7 @@ public final class Client extends GameShell implements Usernamed {
__client_hi = 0; __client_hi = 0;
__client_ht = 0; __client_ht = 0;
oculusOrbState = 0; oculusOrbState = 0;
__client_ho = 50; cameraFollowHeight = 50;
__client_hc = 0; __client_hc = 0;
__client_hk = 0; __client_hk = 0;
__client_if = 0; __client_if = 0;
@@ -4281,7 +4281,7 @@ public final class Client extends GameShell implements Usernamed {
} }
} }
if(FriendSystem.method1868() && KeyHandler.KeyHandler_pressedKeys[82] && KeyHandler.KeyHandler_pressedKeys[81] && mouseWheelRotation != 0) { if(FriendSystem.jmodCheck() && KeyHandler.KeyHandler_pressedKeys[82] && KeyHandler.KeyHandler_pressedKeys[81] && mouseWheelRotation != 0) {
var3 = Canvas.localPlayer.plane - mouseWheelRotation; var3 = Canvas.localPlayer.plane - mouseWheelRotation;
if(var3 < 0) { if(var3 < 0) {
var3 = 0; var3 = 0;
@@ -4710,7 +4710,7 @@ public final class Client extends GameShell implements Usernamed {
int var8; int var8;
if(!isMenuOpen) { if(!isMenuOpen) {
if(__client_lq != -1) { if(__client_lq != -1) {
class39.method741(__client_lq, __client_ln); class39.drawMenuActionTextAt(__client_lq, __client_ln);
} }
} else { } else {
var1 = class25.menuX; var1 = class25.menuX;

View File

@@ -327,7 +327,8 @@ public class FriendSystem {
signature = "(B)Z", signature = "(B)Z",
garbageValue = "0" garbageValue = "0"
) )
public static boolean method1868() { @Export("jmodCheck")
public static boolean jmodCheck() {
return Client.rights >= 2; return Client.rights >= 2;
} }
} }

View File

@@ -76,10 +76,10 @@ public class OwnWorldComparator implements Comparator {
var3 = 0; var3 = 0;
} }
Client.__client_ho = var3; Client.cameraFollowHeight = var3;
return 1; return 1;
} else if(var0 == 5531) { } else if(var0 == 5531) {
Interpreter.Interpreter_intStack[++class179.Interpreter_intStackSize - 1] = Client.__client_ho; Interpreter.Interpreter_intStack[++class179.Interpreter_intStackSize - 1] = Client.cameraFollowHeight;
return 1; return 1;
} else { } else {
return 2; return 2;

View File

@@ -61,7 +61,7 @@ public class Skills {
var1.__g_428(getItemDefinition(var1.placeholderTemplate), getItemDefinition(var1.placeholder)); var1.__g_428(getItemDefinition(var1.placeholderTemplate), getItemDefinition(var1.placeholder));
} }
if(!class30.__ar_l && var1.isMembersOnly) { if(!class30.inMembersWorld && var1.isMembersOnly) {
var1.name = "Members object"; var1.name = "Members object";
var1.isTradable = false; var1.isTradable = false;
var1.groundActions = null; var1.groundActions = null;

View File

@@ -266,8 +266,8 @@ public class WorldMap {
@Export("mouseCoord") @Export("mouseCoord")
TileLocation mouseCoord; TileLocation mouseCoord;
@ObfuscatedName("bc") @ObfuscatedName("bc")
@Export("__bc") @Export("showCoord")
public boolean __bc; public boolean showCoord;
@ObfuscatedName("bo") @ObfuscatedName("bo")
@ObfuscatedSignature( @ObfuscatedSignature(
signature = "Lln;" signature = "Lln;"
@@ -332,7 +332,7 @@ public class WorldMap {
this.__bs = new int[]{1008, 1009, 1010, 1011, 1012}; this.__bs = new int[]{1008, 1009, 1010, 1011, 1012};
this.__bk = new HashSet(); this.__bk = new HashSet();
this.mouseCoord = null; this.mouseCoord = null;
this.__bc = false; this.showCoord = false;
this.__by = -1; this.__by = -1;
this.__bu = -1; this.__bu = -1;
this.__bm = -1; this.__bm = -1;
@@ -478,7 +478,7 @@ public class WorldMap {
if(this.mouseCoord != null && var3) { if(this.mouseCoord != null && var3) {
int var9; int var9;
int var10; int var10;
if(FriendSystem.method1868() && KeyHandler.KeyHandler_pressedKeys[82] && KeyHandler.KeyHandler_pressedKeys[81]) { if(FriendSystem.jmodCheck() && KeyHandler.KeyHandler_pressedKeys[82] && KeyHandler.KeyHandler_pressedKeys[81]) {
int var13 = this.mouseCoord.x; int var13 = this.mouseCoord.x;
var9 = this.mouseCoord.y; var9 = this.mouseCoord.y;
var10 = this.mouseCoord.plane; var10 = this.mouseCoord.plane;
@@ -801,7 +801,7 @@ public class WorldMap {
} }
this.__v_528(var1, var2, var3, var4, var8, var9); this.__v_528(var1, var2, var3, var4, var8, var9);
if(FriendSystem.method1868() && this.__bc && this.mouseCoord != null) { if(FriendSystem.jmodCheck() && this.showCoord && this.mouseCoord != null) {
this.font.draw("Coord: " + this.mouseCoord, Rasterizer2D.Rasterizer2D_xClipStart + 10, Rasterizer2D.Rasterizer2D_yClipStart + 20, 16776960, -1); this.font.draw("Coord: " + this.mouseCoord, Rasterizer2D.Rasterizer2D_xClipStart + 10, Rasterizer2D.Rasterizer2D_yClipStart + 20, 16776960, -1);
} }

View File

@@ -251,7 +251,7 @@ public class class171 {
Font var6 = ScriptEvent.fontPlain11; Font var6 = ScriptEvent.fontPlain11;
ItemDefinition.ItemDefinition_indexCache = var3; ItemDefinition.ItemDefinition_indexCache = var3;
ItemDefinition.ItemDefinition_modelIndexCache = var4; ItemDefinition.ItemDefinition_modelIndexCache = var4;
class30.__ar_l = var5; class30.inMembersWorld = var5;
class83.__cm_e = ItemDefinition.ItemDefinition_indexCache.__s_396(10); class83.__cm_e = ItemDefinition.ItemDefinition_indexCache.__s_396(10);
class204.__gx_n = var6; class204.__gx_n = var6;
IndexCache var7 = ObjectSound.indexCache2; IndexCache var7 = ObjectSound.indexCache2;

View File

@@ -28,8 +28,8 @@ public class class30 {
@Export("musicTrackArchiveId") @Export("musicTrackArchiveId")
public static int musicTrackArchiveId; public static int musicTrackArchiveId;
@ObfuscatedName("l") @ObfuscatedName("l")
@Export("__ar_l") @Export("inMembersWorld")
public static boolean __ar_l; public static boolean inMembersWorld;
@ObfuscatedName("bd") @ObfuscatedName("bd")
@ObfuscatedSignature( @ObfuscatedSignature(
signature = "[Lln;" signature = "[Lln;"

View File

@@ -40,9 +40,9 @@ public class class31 {
if(var0.__e_144() != Client.isMembersWorld) { if(var0.__e_144() != Client.isMembersWorld) {
Client.isMembersWorld = var0.__e_144(); Client.isMembersWorld = var0.__e_144();
boolean var1 = var0.__e_144(); boolean var1 = var0.__e_144();
if(var1 != class30.__ar_l) { if(var1 != class30.inMembersWorld) {
class72.method1780(); class72.method1780();
class30.__ar_l = var1; class30.inMembersWorld = var1;
} }
} }

View File

@@ -767,7 +767,8 @@ public class class39 extends class21 {
signature = "(IIB)V", signature = "(IIB)V",
garbageValue = "3" garbageValue = "3"
) )
static final void method741(int var0, int var1) { @Export("drawMenuActionTextAt")
static final void drawMenuActionTextAt(int var0, int var1) {
if(Client.menuOptionsCount >= 2 || Client.isItemSelected != 0 || Client.isSpellSelected) { if(Client.menuOptionsCount >= 2 || Client.isItemSelected != 0 || Client.isSpellSelected) {
if(Client.showMouseOverText) { if(Client.showMouseOverText) {
int var2 = Client.menuOptionsCount - 1; int var2 = Client.menuOptionsCount - 1;
@@ -790,10 +791,10 @@ public class class39 extends class21 {
} }
if(Client.menuOptionsCount > 2) { if(Client.menuOptionsCount > 2) {
var4 = var4 + BufferedFile.colorStartTag(16777215) + " " + '/' + " " + (Client.menuOptionsCount - 2) + " more options"; var4 = var4 + BufferedFile.colorStartTag(0xffffff) + " " + '/' + " " + (Client.menuOptionsCount - 2) + " more options";
} }
class2.fontBold12.drawRandomAlphaAndSpacing(var4, var0 + 4, var1 + 15, 16777215, 0, Client.cycle / 1000); class2.fontBold12.drawRandomAlphaAndSpacing(var4, var0 + 4, var1 + 15, 0xffffff, 0, Client.cycle / 1000);
} }
} }
} }

View File

@@ -1065,14 +1065,14 @@ public final class class54 {
Client.__client_ik += (var6 - Client.__client_ik) / 80; Client.__client_ik += (var6 - Client.__client_ik) / 80;
} }
MouseRecorder.__bu_hy = class32.getTileHeight(Canvas.localPlayer.x, Canvas.localPlayer.y, SoundSystem.plane) - Client.__client_ho; MouseRecorder.__bu_hy = class32.getTileHeight(Canvas.localPlayer.x, Canvas.localPlayer.y, SoundSystem.plane) - Client.cameraFollowHeight;
} else if(Client.oculusOrbState == 1) { } else if(Client.oculusOrbState == 1) {
if(Client.__client_ij && Canvas.localPlayer != null) { if(Client.__client_ij && Canvas.localPlayer != null) {
var0 = Canvas.localPlayer.pathX[0]; var0 = Canvas.localPlayer.pathX[0];
var1 = Canvas.localPlayer.pathY[0]; var1 = Canvas.localPlayer.pathY[0];
if(var0 >= 0 && var1 >= 0 && var0 < 104 && var1 < 104) { if(var0 >= 0 && var1 >= 0 && var0 < 104 && var1 < 104) {
MouseHandler.oculusOrbFocalPointX = Canvas.localPlayer.x; MouseHandler.oculusOrbFocalPointX = Canvas.localPlayer.x;
var2 = class32.getTileHeight(Canvas.localPlayer.x, Canvas.localPlayer.y, SoundSystem.plane) - Client.__client_ho; var2 = class32.getTileHeight(Canvas.localPlayer.x, Canvas.localPlayer.y, SoundSystem.plane) - Client.cameraFollowHeight;
if(var2 < MouseRecorder.__bu_hy) { if(var2 < MouseRecorder.__bu_hy) {
MouseRecorder.__bu_hy = var2; MouseRecorder.__bu_hy = var2;
} }

View File

@@ -1,3 +1,3 @@
#!/bin/bash #!/bin/bash
mvn clean install --settings travis/settings.xml mvn clean install -DskipTests --settings travis/settings.xml

View File

@@ -259,7 +259,8 @@ under the License.
<properties> <properties>
<maven.javadoc.skip>true</maven.javadoc.skip> <maven.javadoc.skip>true</maven.javadoc.skip>
<checkstyle.skip>false</checkstyle.skip> <checkstyle.skip>false</checkstyle.skip>
<archetype.test.skip>false</archetype.test.skip> <archetype.test.skip>true</archetype.test.skip>
<test.skip>true</test.skip>
</properties> </properties>
</profile> </profile>
</profiles> </profiles>