Remove object wrappers and use mixins to inject functionality

This causes hierarchy to be runelite-client -> runelite-api and
injected-client -> runescape-api -> runelite-api. The mixin injector
fufills the runelite-api interface with access to the runescape-api
interfaces. The mixins live in runelite-mixins and are not loaded within
the client.

Note the obfuscated client classes do not pass JVM verification on 7+,
so the mixins are currently set to target Java 6.
This commit is contained in:
Adam
2017-08-19 13:58:06 -04:00
parent 07c8442f22
commit 59552896ed
124 changed files with 2257 additions and 1814 deletions

View File

@@ -27,172 +27,34 @@ package net.runelite.api;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.image.BufferedImage;
import java.util.Objects;
import net.runelite.rs.api.CombatInfo1;
import net.runelite.rs.api.CombatInfo2;
import net.runelite.rs.api.CombatInfoList;
import net.runelite.rs.api.CombatInfoListHolder;
import net.runelite.rs.api.Node;
public abstract class Actor extends Renderable
public interface Actor extends Renderable
{
int getCombatLevel();
private final Client client;
private net.runelite.rs.api.Actor actor;
String getName();
public Actor(Client client, net.runelite.rs.api.Actor actor)
{
super(actor);
Actor getInteracting();
this.client = client;
this.actor = actor;
}
int getHealthRatio();
@Override
public int hashCode()
{
int hash = 5;
hash = 47 * hash + Objects.hashCode(this.client);
return hash;
}
int getHealth();
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
if (obj == null)
{
return false;
}
if (getClass() != obj.getClass())
{
return false;
}
final Actor other = (Actor) obj;
if (!Objects.equals(this.client, other.client))
{
return false;
}
return true;
}
Point getLocalLocation();
public abstract int getCombatLevel();
int getOrientation();
public abstract String getName();
int getAnimation();
public Actor getInteracting()
{
int i = actor.getInteracting();
if (i == -1)
{
return null;
}
int getGraphic();
if (i < 0x8000)
{
return client.getNpc(i);
}
int getModelHeight();
i -= 0x8000;
return client.getPlayer(i);
}
Polygon getCanvasTilePoly();
public int getHealthRatio()
{
CombatInfoList combatInfoList = actor.getCombatInfoList();
if (combatInfoList != null)
{
Node node = combatInfoList.getNode();
Node next = node.getNext();
if (next instanceof CombatInfoListHolder)
{
CombatInfoListHolder combatInfoListWrapper = (CombatInfoListHolder) next;
CombatInfoList combatInfoList1 = combatInfoListWrapper.getCombatInfo1();
Point getCanvasTextLocation(Graphics2D graphics, String text, int zOffset);
Node node2 = combatInfoList1.getNode();
Node next2 = node2.getNext();
if (next2 instanceof CombatInfo1)
{
CombatInfo1 combatInfo = (CombatInfo1) next2;
return combatInfo.getHealthRatio();
}
}
}
return -1;
}
Point getCanvasImageLocation(Graphics2D graphics, BufferedImage image, int zOffset);
public int getHealth()
{
CombatInfoList combatInfoList = actor.getCombatInfoList();
if (combatInfoList != null)
{
Node node = combatInfoList.getNode();
Node next = node.getNext();
if (next instanceof CombatInfoListHolder)
{
CombatInfoListHolder combatInfoListWrapper = (CombatInfoListHolder) next;
CombatInfo2 cf = combatInfoListWrapper.getCombatInfo2();
return cf.getHealthScale();
}
}
return -1;
}
public Point getLocalLocation()
{
return new Point(getX(), getY());
}
private int getX()
{
return actor.getX();
}
private int getY()
{
return actor.getY();
}
public int getOrientation()
{
return actor.getOrientation();
}
public int getAnimation()
{
return actor.getAnimation();
}
public int getGraphic()
{
return actor.getGraphic();
}
public int getModelHeight()
{
return actor.getModelHeight();
}
public Polygon getCanvasTilePoly()
{
return Perspective.getCanvasTilePoly(client, getLocalLocation());
}
public Point getCanvasTextLocation(Graphics2D graphics, String text, int zOffset)
{
return Perspective.getCanvasTextLocation(client, graphics, getLocalLocation(), text, zOffset);
}
public Point getCanvasImageLocation(Graphics2D graphics, BufferedImage image, int zOffset)
{
return Perspective.getCanvasImageLocation(client, graphics, getLocalLocation(), image, zOffset);
}
public Point getMinimapLocation()
{
return Perspective.worldToMiniMap(client, getX(), getY());
}
Point getMinimapLocation();
}

View File

@@ -25,396 +25,122 @@
package net.runelite.api;
import java.awt.Canvas;
import java.util.Arrays;
import java.util.Objects;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetInfo;
import net.runelite.rs.api.ItemComposition;
public class Client
public interface Client
{
private final net.runelite.rs.api.Client client;
public Client(net.runelite.rs.api.Client client)
{
this.client = client;
}
public Player getLocalPlayer()
{
if (client.getLocalPlayer() == null)
{
return null;
}
return new Player(this, client.getLocalPlayer());
}
public NPC[] getNpcs()
{
return Arrays.stream(client.getCachedNPCs())
.map(npc -> npc != null ? new NPC(this, npc) : null)
.toArray(size -> new NPC[size]);
}
NPC getNpc(int idx)
{
net.runelite.rs.api.NPC npc = client.getCachedNPCs()[idx];
return npc != null ? new NPC(this, npc) : null;
}
public Player[] getPlayers()
{
return Arrays.stream(client.getCachedPlayers())
.map(player -> player != null ? new Player(this, player) : null)
.toArray(size -> new Player[size]);
}
Player getPlayer(int idx)
{
net.runelite.rs.api.Player player = client.getCachedPlayers()[idx];
return player != null ? new Player(this, player) : null;
}
@SuppressWarnings("unchecked")
public <T> T[] runQuery(Query query)
{
return (T[]) query.result(this);
}
public int getBoostedSkillLevel(Skill skill)
{
int[] boostedLevels = client.getBoostedSkillLevels();
return boostedLevels[skill.ordinal()];
}
public int getRealSkillLevel(Skill skill)
{
int[] realLevels = client.getRealSkillLevels();
return realLevels[skill.ordinal()];
}
public void sendGameMessage(String message)
{
client.sendGameMessage(99, "", message);
}
public GameState getGameState()
{
return GameState.of(client.getGameState());
}
public String getUsername()
{
return client.getUsername();
}
public void setUsername(String name)
{
client.setUsername(name);
}
public Canvas getCanvas()
{
return client.getCanvas();
}
public int getFPS()
{
return client.getFPS();
}
public int getClientHeight()
{
return client.getCanvas().getHeight();
}
public int getClientWidth()
{
return client.getCanvas().getWidth();
}
public int getCameraX()
{
return client.getCameraX();
}
public int getCameraY()
{
return client.getCameraY();
}
public int getCameraZ()
{
return client.getCameraZ();
}
public int getCameraPitch()
{
return client.getCameraPitch();
}
public int getCameraYaw()
{
return client.getCameraYaw();
}
public int getViewportHeight()
{
return client.getViewportHeight();
}
public int getViewportWidth()
{
return client.getViewportWidth();
}
public int getScale()
{
return client.getScale();
}
public Point getMouseCanvasPosition()
{
return new Point(client.getMouseX(), client.getMouseY());
}
public int[][][] getTileHeights()
{
return client.getTileHeights();
}
public byte[][][] getTileSettings()
{
return client.getTileSettings();
}
public int getPlane()
{
return client.getPlane();
}
public Region getRegion()
{
return new Region(this, client.getRegion());
}
public ItemComposition getItemDefinition(int id)
{
return client.getItemDefinition(id);
}
public int getBaseX()
{
return client.getBaseX();
}
public int getBaseY()
{
return client.getBaseY();
}
public Widget[] getWidgetRoots()
{
int topGroup = client.getWidgetRoot();
return Arrays.stream(client.getWidgets()[topGroup])
.filter(Objects::nonNull)
.filter(w -> w.getParentId() == -1) // is a root
.map(w -> new Widget(this, w))
.toArray(Widget[]::new);
}
public Widget getWidget(WidgetInfo widget)
{
int groupId = widget.getGroupId();
int childId = widget.getChildId();
return getWidget(groupId, childId);
}
public Widget[] getGroup(int groupId)
{
net.runelite.rs.api.Widget[][] widgets = client.getWidgets();
if (widgets == null || groupId < 0 || groupId >= widgets.length)
{
return null;
}
return Arrays.stream(widgets[groupId])
.filter(Objects::nonNull)
.map(w -> new Widget(this, w))
.toArray(Widget[]::new);
}
public Widget getWidget(int groupId, int childId)
{
net.runelite.rs.api.Widget[][] widgets = client.getWidgets();
if (widgets == null || widgets.length <= groupId)
{
return null;
}
net.runelite.rs.api.Widget[] childWidgets = widgets[groupId];
if (childWidgets == null || childWidgets.length <= childId)
{
return null;
}
return new Widget(this, childWidgets[childId]);
}
public int[] getWidgetPositionsX()
{
return client.getWidgetPositionsX();
}
public int[] getWidgetPositionsY()
{
return client.getWidgetPositionsY();
}
public String[] getPlayerOptions()
{
return client.getPlayerOptions();
}
public boolean[] getPlayerOptionsPriorities()
{
return client.getPlayerOptionsPriorities();
}
public int[] getPlayerMenuType()
{
return client.getPlayerMenuTypes();
}
public String[] getMenuOptions()
{
return client.getMenuOptions();
}
public String[] getMenuTargets()
{
return client.getMenuTargets();
}
public int getMenuCount()
{
return client.getMenuOptionCount();
}
public boolean isMenuOpen()
{
return client.isMenuOpen();
}
public int getMapAngle()
{
return client.getMapAngle();
}
public boolean isResized()
{
return client.isResized();
}
public int getRevision()
{
return client.getRevision();
}
public int[] getMapRegions()
{
return client.getMapRegions();
}
public int[][] getXteaKeys()
{
return client.getXteaKeys();
}
public int getSetting(Varbits varbit)
{
int[] settings = client.getSettings();
int value = settings[varbit.getIndex()];
return varbit.get(value);
}
public XHashTable getComponentTable()
{
return new XHashTable(client.getComponentTable());
}
public int[] getSettings()
{
return client.getSettings();
}
public int[] getWidgetSettings()
{
return client.getWidgetSettings();
}
public boolean isPrayerActive(Prayer prayer)
{
return getSetting(prayer.getVarbit()) == 1;
}
public int getClanChatCount()
{
return client.getClanChatCount();
}
/**
* Returns the local player's current experience in the specified
* {@link Skill}.
*
* @param skill the {@link Skill} to retrieve the experience for
* @return the local player's current experience in the specified
* {@link Skill}, or -1 if the {@link Skill} isn't valid
*/
public int getSkillExperience(Skill skill)
{
int[] experiences = client.getSkillExperiences();
if (skill == Skill.OVERALL)
{
int totalExperience = 0;
for (int experience : experiences)
{
totalExperience += experience;
}
return totalExperience;
}
int idx = skill.ordinal();
// I'm not certain exactly how needed this is, but if the Skill enum is updated in the future
// to hold something else that's not reported it'll save us from an ArrayIndexOutOfBoundsException.
if (idx >= experiences.length)
{
return -1;
}
return experiences[idx];
}
public int getGameDrawingMode()
{
return client.getGameDrawingMode();
}
public void setGameDrawingMode(int gameDrawingMode)
{
client.setGameDrawingMode(gameDrawingMode);
}
public void refreshChat()
{
client.setChatCycle(client.getCycleCntr());
}
Player getPlayer(int idx);
Player[] getCachedPlayers();
NPC getNpc(int idx);
NPC[] getCachedNPCs();
int getBoostedSkillLevel(Skill skill);
int getRealSkillLevel(Skill skill);
void sendGameMessage(String message);
GameState getGameState();
String getUsername();
void setUsername(String name);
Canvas getCanvas();
int getFPS();
int getCameraX();
int getCameraY();
int getCameraZ();
int getCameraPitch();
int getCameraYaw();
int getViewportHeight();
int getViewportWidth();
int getScale();
Point getMouseCanvasPosition();
int[][][] getTileHeights();
byte[][][] getTileSettings();
int getPlane();
Region getRegion();
Player getLocalPlayer();
ItemComposition getItemDefinition(int id);
int getBaseX();
int getBaseY();
Widget[] getWidgetRoots();
Widget getWidget(WidgetInfo widget);
Widget[] getGroup(int groupId);
Widget getWidget(int groupId, int childId);
int[] getWidgetPositionsX();
int[] getWidgetPositionsY();
String[] getPlayerOptions();
boolean[] getPlayerOptionsPriorities();
int[] getPlayerMenuTypes();
String[] getMenuOptions();
String[] getMenuTargets();
int getMenuOptionCount();
boolean isMenuOpen();
int getMapAngle();
boolean isResized();
int getRevision();
int[] getMapRegions();
int[][] getXteaKeys();
int[] getSettings();
int[] getWidgetSettings();
int getSetting(Varbits varbit);
int getClanChatCount();
HashTable getComponentTable();
boolean isPrayerActive(Prayer prayer);
int getSkillExperience(Skill skill);
int getGameDrawingMode();
void setGameDrawingMode(int gameDrawingMode);
void refreshChat();
}

View File

@@ -31,63 +31,7 @@ import java.awt.Polygon;
*
* @author Adam
*/
public class DecorativeObject extends TileObject
public interface DecorativeObject extends TileObject
{
private final net.runelite.rs.api.DecorativeObject decorativeObject;
public DecorativeObject(Client client, net.runelite.rs.api.DecorativeObject decorativeObject)
{
super(client);
this.decorativeObject = decorativeObject;
}
@Override
protected int getHash()
{
return decorativeObject.getHash();
}
@Override
protected int getLocalX()
{
return decorativeObject.getX();
}
@Override
protected int getLocalY()
{
return decorativeObject.getY();
}
public Renderable getRenderable()
{
return Renderable.of(decorativeObject.getRenderable());
}
public Polygon getConvexHull()
{
Renderable renderable = getRenderable();
if (renderable == null)
{
return null;
}
Model model;
if (renderable instanceof Model)
{
model = (Model) renderable;
}
else
{
model = renderable.getModel();
}
if (model == null)
{
return null;
}
return getConvexHull(model, decorativeObject.getOrientation());
}
Polygon getConvexHull();
}

View File

@@ -30,63 +30,7 @@ import java.awt.Polygon;
*
* @author Adam
*/
public class GameObject extends TileObject
public interface GameObject extends TileObject
{
private final net.runelite.rs.api.GameObject gameObject;
public GameObject(Client client, net.runelite.rs.api.GameObject gameObject)
{
super(client);
this.gameObject = gameObject;
}
@Override
protected int getHash()
{
return gameObject.getHash();
}
@Override
protected int getLocalX()
{
return gameObject.getX();
}
@Override
protected int getLocalY()
{
return gameObject.getY();
}
public Renderable getRenderable()
{
return Renderable.of(gameObject.getRenderable());
}
public Polygon getConvexHull()
{
Renderable renderable = getRenderable();
if (renderable == null)
{
return null;
}
Model model;
if (renderable instanceof Model)
{
model = (Model) renderable;
}
else
{
model = renderable.getModel();
}
if (model == null)
{
return null;
}
return getConvexHull(model, gameObject.getOrientation());
}
Polygon getConvexHull();
}

View File

@@ -24,31 +24,6 @@
*/
package net.runelite.api;
public class GroundObject extends TileObject
public interface GroundObject extends TileObject
{
private final net.runelite.rs.api.GroundObject groundObject;
public GroundObject(Client client, net.runelite.rs.api.GroundObject groundObject)
{
super(client);
this.groundObject = groundObject;
}
@Override
protected int getHash()
{
return groundObject.getHash();
}
@Override
protected int getLocalX()
{
return groundObject.getX();
}
@Override
protected int getLocalY()
{
return groundObject.getY();
}
}

View File

@@ -24,38 +24,9 @@
*/
package net.runelite.api;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class XHashTable
public interface HashTable
{
private final net.runelite.rs.api.XHashTable hashtable;
public XHashTable(net.runelite.rs.api.XHashTable hashtable)
{
this.hashtable = hashtable;
}
public Collection<Node> getNodes()
{
List<Node> nodes = new ArrayList<>();
net.runelite.rs.api.Node[] buckets = hashtable.getBuckets();
for (int i = 0; i < buckets.length; ++i)
{
net.runelite.rs.api.Node node = buckets[i];
// It looks like the first node in the bucket is always
// a sentinel
net.runelite.rs.api.Node cur = node.getNext();
while (cur != node)
{
nodes.add(Node.of(cur));
cur = cur.getNext();
}
}
return nodes;
}
Collection<Node> getNodes();
}

View File

@@ -24,23 +24,9 @@
*/
package net.runelite.api;
public class Item extends Renderable
public interface Item extends Renderable
{
private final net.runelite.rs.api.Item item;
int getId();
public Item(net.runelite.rs.api.Item item)
{
super(item);
this.item = item;
}
public int getId()
{
return item.getId();
}
public int getQuantity()
{
return item.getQuantity();
}
int getQuantity();
}

View File

@@ -0,0 +1,77 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.api;
public interface ItemComposition
{
/**
* Returns the item's name as a string.
*
* @return the name of the item
*/
String getName();
/**
* Returns the item's ID. A list of item IDs can be found in
* ItemID.
*
* @return the item's ID as an integer
*/
int getId();
/**
* Returns a result that depends on whether the item is in noted form or
* not.
*
* @return 799 if noted, -1 if unnoted
*/
int getNote();
/**
* Returns the item ID of the noted/unnoted counterpart. For example, if
* you call this on an unnoted monkfish(ID 7946), this method will
* return the ID of a noted monkfish(ID 7947), and vice versa.
*
* @return the ID that is linked to this item in noted/unnoted form.
*/
int getLinkedNoteId();
/**
* Returns the store price of the item. Even if the item cannot be found
* in a store, all items have a store price from which the High and Low
* Alchemy values are calculated. Multiply the price by 0.6 to get the
* High Alchemy value, or 0.4 to get the Low Alchemy value.
*
* @return the general store value of the item
*/
int getPrice();
/**
* Returns whether or not the item is members-only.
*
* @return true if members-only, false otherwise.
*/
boolean isMembers();
}

View File

@@ -24,46 +24,11 @@
*/
package net.runelite.api;
public class ItemLayer extends TileObject
public interface ItemLayer extends TileObject
{
private final net.runelite.rs.api.ItemLayer itemLayer;
Renderable getBottom();
public ItemLayer(Client client, net.runelite.rs.api.ItemLayer itemLayer)
{
super(client);
this.itemLayer = itemLayer;
}
Renderable getMiddle();
@Override
protected int getHash()
{
return itemLayer.getHash();
}
@Override
protected int getLocalX()
{
return itemLayer.getX();
}
@Override
protected int getLocalY()
{
return itemLayer.getY();
}
public Renderable getBottom()
{
return Renderable.of(itemLayer.getBottom());
}
public Renderable getMiddle()
{
return Renderable.of(itemLayer.getMiddle());
}
public Renderable getTop()
{
return Renderable.of(itemLayer.getTop());
}
Renderable getTop();
}

View File

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

View File

@@ -24,32 +24,13 @@
*/
package net.runelite.api;
public class MessageNode
public interface MessageNode
{
private final net.runelite.rs.api.MessageNode messageNode;
ChatMessageType getType();
public MessageNode(net.runelite.rs.api.MessageNode messageNode)
{
this.messageNode = messageNode;
}
String getSender();
public ChatMessageType getType()
{
return ChatMessageType.of(messageNode.getType());
}
String getValue();
public String getSender()
{
return messageNode.getSender();
}
public String getValue()
{
return messageNode.getValue();
}
public void setValue(String value)
{
messageNode.setValue(value);
}
void setValue(String value);
}

View File

@@ -24,71 +24,13 @@
*/
package net.runelite.api;
import java.util.ArrayList;
import java.util.List;
import net.runelite.api.model.Triangle;
import net.runelite.api.model.Vertex;
public class Model extends Renderable
public interface Model extends Renderable
{
private final net.runelite.rs.api.Model model;
List<Vertex> getVertices();
public Model(net.runelite.rs.api.Model model)
{
super(model);
this.model = model;
}
public List<Vertex> getVertices()
{
int[] verticesX = model.getVerticesX();
int[] verticesY = model.getVerticesY();
int[] verticesZ = model.getVerticesZ();
assert verticesX.length == verticesY.length;
assert verticesY.length == verticesZ.length;
List<Vertex> vertices = new ArrayList<>();
for (int i = 0; i < verticesX.length; ++i)
{
Vertex v = new Vertex(
verticesX[i],
verticesY[i],
verticesZ[i]
);
vertices.add(v);
}
return vertices;
}
public List<Triangle> getTriangles()
{
int[] trianglesX = model.getTrianglesX();
int[] trianglesY = model.getTrianglesY();
int[] trianglesZ = model.getTrianglesZ();
assert trianglesX.length == trianglesY.length;
assert trianglesY.length == trianglesZ.length;
List<Vertex> vertices = getVertices();
List<Triangle> triangles = new ArrayList<>(trianglesX.length);
for (int i = 0; i < trianglesX.length; ++i)
{
int triangleX = trianglesX[i];
int triangleY = trianglesY[i];
int triangleZ = trianglesZ[i];
Triangle triangle = new Triangle(
vertices.get(triangleX),
vertices.get(triangleY),
vertices.get(triangleZ)
);
triangles.add(triangle);
}
return triangles;
}
List<Triangle> getTriangles();
}

View File

@@ -22,34 +22,16 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.api;
public class NPC extends Actor
public interface NPC extends Actor
{
private net.runelite.rs.api.NPC npc;
public NPC(Client client, net.runelite.rs.api.NPC npc)
{
super(client, npc);
this.npc = npc;
}
public int getId()
{
return npc.getComposition().getId();
}
int getId();
@Override
public String getName()
{
return npc.getComposition().getName().replace('\u00A0', ' ');
}
String getName();
@Override
public int getCombatLevel()
{
return npc.getComposition().getCombatLevel();
}
int getCombatLevel();
}

View File

@@ -24,58 +24,11 @@
*/
package net.runelite.api;
public class Node
public interface Node
{
private final net.runelite.rs.api.Node node;
Node getNext();
public Node(net.runelite.rs.api.Node node)
{
this.node = node;
}
Node getPrevious();
@Override
public String toString()
{
return "Node{" + "node=" + node + '}';
}
public Node getNext()
{
return of(node.getNext());
}
public Node getPrev()
{
return of(node.getPrevious());
}
public long getHash()
{
return node.getHash();
}
public static final Node of(net.runelite.rs.api.Node node)
{
if (node == null)
{
return null;
}
if (node instanceof net.runelite.rs.api.Item)
{
return new Item((net.runelite.rs.api.Item) node);
}
if (node instanceof net.runelite.rs.api.Renderable)
{
return Renderable.of((net.runelite.rs.api.Renderable) node);
}
if (node instanceof net.runelite.rs.api.WidgetNode)
{
return new WidgetNode((net.runelite.rs.api.WidgetNode) node);
}
return new Node(node);
}
long getHash();
}

View File

@@ -156,7 +156,7 @@ public class Perspective
int xx = y * sin + cos * x >> 16;
int yy = sin * x - y * cos >> 16;
int miniMapX = client.getClientWidth() - (!client.isResized() ? 208 : 167);
int miniMapX = client.getCanvas().getWidth() - (!client.isResized() ? 208 : 167);
x = (miniMapX + 167 / 2) + xx;
y = (167 / 2 - 1) + yy;

View File

@@ -25,115 +25,13 @@
package net.runelite.api;
import java.awt.Polygon;
import java.util.ArrayList;
import java.util.List;
import net.runelite.api.model.Triangle;
import net.runelite.api.model.Vertex;
public class Player extends Actor
public interface Player extends Actor
{
private final Client client;
private final net.runelite.rs.api.Player player;
public Player(Client client, net.runelite.rs.api.Player player)
{
super(client, player);
this.player = player;
this.client = client;
}
@Override
public String getName()
{
return player.getName().replace('\u00A0', ' ');
}
int getCombatLevel();
@Override
public int getCombatLevel()
{
return player.getCombatLevel();
}
PlayerComposition getPlayerComposition();
public PlayerComposition getPlayerComposition()
{
return new PlayerComposition(player.getComposition());
}
public Polygon[] getPolygons()
{
Model model = getModel();
if (model == null)
{
return null;
}
int localX = player.getX();
int localY = player.getY();
// models are orientated north (1024) and there are 2048 angles total
int orientation = (player.getOrientation() + 1024) % 2048;
List<Triangle> triangles = model.getTriangles();
if (orientation != 0)
{
triangles = rotate(triangles, orientation);
}
List<Polygon> polys = new ArrayList<>();
for (Triangle triangle : triangles)
{
Vertex vx = triangle.getA();
Vertex vy = triangle.getB();
Vertex vz = triangle.getC();
Point x = Perspective.worldToCanvas(client,
localX - vx.getX(),
localY - vx.getZ(),
-vx.getY());
Point y = Perspective.worldToCanvas(client,
localX - vy.getX(),
localY - vy.getZ(),
-vy.getY());
Point z = Perspective.worldToCanvas(client,
localX - vz.getX(),
localY - vz.getZ(),
-vz.getY());
int xx[] =
{
x.getX(), y.getX(), z.getX()
};
int yy[] =
{
x.getY(), y.getY(), z.getY()
};
polys.add(new Polygon(xx, yy, 3));
}
return polys.toArray(new Polygon[polys.size()]);
}
private List<Triangle> rotate(List<Triangle> triangles, int orientation)
{
List<Triangle> rotatedTriangles = new ArrayList<>();
for (Triangle triangle : triangles)
{
Vertex a = triangle.getA();
Vertex b = triangle.getB();
Vertex c = triangle.getC();
Triangle rotatedTriangle = new Triangle(
a.rotate(orientation),
b.rotate(orientation),
c.rotate(orientation)
);
rotatedTriangles.add(rotatedTriangle);
}
return rotatedTriangles;
}
Polygon[] getPolygons();
}

View File

@@ -26,43 +26,18 @@ package net.runelite.api;
import net.runelite.api.kit.KitType;
public class PlayerComposition
public interface PlayerComposition
{
private final net.runelite.rs.api.PlayerComposition playerComposition;
public PlayerComposition(net.runelite.rs.api.PlayerComposition playerComposition)
{
this.playerComposition = playerComposition;
}
/**
* Get equipment ids. If id is &ge; 256 &amp;&amp; &lt; 512 then subtract 256 and the id is a kit definition.
* If the id is &ge; 512 then subtract 512 and the id is an item id.
* Get equipment ids. If id is &ge; 256 &amp;&amp; &lt; 512 then
* subtract 256 and the id is a kit definition. If the id is &ge; 512
* then subtract 512 and the id is an item id.
*
* @return
*/
public int[] getEquipmentIds()
{
return playerComposition.getEquipmentIds();
}
int[] getEquipmentIds();
public int getEquipmentId(KitType type)
{
int id = getEquipmentIds()[type.getIndex()];
if (id < 512)
{
return -1; // not an item
}
return id - 512;
}
int getEquipmentId(KitType type);
public int getKitId(KitType type)
{
int id = getEquipmentIds()[type.getIndex()];
if (id < 256 || id >= 512)
{
return -1; // not a kit
}
return id - 256;
}
int getKitId(KitType type);
}

View File

@@ -34,7 +34,7 @@ public abstract class Query<EntityType, QueryType>
{
}
protected abstract EntityType[] result(Client client);
public abstract EntityType[] result(Client client);
protected Predicate<EntityType> and(Predicate<EntityType> other)
{

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -24,27 +24,7 @@
*/
package net.runelite.api;
import java.util.Arrays;
public class Region
public interface Region
{
private final Client client;
private final net.runelite.rs.api.Region region;
public Region(Client client, net.runelite.rs.api.Region region)
{
this.client = client;
this.region = region;
}
public Tile[][][] getTiles()
{
return Arrays.stream(region.getTiles())
.map(tile1 -> Arrays.stream(tile1)
.map(tile2 -> Arrays.stream(tile2)
.map(tile3 -> tile3 != null ? new Tile(client, tile3) : null)
.toArray(Tile[]::new)
).toArray(Tile[][]::new)
).toArray(Tile[][][]::new);
}
Tile[][][] getTiles();
}

View File

@@ -24,34 +24,7 @@
*/
package net.runelite.api;
public class Renderable extends Node
public interface Renderable extends Node
{
private final net.runelite.rs.api.Renderable renderable;
public Renderable(net.runelite.rs.api.Renderable renderable)
{
super(renderable);
this.renderable = renderable;
}
public Model getModel()
{
net.runelite.rs.api.Model model = renderable.getModel();
return model != null ? new Model(model) : null;
}
public static Renderable of(net.runelite.rs.api.Renderable renderable)
{
if (renderable == null)
{
return null;
}
if (renderable instanceof net.runelite.rs.api.Model)
{
return new Model((net.runelite.rs.api.Model) renderable);
}
return new Renderable(renderable);
}
Model getModel();
}

View File

@@ -24,83 +24,20 @@
*/
package net.runelite.api;
import java.util.Arrays;
public class Tile
public interface Tile
{
private final Client client;
private final net.runelite.rs.api.Tile tile;
public Tile(Client client, net.runelite.rs.api.Tile tile)
{
this.client = client;
this.tile = tile;
}
/**
* Get the decorative object for this tile.
*
* @return
*/
public DecorativeObject getDecorativeObject()
{
net.runelite.rs.api.DecorativeObject decorativeObject = tile.getDecorativeObject();
DecorativeObject getDecorativeObject();
if (decorativeObject == null)
{
return null;
}
GameObject[] getGameObjects();
return new DecorativeObject(client, decorativeObject);
}
ItemLayer getItemLayer();
public GameObject[] getGameObjects()
{
net.runelite.rs.api.GameObject[] objects = tile.getObjects();
GroundObject getGroundObject();
if (objects == null)
{
return null;
}
return Arrays.stream(tile.getObjects())
.map(go -> go != null ? new GameObject(client, go) : null)
.toArray(i -> new GameObject[i]);
}
public ItemLayer getItemLayer()
{
net.runelite.rs.api.ItemLayer itemLayer = tile.getItemLayer();
if (itemLayer == null)
{
return null;
}
return new ItemLayer(client, itemLayer);
}
public GroundObject getGroundObject()
{
net.runelite.rs.api.GroundObject groundObject = tile.getGroundObject();
if (groundObject == null)
{
return null;
}
return new GroundObject(client, groundObject);
}
public WallObject getWallObject()
{
net.runelite.rs.api.WallObject wallObject = tile.getWallObject();
if (wallObject == null)
{
return null;
}
return new WallObject(client, wallObject);
}
WallObject getWallObject();
}

View File

@@ -26,113 +26,28 @@ package net.runelite.api;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.util.ArrayList;
import java.util.List;
import net.runelite.api.model.Jarvis;
import net.runelite.api.model.Vertex;
public abstract class TileObject
public interface TileObject
{
protected final Client client;
int getHash();
public TileObject(Client client)
{
this.client = client;
}
int getX();
protected abstract int getHash();
int getY();
protected abstract int getLocalX();
int getId();
protected abstract int getLocalY();
Point getWorldLocation();
public int getId()
{
int hash = getHash();
return hash >> 14 & 32767;
}
Point getLocalLocation();
public Point getWorldLocation()
{
Point localLocation = getLocalLocation();
return Perspective.localToWorld(client, localLocation);
}
Point getCanvasLocation();
public Point getLocalLocation()
{
return new Point(getLocalX(), getLocalY());
}
Polygon getCanvasTilePoly();
public Point getCanvasLocation()
{
Point locaLocation = getLocalLocation();
return Perspective.worldToCanvas(client, locaLocation.getX(), locaLocation.getY(), 0);
}
Point getCanvasTextLocation(Graphics2D graphics, String text, int zOffset);
public Polygon getCanvasTilePoly()
{
return Perspective.getCanvasTilePoly(client, getLocalLocation());
}
Point getMinimapLocation();
public Point getCanvasTextLocation(Graphics2D graphics, String text, int zOffset)
{
return Perspective.getCanvasTextLocation(client, graphics, getLocalLocation(), text, zOffset);
}
public Point getMinimapLocation()
{
return Perspective.worldToMiniMap(client, getLocalX(), getLocalY());
}
protected Polygon getConvexHull(Model model, int orientation)
{
int localX = getLocalX();
int localY = getLocalY();
// models are orientated north (1024) and there are 2048 angles total
orientation = (orientation + 1024) % 2048;
List<Vertex> verticies = model.getVertices();
if (orientation != 0)
{
// rotate verticies
for (int i = 0; i < verticies.size(); ++i)
{
Vertex v = verticies.get(i);
verticies.set(i, v.rotate(orientation));
}
}
List<Point> points = new ArrayList<>();
for (Vertex v : verticies)
{
// Compute canvas location of vertex
Point p = Perspective.worldToCanvas(client,
localX - v.getX(),
localY - v.getZ(),
-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;
}
Polygon getConvexHull(Model model, int orientation);
}

View File

@@ -29,31 +29,6 @@ package net.runelite.api;
*
* @author Adam
*/
public class WallObject extends TileObject
public interface WallObject extends TileObject
{
private final net.runelite.rs.api.WallObject wallObject;
public WallObject(Client client, net.runelite.rs.api.WallObject wallObject)
{
super(client);
this.wallObject = wallObject;
}
@Override
protected int getHash()
{
return wallObject.getHash();
}
@Override
protected int getLocalX()
{
return wallObject.getX();
}
@Override
protected int getLocalY()
{
return wallObject.getY();
}
}

View File

@@ -24,18 +24,7 @@
*/
package net.runelite.api;
public class WidgetNode extends Node
public interface WidgetNode extends Node
{
private final net.runelite.rs.api.WidgetNode widgetNode;
public WidgetNode(net.runelite.rs.api.WidgetNode widgetNode)
{
super(widgetNode);
this.widgetNode = widgetNode;
}
public int getId()
{
return widgetNode.getId();
}
int getId();
}

View File

@@ -35,7 +35,7 @@ import java.util.Objects;
public class DecorativeObjectQuery extends TileObjectQuery<DecorativeObject, DecorativeObjectQuery>
{
@Override
protected DecorativeObject[] result(Client client)
public DecorativeObject[] result(Client client)
{
return getDecorativeObjects(client).stream().filter(Objects::nonNull).filter(predicate).toArray(DecorativeObject[]::new);
}

View File

@@ -36,7 +36,7 @@ import java.util.Objects;
public class GameObjectQuery extends TileObjectQuery<GameObject, GameObjectQuery>
{
@Override
protected GameObject[] result(Client client)
public GameObject[] result(Client client)
{
return getGameObjects(client).stream().filter(Objects::nonNull).filter(predicate).toArray(GameObject[]::new);
}

View File

@@ -35,7 +35,7 @@ import java.util.Objects;
public class GroundObjectQuery extends TileObjectQuery<GroundObject, GroundObjectQuery>
{
@Override
protected GroundObject[] result(Client client)
public GroundObject[] result(Client client)
{
return getGroundObjects(client).stream().filter(Objects::nonNull).filter(predicate).toArray(GroundObject[]::new);
}

View File

@@ -33,9 +33,9 @@ import java.util.Objects;
public class NPCQuery extends ActorQuery<NPC, NPCQuery>
{
@Override
protected NPC[] result(Client client)
public NPC[] result(Client client)
{
return Arrays.stream(client.getNpcs())
return Arrays.stream(client.getCachedNPCs())
.filter(Objects::nonNull)
.filter(predicate)
.toArray(NPC[]::new);

View File

@@ -33,9 +33,9 @@ import java.util.Objects;
public class PlayerQuery extends ActorQuery<Player, PlayerQuery>
{
@Override
protected Player[] result(Client client)
public Player[] result(Client client)
{
return Arrays.stream(client.getPlayers())
return Arrays.stream(client.getCachedPlayers())
.filter(Objects::nonNull)
.filter(predicate)
.toArray(Player[]::new);

View File

@@ -35,7 +35,7 @@ import java.util.Objects;
public class WallObjectQuery extends TileObjectQuery<WallObject, WallObjectQuery>
{
@Override
protected WallObject[] result(Client client)
public WallObject[] result(Client client)
{
return getWallObjects(client).stream().filter(Objects::nonNull).filter(predicate).toArray(WallObject[]::new);
}

View File

@@ -81,7 +81,7 @@ public class WidgetItemQuery extends Query<WidgetItem, WidgetItemQuery>
}
@Override
protected WidgetItem[] result(Client client)
public WidgetItem[] result(Client client)
{
Widget widget = client.getWidget(widgetInfo);
if (widget != null)

View File

@@ -25,320 +25,60 @@
package net.runelite.api.widgets;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import net.runelite.api.Client;
import net.runelite.api.Node;
import net.runelite.api.Point;
import net.runelite.api.WidgetNode;
import net.runelite.api.XHashTable;
import static net.runelite.api.widgets.WidgetInfo.TO_CHILD;
import static net.runelite.api.widgets.WidgetInfo.TO_GROUP;
public class Widget
public interface Widget
{
private static final int ITEM_SLOT_SIZE = 32;
int getId();
private final Client client;
private final net.runelite.rs.api.Widget widget;
int getType();
public Widget(Client client, net.runelite.rs.api.Widget widget)
{
this.client = client;
this.widget = widget;
}
int getContentType();
public int getId()
{
return widget.getId();
}
Widget getParent();
public int getType()
{
return widget.getType();
}
int getParentId();
public int getContentType()
{
return widget.getContentType();
}
Widget getChild(int index);
public Widget getParent()
{
int id = getParentId();
if (id == -1)
{
return null;
}
Widget[] getDynamicChildren();
return client.getWidget(TO_GROUP(id), TO_CHILD(id));
}
Widget[] getStaticChildren();
public int getParentId()
{
int parentId = widget.getParentId();
if (parentId != -1)
{
return parentId;
}
Widget[] getNestedChildren();
int i = TO_GROUP(getId());
XHashTable componentTable = client.getComponentTable();
for (Node node : componentTable.getNodes())
{
WidgetNode wn = (WidgetNode) node;
int getRelativeX();
if (i == wn.getId())
{
return (int) wn.getHash();
}
}
int getRelativeY();
return -1;
}
String getText();
public Widget getChild(int index)
{
net.runelite.rs.api.Widget[] widgets = widget.getChildren();
void setText(String text);
if (widgets == null || widgets[index] == null)
{
return null;
}
int getTextColor();
return new Widget(client, widgets[index]);
}
String getName();
public Widget[] getDynamicChildren()
{
net.runelite.rs.api.Widget[] children = widget.getChildren();
int getModelId();
if (children == null)
{
return new Widget[0];
}
int getSpriteId();
return Arrays.stream(children)
.filter(Objects::nonNull)
.filter(w -> w.getParentId() == getId())
.map(w -> new Widget(client, w))
.toArray(Widget[]::new);
}
boolean isHidden();
public Widget[] getStaticChildren()
{
return Arrays.stream(client.getGroup(TO_GROUP(getId())))
.filter(Objects::nonNull)
.filter(w -> w.getParentId() == getId())
.toArray(Widget[]::new);
}
Point getCanvasLocation();
public Widget[] getNestedChildren()
{
XHashTable componentTable = client.getComponentTable();
int group = -1;
int getWidth();
// XXX can actually use hashtable lookup instead of table
// iteration here...
for (Node node : componentTable.getNodes())
{
WidgetNode wn = (WidgetNode) node;
int getHeight();
if (wn.getHash() == getId())
{
group = wn.getId();
break;
}
}
Rectangle getBounds();
if (group == -1)
{
return new Widget[0];
}
Collection<WidgetItem> getWidgetItems();
return Arrays.stream(client.getGroup(group))
.filter(w -> w.getParentId() == getId())
.toArray(Widget[]::new);
}
WidgetItem getWidgetItem(int index);
private int getRelativeX()
{
return widget.getRelativeX();
}
int getItemId();
private int getRelativeY()
{
return widget.getRelativeY();
}
public String getText()
{
return widget.getText().replace('\u00A0', ' ');
}
public void setText(String text)
{
widget.setText(text);
}
public int getTextColor()
{
return widget.getTextColor();
}
public String getName()
{
return widget.getName().replace('\u00A0', ' ');
}
public int getModelId()
{
return widget.getModelId();
}
public int getSpriteId()
{
return widget.getSpriteId();
}
public boolean isHidden()
{
Widget parent = getParent();
return (parent != null && parent.isHidden()) || widget.isHidden();
}
public Point getCanvasLocation()
{
int x = 0;
int y = 0;
Widget cur;
for (cur = this; cur.getParent() != null; cur = cur.getParent())
{
x += cur.getRelativeX();
y += cur.getRelativeY();
x -= cur.widget.getScrollX();
y -= cur.widget.getScrollY();
}
// cur is now the root
int[] widgetBoundsWidth = client.getWidgetPositionsX();
int[] widgetBoundsHeight = client.getWidgetPositionsY();
int boundsIndex = cur.widget.getBoundsIndex();
if (boundsIndex != -1)
{
x += widgetBoundsWidth[boundsIndex];
y += widgetBoundsHeight[boundsIndex];
if (cur.getType() > 0)
{
x += cur.getRelativeX();
y += cur.getRelativeY();
}
}
else
{
x += cur.getRelativeX();
y += cur.getRelativeY();
}
return new Point(x, y);
}
public int getWidth()
{
return widget.getWidth();
}
public int getHeight()
{
return widget.getHeight();
}
public Rectangle getBounds()
{
Point canvasLocation = getCanvasLocation();
return new Rectangle(canvasLocation.getX(), canvasLocation.getY(), getWidth(), getHeight());
}
public Collection<WidgetItem> getWidgetItems()
{
int[] itemIds = widget.getItemIds();
if (itemIds == null)
{
return null;
}
List<WidgetItem> items = new ArrayList<>(itemIds.length);
for (int i = 0; i < itemIds.length; ++i)
{
WidgetItem item = getWidgetItem(i);
if (item != null)
{
items.add(item);
}
}
return items;
}
public WidgetItem getWidgetItem(int index)
{
int[] itemIds = widget.getItemIds();
int[] itemQuantities = widget.getItemQuantities();
if (itemIds == null || itemQuantities == null)
{
return null;
}
int columns = getWidth(); // the number of item slot columns is stored here
int paddingX = getPaddingX();
int paddingY = getPaddingY();
int itemId = itemIds[index];
int itemQuantity = itemQuantities[index];
Point widgetCanvasLocation = getCanvasLocation();
if (itemId <= 0 || itemQuantity <= 0 || columns <= 0)
{
return null;
}
int row = index / columns;
int col = index % columns;
int itemX = widgetCanvasLocation.getX() + ((ITEM_SLOT_SIZE + paddingX) * col);
int itemY = widgetCanvasLocation.getY() + ((ITEM_SLOT_SIZE + paddingY) * row);
Rectangle bounds = new Rectangle(itemX - 1, itemY - 1, ITEM_SLOT_SIZE, ITEM_SLOT_SIZE);
return new WidgetItem(itemId - 1, itemQuantity, index, bounds);
}
private int getPaddingX()
{
return widget.getPaddingX();
}
private int getPaddingY()
{
return widget.getPaddingY();
}
public int getItemId()
{
return widget.getItemId();
}
public int getItemQuantity()
{
return widget.getItemQuantity();
}
int getItemQuantity();
}