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

@@ -0,0 +1,37 @@
/*
* Copyright (c) 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.mixins;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Inject
{
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 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.mixins;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Repeatable(Mixins.class)
public @interface Mixin
{
/**
* Class to inject this mixin into
*
* @return
*/
Class<?> value();
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright (c) 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.mixins;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Mixins
{
Mixin[] value();
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright (c) 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.mixins;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Shadow
{
String value();
}

View File

@@ -0,0 +1,148 @@
/*
* 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.mixins;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.image.BufferedImage;
import net.runelite.api.Actor;
import net.runelite.api.Perspective;
import net.runelite.api.Point;
import net.runelite.api.mixins.Inject;
import net.runelite.api.mixins.Mixin;
import net.runelite.api.mixins.Shadow;
import net.runelite.rs.api.RSActor;
import net.runelite.rs.api.RSClient;
import net.runelite.rs.api.RSCombatInfo1;
import net.runelite.rs.api.RSCombatInfo2;
import net.runelite.rs.api.RSCombatInfoList;
import net.runelite.rs.api.RSCombatInfoListHolder;
import net.runelite.rs.api.RSNode;
@Mixin(RSActor.class)
public abstract class RSActorMixin implements RSActor
{
@Shadow("clientInstance")
private static RSClient client;
@Inject
@Override
public Actor getInteracting()
{
int i = getRSInteracting();
if (i == -1)
{
return null;
}
if (i < 0x8000)
{
return client.getNpc(i);
}
i -= 0x8000;
return client.getPlayer(i);
}
@Inject
@Override
public int getHealthRatio()
{
RSCombatInfoList combatInfoList = getCombatInfoList();
if (combatInfoList != null)
{
RSNode node = combatInfoList.getNode();
RSNode next = node.getNext();
if (next instanceof RSCombatInfoListHolder)
{
RSCombatInfoListHolder combatInfoListWrapper = (RSCombatInfoListHolder) next;
RSCombatInfoList combatInfoList1 = combatInfoListWrapper.getCombatInfo1();
RSNode node2 = combatInfoList1.getNode();
RSNode next2 = node2.getNext();
if (next2 instanceof RSCombatInfo1)
{
RSCombatInfo1 combatInfo = (RSCombatInfo1) next2;
return combatInfo.getHealthRatio();
}
}
}
return -1;
}
@Inject
@Override
public int getHealth()
{
RSCombatInfoList combatInfoList = getCombatInfoList();
if (combatInfoList != null)
{
RSNode node = combatInfoList.getNode();
RSNode next = node.getNext();
if (next instanceof RSCombatInfoListHolder)
{
RSCombatInfoListHolder combatInfoListWrapper = (RSCombatInfoListHolder) next;
RSCombatInfo2 cf = combatInfoListWrapper.getCombatInfo2();
return cf.getHealthScale();
}
}
return -1;
}
@Inject
@Override
public Point getLocalLocation()
{
return new Point(getX(), getY());
}
@Inject
@Override
public Polygon getCanvasTilePoly()
{
return Perspective.getCanvasTilePoly(client, getLocalLocation());
}
@Inject
@Override
public Point getCanvasTextLocation(Graphics2D graphics, String text, int zOffset)
{
return Perspective.getCanvasTextLocation(client, graphics, getLocalLocation(), text, zOffset);
}
@Inject
@Override
public Point getCanvasImageLocation(Graphics2D graphics, BufferedImage image, int zOffset)
{
return Perspective.getCanvasImageLocation(client, graphics, getLocalLocation(), image, zOffset);
}
@Inject
@Override
public Point getMinimapLocation()
{
return Perspective.worldToMiniMap(client, getX(), getY());
}
}

View File

@@ -0,0 +1,225 @@
/*
* 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.mixins;
import java.util.ArrayList;
import java.util.List;
import net.runelite.api.GameState;
import net.runelite.api.NPC;
import net.runelite.api.Player;
import net.runelite.api.Point;
import net.runelite.api.Prayer;
import net.runelite.api.Skill;
import net.runelite.api.Varbits;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetInfo;
import net.runelite.api.mixins.Inject;
import net.runelite.api.mixins.Mixin;
import net.runelite.rs.api.RSClient;
import net.runelite.rs.api.RSWidget;
@Mixin(RSClient.class)
public abstract class RSClientMixin implements RSClient
{
@Inject
@Override
public Player getPlayer(int idx)
{
return getCachedPlayers()[idx];
}
@Inject
@Override
public NPC getNpc(int idx)
{
return getCachedNPCs()[idx];
}
@Inject
@Override
public int getBoostedSkillLevel(Skill skill)
{
int[] boostedLevels = getBoostedSkillLevels();
return boostedLevels[skill.ordinal()];
}
@Inject
@Override
public int getRealSkillLevel(Skill skill)
{
int[] realLevels = getRealSkillLevels();
return realLevels[skill.ordinal()];
}
@Inject
@Override
public void sendGameMessage(String message)
{
sendGameMessage(99, "", message);
}
@Inject
@Override
public GameState getGameState()
{
return GameState.of(getRSGameState());
}
@Inject
@Override
public Point getMouseCanvasPosition()
{
return new Point(getMouseX(), getMouseY());
}
@Inject
@Override
public Widget[] getWidgetRoots()
{
int topGroup = getWidgetRoot();
List<Widget> widgets = new ArrayList<Widget>();
for (Widget widget : getWidgets()[topGroup])
{
if (widget != null && widget.getParentId() == -1)
{
widgets.add(widget);
}
}
return widgets.toArray(new Widget[widgets.size()]);
}
@Inject
@Override
public Widget getWidget(WidgetInfo widget)
{
int groupId = widget.getGroupId();
int childId = widget.getChildId();
return getWidget(groupId, childId);
}
@Inject
@Override
public Widget[] getGroup(int groupId)
{
RSWidget[][] widgets = getWidgets();
if (widgets == null || groupId < 0 || groupId >= widgets.length)
{
return null;
}
List<Widget> w = new ArrayList<Widget>();
for (Widget widget : widgets[groupId])
{
if (widget != null)
{
w.add(widget);
}
}
return w.toArray(new Widget[w.size()]);
}
@Inject
@Override
public Widget getWidget(int groupId, int childId)
{
RSWidget[][] widgets = getWidgets();
if (widgets == null || widgets.length <= groupId)
{
return null;
}
RSWidget[] childWidgets = widgets[groupId];
if (childWidgets == null || childWidgets.length <= childId)
{
return null;
}
return childWidgets[childId];
}
@Inject
@Override
public int getSetting(Varbits varbit)
{
int[] settings = getSettings();
int value = settings[varbit.getIndex()];
return varbit.get(value);
}
@Inject
@Override
public boolean isPrayerActive(Prayer prayer)
{
return getSetting(prayer.getVarbit()) == 1;
}
/**
* 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
*/
@Inject
@Override
public int getSkillExperience(Skill skill)
{
int[] experiences = 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];
}
@Inject
@Override
public void refreshChat()
{
setChatCycle(getCycleCntr());
}
}

View File

@@ -0,0 +1,65 @@
/*
* 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.mixins;
import java.awt.Polygon;
import net.runelite.api.Model;
import net.runelite.api.Renderable;
import net.runelite.api.mixins.Inject;
import net.runelite.api.mixins.Mixin;
import net.runelite.rs.api.RSDecorativeObject;
@Mixin(RSDecorativeObject.class)
public abstract class RSDecorativeObjectMixin implements RSDecorativeObject
{
@Inject
@Override
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, getOrientation());
}
}

View File

@@ -0,0 +1,65 @@
/*
* 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.mixins;
import java.awt.Polygon;
import net.runelite.api.Model;
import net.runelite.api.Renderable;
import net.runelite.api.mixins.Inject;
import net.runelite.api.mixins.Mixin;
import net.runelite.rs.api.RSGameObject;
@Mixin(RSGameObject.class)
public abstract class RSGameObjectMixin implements RSGameObject
{
@Inject
@Override
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, getOrientation());
}
}

View File

@@ -0,0 +1,62 @@
/*
* 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.mixins;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import net.runelite.api.Node;
import net.runelite.api.mixins.Inject;
import net.runelite.api.mixins.Mixin;
import net.runelite.rs.api.RSHashTable;
import net.runelite.rs.api.RSNode;
@Mixin(RSHashTable.class)
public abstract class RSHashTableMixin implements RSHashTable
{
@Inject
@Override
public Collection<Node> getNodes()
{
List<Node> nodes = new ArrayList<Node>();
RSNode[] buckets = getBuckets();
for (int i = 0; i < buckets.length; ++i)
{
Node node = buckets[i];
// It looks like the first node in the bucket is always
// a sentinel
Node cur = node.getNext();
while (cur != node)
{
nodes.add(cur);
cur = cur.getNext();
}
}
return nodes;
}
}

View File

@@ -0,0 +1,41 @@
/*
* 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.mixins;
import net.runelite.api.ChatMessageType;
import net.runelite.api.mixins.Inject;
import net.runelite.api.mixins.Mixin;
import net.runelite.rs.api.RSMessageNode;
@Mixin(RSMessageNode.class)
public abstract class RSMessageNodeMixin implements RSMessageNode
{
@Inject
@Override
public ChatMessageType getType()
{
return ChatMessageType.of(getRSType());
}
}

View File

@@ -0,0 +1,88 @@
/*
* 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.mixins;
import java.util.ArrayList;
import java.util.List;
import net.runelite.api.model.Triangle;
import net.runelite.api.model.Vertex;
import net.runelite.api.mixins.Inject;
import net.runelite.api.mixins.Mixin;
import net.runelite.rs.api.RSModel;
@Mixin(RSModel.class)
public abstract class RSModelMixin implements RSModel
{
@Override
@Inject
public List<Vertex> getVertices()
{
int[] verticesX = getVerticesX();
int[] verticesY = getVerticesY();
int[] verticesZ = getVerticesZ();
List<Vertex> vertices = new ArrayList<Vertex>();
for (int i = 0; i < verticesX.length; ++i)
{
Vertex v = new Vertex(
verticesX[i],
verticesY[i],
verticesZ[i]
);
vertices.add(v);
}
return vertices;
}
@Override
@Inject
public List<Triangle> getTriangles()
{
int[] trianglesX = getTrianglesX();
int[] trianglesY = getTrianglesY();
int[] trianglesZ = getTrianglesZ();
List<Vertex> vertices = getVertices();
List<Triangle> triangles = new ArrayList<Triangle>(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;
}
}

View File

@@ -0,0 +1,54 @@
/*
* 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.mixins;
import net.runelite.api.mixins.Inject;
import net.runelite.api.mixins.Mixin;
import net.runelite.rs.api.RSNPC;
@Mixin(RSNPC.class)
public abstract class RSNPCMixin implements RSNPC
{
@Inject
@Override
public int getId()
{
return getComposition().getId();
}
@Inject
@Override
public String getName()
{
return getComposition().getName().replace('\u00A0', ' ');
}
@Inject
@Override
public int getCombatLevel()
{
return getComposition().getCombatLevel();
}
}

View File

@@ -0,0 +1,58 @@
/*
* 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.mixins;
import net.runelite.api.kit.KitType;
import net.runelite.api.mixins.Inject;
import net.runelite.api.mixins.Mixin;
import net.runelite.rs.api.RSPlayerComposition;
@Mixin(RSPlayerComposition.class)
public abstract class RSPlayerCompositionMixin implements RSPlayerComposition
{
@Inject
@Override
public int getEquipmentId(KitType type)
{
int id = getEquipmentIds()[type.getIndex()];
if (id < 512)
{
return -1; // not an item
}
return id - 512;
}
@Inject
@Override
public int getKitId(KitType type)
{
int id = getEquipmentIds()[type.getIndex()];
if (id < 256 || id >= 512)
{
return -1; // not a kit
}
return id - 256;
}
}

View File

@@ -0,0 +1,133 @@
/*
* 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.mixins;
import java.awt.Polygon;
import java.util.ArrayList;
import java.util.List;
import net.runelite.api.Model;
import net.runelite.api.Perspective;
import net.runelite.api.Point;
import net.runelite.api.model.Triangle;
import net.runelite.api.model.Vertex;
import net.runelite.api.mixins.Inject;
import net.runelite.api.mixins.Mixin;
import net.runelite.api.mixins.Shadow;
import net.runelite.rs.api.RSClient;
import net.runelite.rs.api.RSPlayer;
@Mixin(RSPlayer.class)
public abstract class RSPlayerMixin implements RSPlayer
{
@Shadow("clientInstance")
private static RSClient client;
@Inject
@Override
public String getName()
{
return getRSName().replace('\u00A0', ' ');
}
@Inject
@Override
public Polygon[] getPolygons()
{
Model model = getModel();
if (model == null)
{
return null;
}
int localX = getX();
int localY = getY();
// models are orientated north (1024) and there are 2048 angles total
int orientation = (getOrientation() + 1024) % 2048;
List<Triangle> triangles = model.getTriangles();
if (orientation != 0)
{
triangles = rotate(triangles, orientation);
}
List<Polygon> polys = new ArrayList<Polygon>();
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()]);
}
@Inject
private List<Triangle> rotate(List<Triangle> triangles, int orientation)
{
List<Triangle> rotatedTriangles = new ArrayList<Triangle>();
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;
}
}

View File

@@ -0,0 +1,310 @@
/*
* 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.mixins;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import net.runelite.api.Node;
import net.runelite.api.Point;
import net.runelite.api.WidgetNode;
import net.runelite.api.widgets.Widget;
import static net.runelite.api.widgets.WidgetInfo.TO_CHILD;
import static net.runelite.api.widgets.WidgetInfo.TO_GROUP;
import net.runelite.api.widgets.WidgetItem;
import net.runelite.api.mixins.Inject;
import net.runelite.api.mixins.Mixin;
import net.runelite.api.mixins.Shadow;
import net.runelite.rs.api.RSClient;
import net.runelite.rs.api.RSHashTable;
import net.runelite.rs.api.RSWidget;
@Mixin(RSWidget.class)
public abstract class RSWidgetMixin implements RSWidget
{
private static final int ITEM_SLOT_SIZE = 32;
@Shadow("clientInstance")
private static RSClient client;
@Inject
@Override
public Widget getParent()
{
int id = getParentId();
if (id == -1)
{
return null;
}
return client.getWidget(TO_GROUP(id), TO_CHILD(id));
}
@Inject
@Override
public int getParentId()
{
int parentId = getRSParentId();
if (parentId != -1)
{
return parentId;
}
int i = TO_GROUP(getId());
RSHashTable componentTable = client.getComponentTable();
for (Node node : componentTable.getNodes())
{
WidgetNode wn = (WidgetNode) node;
if (i == wn.getId())
{
return (int) wn.getHash();
}
}
return -1;
}
@Inject
@Override
public String getText()
{
return getRSText().replace('\u00A0', ' ');
}
@Inject
@Override
public String getName()
{
return getRSName().replace('\u00A0', ' ');
}
@Inject
@Override
public boolean isHidden()
{
Widget parent = getParent();
return (parent != null && parent.isHidden()) || isRSHidden();
}
@Inject
@Override
public Point getCanvasLocation()
{
int x = 0;
int y = 0;
RSWidget cur;
for (cur = this; cur.getParent() != null; cur = (RSWidget) cur.getParent())
{
x += cur.getRelativeX();
y += cur.getRelativeY();
x -= cur.getScrollX();
y -= cur.getScrollY();
}
// cur is now the root
int[] widgetBoundsWidth = client.getWidgetPositionsX();
int[] widgetBoundsHeight = client.getWidgetPositionsY();
int boundsIndex = cur.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);
}
@Inject
@Override
public Rectangle getBounds()
{
Point canvasLocation = getCanvasLocation();
return new Rectangle(canvasLocation.getX(), canvasLocation.getY(), getWidth(), getHeight());
}
@Inject
@Override
public Collection<WidgetItem> getWidgetItems()
{
int[] itemIds = getItemIds();
if (itemIds == null)
{
return null;
}
List<WidgetItem> items = new ArrayList<WidgetItem>(itemIds.length);
for (int i = 0; i < itemIds.length; ++i)
{
WidgetItem item = getWidgetItem(i);
if (item != null)
{
items.add(item);
}
}
return items;
}
@Inject
@Override
public WidgetItem getWidgetItem(int index)
{
int[] itemIds = getItemIds();
int[] itemQuantities = 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);
}
@Inject
@Override
public Widget getChild(int index)
{
RSWidget[] widgets = getChildren();
if (widgets == null || widgets[index] == null)
{
return null;
}
return widgets[index];
}
@Inject
@Override
public Widget[] getDynamicChildren()
{
RSWidget[] children = getChildren();
if (children == null)
{
return new Widget[0];
}
List<Widget> widgets = new ArrayList<Widget>();
for (Widget widget : children)
{
if (widget != null && widget.getParentId() == getId())
{
widgets.add(widget);
}
}
return widgets.toArray(new Widget[widgets.size()]);
}
@Inject
@Override
public Widget[] getStaticChildren()
{
List<Widget> widgets = new ArrayList<Widget>();
for (Widget widget : client.getGroup(TO_GROUP(getId())))
{
if (widget != null && widget.getParentId() == getId())
{
widgets.add(widget);
}
}
return widgets.toArray(new Widget[widgets.size()]);
}
@Inject
@Override
public Widget[] getNestedChildren()
{
RSHashTable componentTable = client.getComponentTable();
int group = -1;
// XXX can actually use hashtable lookup instead of table
// iteration here...
for (Node node : componentTable.getNodes())
{
WidgetNode wn = (WidgetNode) node;
if (wn.getHash() == getId())
{
group = wn.getId();
break;
}
}
if (group == -1)
{
return new Widget[0];
}
List<Widget> widgets = new ArrayList<Widget>();
for (Widget widget : client.getGroup(group))
{
if (widget != null && widget.getParentId() == getId())
{
widgets.add(widget);
}
}
return widgets.toArray(new Widget[widgets.size()]);
}
}

View File

@@ -0,0 +1,165 @@
/*
* 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.mixins;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.util.ArrayList;
import java.util.List;
import net.runelite.api.Model;
import net.runelite.api.Perspective;
import net.runelite.api.Point;
import net.runelite.api.TileObject;
import net.runelite.api.model.Jarvis;
import net.runelite.api.model.Vertex;
import net.runelite.api.mixins.Inject;
import net.runelite.api.mixins.Mixin;
import net.runelite.api.mixins.Mixins;
import net.runelite.api.mixins.Shadow;
import net.runelite.rs.api.RSClient;
import net.runelite.rs.api.RSDecorativeObject;
import net.runelite.rs.api.RSGameObject;
import net.runelite.rs.api.RSGroundObject;
import net.runelite.rs.api.RSItemLayer;
import net.runelite.rs.api.RSWallObject;
@Mixins({
@Mixin(RSDecorativeObject.class),
@Mixin(RSGameObject.class),
@Mixin(RSGroundObject.class),
@Mixin(RSItemLayer.class),
@Mixin(RSWallObject.class)
})
public abstract class TileObjectMixin implements TileObject
{
@Shadow("clientInstance")
private static RSClient client;
@Override
@Inject
public int getId()
{
int hash = getHash();
return hash >> 14 & 32767;
}
@Override
@Inject
public Point getWorldLocation()
{
Point localLocation = getLocalLocation();
return Perspective.localToWorld(client, localLocation);
}
@Override
@Inject
public Point getLocalLocation()
{
return new Point(getX(), getY());
}
@Override
@Inject
public Point getCanvasLocation()
{
Point locaLocation = getLocalLocation();
return Perspective.worldToCanvas(client, locaLocation.getX(), locaLocation.getY(), 0);
}
@Override
@Inject
public Polygon getCanvasTilePoly()
{
return Perspective.getCanvasTilePoly(client, getLocalLocation());
}
@Override
@Inject
public Point getCanvasTextLocation(Graphics2D graphics, String text, int zOffset)
{
return Perspective.getCanvasTextLocation(client, graphics, getLocalLocation(), text, zOffset);
}
@Override
@Inject
public Point getMinimapLocation()
{
return Perspective.worldToMiniMap(client, getX(), getY());
}
@Override
@Inject
public Polygon getConvexHull(Model model, int orientation)
{
int localX = getX();
int localY = getY();
// 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<Point>();
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;
}
}