diff --git a/http-api/build.gradle b/http-api/build.gradle index 28e551d14a..5d09f50c6d 100644 --- a/http-api/build.gradle +++ b/http-api/build.gradle @@ -5,6 +5,7 @@ description = 'Web API' dependencies { annotationProcessor group: 'org.projectlombok', name: 'lombok', version: lombok + compileOnly group: 'javax.inject', name: 'javax.inject', version: javaxInject compileOnly group: 'org.projectlombok', name: 'lombok', version: lombok implementation group: 'com.google.code.gson', name: 'gson', version: gson diff --git a/http-api/src/main/java/net/runelite/http/api/feed/FeedClient.java b/http-api/src/main/java/net/runelite/http/api/feed/FeedClient.java index 6b05ad20ba..bf4698315c 100644 --- a/http-api/src/main/java/net/runelite/http/api/feed/FeedClient.java +++ b/http-api/src/main/java/net/runelite/http/api/feed/FeedClient.java @@ -28,8 +28,10 @@ import com.google.gson.JsonParseException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import javax.inject.Inject; import net.runelite.http.api.RuneLiteAPI; import okhttp3.HttpUrl; +import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import org.slf4j.Logger; @@ -39,6 +41,14 @@ public class FeedClient { private static final Logger logger = LoggerFactory.getLogger(FeedClient.class); + private final OkHttpClient client; + + @Inject + public FeedClient(OkHttpClient client) + { + this.client = client; + } + public FeedResult lookupFeed() throws IOException { HttpUrl url = RuneLiteAPI.getApiBase().newBuilder() @@ -51,7 +61,7 @@ public class FeedClient .url(url) .build(); - try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute()) + try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) { diff --git a/http-api/src/main/java/net/runelite/http/api/item/ItemClient.java b/http-api/src/main/java/net/runelite/http/api/item/ItemClient.java index 0e34a05742..a9361f73cb 100644 --- a/http-api/src/main/java/net/runelite/http/api/item/ItemClient.java +++ b/http-api/src/main/java/net/runelite/http/api/item/ItemClient.java @@ -35,8 +35,10 @@ import java.lang.reflect.Type; import java.util.Arrays; import java.util.Map; import javax.imageio.ImageIO; +import javax.inject.Inject; import net.runelite.http.api.RuneLiteAPI; import okhttp3.HttpUrl; +import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import org.slf4j.Logger; @@ -46,6 +48,14 @@ public class ItemClient { private static final Logger logger = LoggerFactory.getLogger(ItemClient.class); + private final OkHttpClient client; + + @Inject + public ItemClient(OkHttpClient client) + { + this.client = client; + } + public ItemPrice lookupItemPrice(int itemId) throws IOException { HttpUrl url = RuneLiteAPI.getApiBase().newBuilder() @@ -60,7 +70,7 @@ public class ItemClient .url(url) .build(); - try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute()) + try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) { @@ -96,7 +106,7 @@ public class ItemClient .url(url) .build(); - try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute()) + try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) { @@ -129,7 +139,7 @@ public class ItemClient return Observable.defer(() -> { - try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute()) + try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) { @@ -162,7 +172,7 @@ public class ItemClient .url(url) .build(); - try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute()) + try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) { @@ -197,7 +207,7 @@ public class ItemClient .url(url) .build(); - try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute()) + try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) { @@ -233,7 +243,7 @@ public class ItemClient .url(url) .build(); - try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute()) + try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) { diff --git a/http-api/src/main/java/net/runelite/http/api/worlds/WorldClient.java b/http-api/src/main/java/net/runelite/http/api/worlds/WorldClient.java index 13559bdd3b..61169ab601 100644 --- a/http-api/src/main/java/net/runelite/http/api/worlds/WorldClient.java +++ b/http-api/src/main/java/net/runelite/http/api/worlds/WorldClient.java @@ -29,8 +29,10 @@ import com.google.gson.JsonParseException; import io.reactivex.Observable; import java.io.InputStream; import java.io.InputStreamReader; +import javax.inject.Inject; import net.runelite.http.api.RuneLiteAPI; import okhttp3.HttpUrl; +import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import org.slf4j.Logger; @@ -40,6 +42,14 @@ public class WorldClient { private static final Logger logger = LoggerFactory.getLogger(WorldClient.class); + private final OkHttpClient client; + + @Inject + public WorldClient(OkHttpClient client) + { + this.client = client; + } + public Observable lookupWorlds() { HttpUrl url = RuneLiteAPI.getApiBase().newBuilder() @@ -54,7 +64,7 @@ public class WorldClient .url(url) .build(); - try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute()) + try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) { diff --git a/http-service/src/main/java/net/runelite/http/service/feed/FeedController.java b/http-service/src/main/java/net/runelite/http/service/feed/FeedController.java index c679cd319f..480478c9d0 100644 --- a/http-service/src/main/java/net/runelite/http/service/feed/FeedController.java +++ b/http-service/src/main/java/net/runelite/http/service/feed/FeedController.java @@ -24,6 +24,9 @@ */ package net.runelite.http.service.feed; +import com.google.common.hash.HashCode; +import com.google.common.hash.Hasher; +import com.google.common.hash.Hashing; import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -51,7 +54,26 @@ public class FeedController private final TwitterService twitterService; private final OSRSNewsService osrsNewsService; - private FeedResult feedResult; + private static class MemoizedFeed + { + final FeedResult feedResult; + final String hash; + + MemoizedFeed(FeedResult feedResult) + { + this.feedResult = feedResult; + + Hasher hasher = Hashing.sha256().newHasher(); + for (FeedItem itemPrice : feedResult.getItems()) + { + hasher.putBytes(itemPrice.getTitle().getBytes()).putBytes(itemPrice.getContent().getBytes()); + } + HashCode code = hasher.hash(); + hash = code.toString(); + } + } + + private MemoizedFeed memoizedFeed; @Autowired public FeedController(BlogService blogService, TwitterService twitterService, OSRSNewsService osrsNewsService) @@ -93,20 +115,21 @@ public class FeedController log.warn(e.getMessage()); } - feedResult = new FeedResult(items); + memoizedFeed = new MemoizedFeed(new FeedResult(items)); } @GetMapping public ResponseEntity getFeed() { - if (feedResult == null) + if (memoizedFeed == null) { return ResponseEntity.notFound() .build(); } return ResponseEntity.ok() + .eTag(memoizedFeed.hash) .cacheControl(CacheControl.maxAge(10, TimeUnit.MINUTES).cachePublic()) - .body(feedResult); + .body(memoizedFeed.feedResult); } } diff --git a/http-service/src/main/java/net/runelite/http/service/item/ItemController.java b/http-service/src/main/java/net/runelite/http/service/item/ItemController.java index 9d1ed5710e..8db56ef2ff 100644 --- a/http-service/src/main/java/net/runelite/http/service/item/ItemController.java +++ b/http-service/src/main/java/net/runelite/http/service/item/ItemController.java @@ -28,6 +28,9 @@ import com.google.common.base.Supplier; import com.google.common.base.Suppliers; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; +import com.google.common.hash.HashCode; +import com.google.common.hash.Hasher; +import com.google.common.hash.Hashing; import java.time.Instant; import java.util.Arrays; import java.util.List; @@ -53,20 +56,39 @@ public class ItemController private static final String RUNELITE_CACHE = "RuneLite-Cache"; private static final int MAX_BATCH_LOOKUP = 1024; + private static class MemoizedPrices + { + final ItemPrice[] prices; + final String hash; + + MemoizedPrices(ItemPrice[] prices) + { + this.prices = prices; + + Hasher hasher = Hashing.sha256().newHasher(); + for (ItemPrice itemPrice : prices) + { + hasher.putInt(itemPrice.getId()).putInt(itemPrice.getPrice()); + } + HashCode code = hasher.hash(); + hash = code.toString(); + } + } + private final Cache cachedEmpty = CacheBuilder.newBuilder() .maximumSize(1024L) .build(); private final ItemService itemService; - private final Supplier memorizedPrices; + private final Supplier memoizedPrices; @Autowired public ItemController(ItemService itemService) { this.itemService = itemService; - memorizedPrices = Suppliers.memoizeWithExpiration(() -> itemService.fetchPrices().stream() + memoizedPrices = Suppliers.memoizeWithExpiration(() -> new MemoizedPrices(itemService.fetchPrices().stream() .map(priceEntry -> { ItemPrice itemPrice = new ItemPrice(); @@ -76,7 +98,7 @@ public class ItemController itemPrice.setTime(priceEntry.getTime()); return itemPrice; }) - .toArray(ItemPrice[]::new), 30, TimeUnit.MINUTES); + .toArray(ItemPrice[]::new)), 30, TimeUnit.MINUTES); } @GetMapping("/{itemId}") @@ -220,8 +242,10 @@ public class ItemController @GetMapping("/prices") public ResponseEntity prices() { + MemoizedPrices memorizedPrices = this.memoizedPrices.get(); return ResponseEntity.ok() + .eTag(memorizedPrices.hash) .cacheControl(CacheControl.maxAge(30, TimeUnit.MINUTES).cachePublic()) - .body(memorizedPrices.get()); + .body(memorizedPrices.prices); } } diff --git a/runelite-api/src/main/java/net/runelite/api/Actor.java b/runelite-api/src/main/java/net/runelite/api/Actor.java index 460e12132e..9723fc9605 100644 --- a/runelite-api/src/main/java/net/runelite/api/Actor.java +++ b/runelite-api/src/main/java/net/runelite/api/Actor.java @@ -26,6 +26,7 @@ package net.runelite.api; import java.awt.Graphics2D; import java.awt.Polygon; +import java.awt.Shape; import java.awt.image.BufferedImage; import javax.annotation.Nullable; import net.runelite.api.coords.LocalPoint; @@ -213,7 +214,7 @@ public interface Actor extends Entity, Locatable * @return the convex hull * @see net.runelite.api.model.Jarvis */ - Polygon getConvexHull(); + Shape getConvexHull(); /** * Gets the world area that the actor occupies. diff --git a/runelite-api/src/main/java/net/runelite/api/DecorativeObject.java b/runelite-api/src/main/java/net/runelite/api/DecorativeObject.java index e9ba02a18f..3686f8590d 100644 --- a/runelite-api/src/main/java/net/runelite/api/DecorativeObject.java +++ b/runelite-api/src/main/java/net/runelite/api/DecorativeObject.java @@ -24,7 +24,7 @@ */ package net.runelite.api; -import java.awt.Polygon; +import java.awt.Shape; /** * Represents a decorative object, such as an object on a wall. @@ -37,8 +37,8 @@ public interface DecorativeObject extends TileObject * @return the convex hull * @see api.model.Jarvis */ - Polygon getConvexHull(); - Polygon getConvexHull2(); + Shape getConvexHull(); + Shape getConvexHull2(); Entity getEntity1(); Entity getEntity2(); diff --git a/runelite-api/src/main/java/net/runelite/api/GameObject.java b/runelite-api/src/main/java/net/runelite/api/GameObject.java index adb7edd3d4..46cfbc3411 100644 --- a/runelite-api/src/main/java/net/runelite/api/GameObject.java +++ b/runelite-api/src/main/java/net/runelite/api/GameObject.java @@ -24,7 +24,7 @@ */ package net.runelite.api; -import java.awt.Polygon; +import java.awt.Shape; import net.runelite.api.coords.Angle; /** @@ -54,19 +54,12 @@ public interface GameObject extends TileObject Point getSceneMaxLocation(); /** - * Gets the convex hull of the actors model. + * Gets the convex hull of the object's model. * * @return the convex hull * @see //net.runelite.api.model.Jarvis */ - Polygon getConvexHull(); - - /** - * Gets the polygons that make up the game object model. - * - * @return the model polygons - */ - Polygon[] getPolygons(); + Shape getConvexHull(); /** * Gets the orientation of the object. diff --git a/runelite-api/src/main/java/net/runelite/api/GroundObject.java b/runelite-api/src/main/java/net/runelite/api/GroundObject.java index bfd7fc34e2..39f6bce225 100644 --- a/runelite-api/src/main/java/net/runelite/api/GroundObject.java +++ b/runelite-api/src/main/java/net/runelite/api/GroundObject.java @@ -24,6 +24,8 @@ */ package net.runelite.api; +import java.awt.Shape; + /** * Represents an object on the ground of a tile. */ @@ -32,4 +34,12 @@ public interface GroundObject extends TileObject Entity getEntity(); Model getModel(); + + /** + * Gets the convex hull of the objects model. + * + * @return the convex hull + * @see net.runelite.api.model.Jarvis + */ + Shape getConvexHull(); } diff --git a/runelite-api/src/main/java/net/runelite/api/Perspective.java b/runelite-api/src/main/java/net/runelite/api/Perspective.java index 4c08e65bf1..eae51d71e5 100644 --- a/runelite-api/src/main/java/net/runelite/api/Perspective.java +++ b/runelite-api/src/main/java/net/runelite/api/Perspective.java @@ -24,24 +24,22 @@ */ package net.runelite.api; -import java.awt.geom.Path2D; -import static net.runelite.api.Constants.TILE_FLAG_BRIDGE; import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.Polygon; -import java.awt.Rectangle; -import java.awt.geom.Area; +import java.awt.Shape; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import static net.runelite.api.Constants.TILE_FLAG_BRIDGE; import net.runelite.api.coords.LocalPoint; +import net.runelite.api.geometry.RectangleUnion; +import net.runelite.api.geometry.Shapes; +import net.runelite.api.geometry.SimplePolygon; import net.runelite.api.model.Jarvis; -import net.runelite.api.model.Triangle; -import net.runelite.api.model.Vertex; import net.runelite.api.widgets.Widget; import net.runelite.api.widgets.WidgetInfo; @@ -149,7 +147,74 @@ public class Perspective } return null; + } + /** + * Translates a model's vertices into 2d space + */ + public static void modelToCanvas(Client client, int end, int x3dCenter, int y3dCenter, int z3dCenter, int rotate, int[] x3d, int[] y3d, int[] z3d, int[] x2d, int[] y2d) + { + final int + cameraPitch = client.getCameraPitch(), + cameraYaw = client.getCameraYaw(), + + pitchSin = SINE[cameraPitch], + pitchCos = COSINE[cameraPitch], + yawSin = SINE[cameraYaw], + yawCos = COSINE[cameraYaw], + rotateSin = SINE[rotate], + rotateCos = COSINE[rotate], + + cx = x3dCenter - client.getCameraX(), + cy = y3dCenter - client.getCameraY(), + cz = z3dCenter - client.getCameraZ(), + + viewportXMiddle = client.getViewportWidth() / 2, + viewportYMiddle = client.getViewportHeight() / 2, + viewportXOffset = client.getViewportXOffset(), + viewportYOffset = client.getViewportYOffset(), + + zoom3d = client.getScale(); + + for (int i = 0; i < end; i++) + { + int x = x3d[i]; + int y = y3d[i]; + int z = z3d[i]; + + if (rotate != 0) + { + int x0 = x; + x = x0 * rotateCos + y * rotateSin >> 16; + y = y * rotateCos - x0 * rotateSin >> 16; + } + + x += cx; + y += cy; + z += cz; + + final int + x1 = x * yawCos + y * yawSin >> 16, + y1 = y * yawCos - x * yawSin >> 16, + y2 = z * pitchCos - y1 * pitchSin >> 16, + z1 = y1 * pitchCos + z * pitchSin >> 16; + + int viewX, viewY; + + if (z1 < 50) + { + viewX = Integer.MIN_VALUE; + viewY = Integer.MIN_VALUE; + } + else + { + viewX = (viewportXMiddle + x1 * zoom3d / z1) + viewportXOffset; + viewY = (viewportYMiddle + y2 * zoom3d / z1) + viewportYOffset; + } + + x2d[i] = viewX; + y2d[i] = viewY; + } } /** @@ -490,244 +555,178 @@ public class Perspective * Get the on-screen clickable area of {@code model} as though it's for the * object on the tile at ({@code localX}, {@code localY}) and rotated to * angle {@code orientation}. - * - * @param client the game client - * @param model the model to calculate a clickbox for + * @param client the game client + * @param model the model to calculate a clickbox for * @param orientation the orientation of the model (0-2048, where 0 is north) - * @param point the coordinate of the tile + * @param point the coordinate of the tile * @return the clickable area of the model */ - public static @Nullable Area getClickbox(@Nonnull Client client, Model model, int orientation, @Nonnull LocalPoint point) + @Nullable + public static Shape getClickbox(@Nonnull Client client, Model model, int orientation, LocalPoint point) { if (model == null) { return null; } - List triangles = model.getTriangles().stream() - .map(triangle -> triangle.rotate(orientation)) - .collect(Collectors.toList()); + int x = point.getX(); + int y = point.getY(); + int z = getTileHeight(client, point, client.getPlane()); - List vertices = model.getVertices().stream() - .map(v -> v.rotate(orientation)) - .collect(Collectors.toList()); + SimplePolygon bounds = calculateAABB(client, model, orientation, x, y, z); - Area clickBox = get2DGeometry(client, triangles, point); - Area visibleAABB = getAABB(client, vertices, point); - - if (visibleAABB == null) + if (bounds == null) { return null; } - clickBox.intersect(visibleAABB); - return clickBox; - } - - /** - * Determine if a given point is off-screen. - * - * @param client - * @param point - * @return - */ - private static boolean isOffscreen(@Nonnull Client client, @Nonnull Point point) - { - return (point.getX() < 0 || point.getX() >= client.getViewportWidth()) - && (point.getY() < 0 || point.getY() >= client.getViewportHeight()); - } - - private static @Nonnull Area get2DGeometry( - @Nonnull Client client, - @Nonnull List triangles, - @Nonnull LocalPoint point - ) - { - int radius = 5; - Path2D.Double geometry = new Path2D.Double(); - - final int tileHeight = getTileHeight(client, point, client.getPlane()); - - for (Triangle triangle : triangles) + if (model.isClickable()) { - net.runelite.api.model.Vertex _a = triangle.getA(); - Point a = localToCanvas(client, - point.getX() - _a.getX(), - point.getY() - _a.getZ(), - tileHeight + _a.getY()); - if (a == null) - { - continue; - } - - Vertex _b = triangle.getB(); - Point b = localToCanvas(client, - point.getX() - _b.getX(), - point.getY() - _b.getZ(), - tileHeight + _b.getY()); - if (b == null) - { - continue; - } - - Vertex _c = triangle.getC(); - Point c = localToCanvas(client, - point.getX() - _c.getX(), - point.getY() - _c.getZ(), - tileHeight + _c.getY()); - if (c == null) - { - continue; - } - - if (isOffscreen(client, a) && isOffscreen(client, b) && isOffscreen(client, c)) - { - continue; - } - - int minX = Math.min(Math.min(a.getX(), b.getX()), c.getX()); - int minY = Math.min(Math.min(a.getY(), b.getY()), c.getY()); - - // For some reason, this calculation is always 4 pixels short of the actual in-client one - int maxX = Math.max(Math.max(a.getX(), b.getX()), c.getX()) + 4; - int maxY = Math.max(Math.max(a.getY(), b.getY()), c.getY()) + 4; - - Rectangle clickableRect = new Rectangle( - minX - radius, minY - radius, - maxX - minX + radius, maxY - minY + radius - ); - - if (geometry.contains(clickableRect)) - { - continue; - } - - geometry.append(clickableRect, false); + return bounds; } - return new Area(geometry); - } - - private static Area getAABB( - @Nonnull Client client, - @Nonnull List vertices, - @Nonnull LocalPoint point - ) - { - int maxX = 0; - int minX = 0; - int maxY = 0; - int minY = 0; - int maxZ = 0; - int minZ = 0; - - for (Vertex vertex : vertices) - { - int x = vertex.getX(); - int y = vertex.getY(); - int z = vertex.getZ(); - - if (x > maxX) - { - maxX = x; - } - if (x < minX) - { - minX = x; - } - - if (y > maxY) - { - maxY = y; - } - if (y < minY) - { - minY = y; - } - - if (z > maxZ) - { - maxZ = z; - } - if (z < minZ) - { - minZ = z; - } - } - - int centerX = (minX + maxX) / 2; - int centerY = (minY + maxY) / 2; - int centerZ = (minZ + maxZ) / 2; - - int extremeX = (maxX - minX + 1) / 2; - int extremeY = (maxY - minY + 1) / 2; - int extremeZ = (maxZ - minZ + 1) / 2; - - if (extremeX < 32) - { - extremeX = 32; - } - - if (extremeZ < 32) - { - extremeZ = 32; - } - - int x1 = point.getX() - (centerX - extremeX); - int y1 = centerY - extremeY; - int z1 = point.getY() - (centerZ - extremeZ); - - int x2 = point.getX() - (centerX + extremeX); - int y2 = centerY + extremeY; - int z2 = point.getY() - (centerZ + extremeZ); - - final int tileHeight = getTileHeight(client, point, client.getPlane()); - - Point p1 = localToCanvas(client, x1, z1, tileHeight + y1); - Point p2 = localToCanvas(client, x1, z2, tileHeight + y1); - Point p3 = localToCanvas(client, x2, z2, tileHeight + y1); - - Point p4 = localToCanvas(client, x2, z1, tileHeight + y1); - Point p5 = localToCanvas(client, x1, z1, tileHeight + y2); - Point p6 = localToCanvas(client, x1, z2, tileHeight + y2); - Point p7 = localToCanvas(client, x2, z2, tileHeight + y2); - Point p8 = localToCanvas(client, x2, z1, tileHeight + y2); - - List points = new ArrayList<>(8); - points.add(p1); - points.add(p2); - points.add(p3); - points.add(p4); - points.add(p5); - points.add(p6); - points.add(p7); - points.add(p8); - - try - { - points = Jarvis.convexHull(points); - } - catch (NullPointerException e) - { - // No non-null screen points for this AABB e.g. for an way off-screen model - return null; - } - - if (points == null) + Shapes bounds2d = calculate2DBounds(client, model, orientation, x, y, z); + if (bounds2d == null) { return null; } - Polygon hull = new Polygon(); - for (Point p : points) + for (SimplePolygon poly : bounds2d.getShapes()) { - if (p != null) - { - hull.addPoint(p.getX(), p.getY()); - } + poly.intersectWithConvex(bounds); } - return new Area(hull); + return bounds2d; + } + + private static SimplePolygon calculateAABB(Client client, Model m, int jauOrient, int x, int y, int z) + { + int ex = m.getExtremeX(); + if (ex == -1) + { + // dynamic models don't get stored when they render where this normally happens + m.calculateBoundsCylinder(); + m.calculateExtreme(0); + ex = m.getExtremeX(); + } + + int x1 = m.getCenterX(); + int y1 = m.getCenterZ(); + int z1 = m.getCenterY(); + + int ey = m.getExtremeZ(); + int ez = m.getExtremeY(); + + int x2 = x1 + ex; + int y2 = y1 + ey; + int z2 = z1 + ez; + + x1 -= ex; + y1 -= ey; + z1 -= ez; + + int[] xa = new int[]{ + x1, x2, x1, x2, + x1, x2, x1, x2 + }; + int[] ya = new int[]{ + y1, y1, y2, y2, + y1, y1, y2, y2 + }; + int[] za = new int[]{ + z1, z1, z1, z1, + z2, z2, z2, z2 + }; + + int[] x2d = new int[8]; + int[] y2d = new int[8]; + + modelToCanvas(client, 8, x, y, z, jauOrient, xa, ya, za, x2d, y2d); + + return Jarvis.convexHull(x2d, y2d); + } + + private static Shapes calculate2DBounds(Client client, Model m, int jauOrient, int x, int y, int z) + { + int[] x2d = new int[m.getVerticesCount()]; + int[] y2d = new int[m.getVerticesCount()]; + + Perspective.modelToCanvas(client, + m.getVerticesCount(), + x, y, z, + jauOrient, + m.getVerticesX(), m.getVerticesZ(), m.getVerticesY(), + x2d, y2d); + + final int radius = 5; + + int[][] tris = new int[][]{ + m.getTrianglesX(), + m.getTrianglesY(), + m.getTrianglesZ() + }; + + int vpX1 = client.getViewportXOffset(); + int vpY1 = client.getViewportXOffset(); + int vpX2 = vpX1 + client.getViewportWidth(); + int vpY2 = vpY1 + client.getViewportHeight(); + + List rects = new ArrayList<>(m.getTrianglesCount()); + + nextTri: + for (int tri = 0; tri < m.getTrianglesCount(); tri++) + { + int + minX = Integer.MAX_VALUE, + minY = Integer.MAX_VALUE, + maxX = Integer.MIN_VALUE, + maxY = Integer.MIN_VALUE; + + for (int[] vertex : tris) + { + final int idx = vertex[tri]; + final int xs = x2d[idx]; + final int ys = y2d[idx]; + + if (xs == Integer.MIN_VALUE || ys == Integer.MIN_VALUE) + { + continue nextTri; + } + + if (xs < minX) + { + minX = xs; + } + if (xs > maxX) + { + maxX = xs; + } + if (ys < minY) + { + minY = ys; + } + if (ys > maxY) + { + maxY = ys; + } + } + + minX -= radius; + minY -= radius; + maxX += radius; + maxY += radius; + + if (vpX1 > maxX || vpX2 < minX || vpY1 > maxY || vpY2 < minY) + { + continue; + } + + RectangleUnion.Rectangle r = new RectangleUnion.Rectangle(minX, minY, maxX, maxY); + + rects.add(r); + } + + return RectangleUnion.union(rects); } /** diff --git a/runelite-api/src/main/java/net/runelite/api/SpriteID.java b/runelite-api/src/main/java/net/runelite/api/SpriteID.java index 41af3559c4..d2667b2e85 100644 --- a/runelite-api/src/main/java/net/runelite/api/SpriteID.java +++ b/runelite-api/src/main/java/net/runelite/api/SpriteID.java @@ -1564,6 +1564,7 @@ public final class SpriteID public static final int MOBILE_FUNCTION_MODE_DISABLED = 1624; public static final int MOBILE_YELLOW_TOUCH_ANIMATION_1 = 1625; public static final int MOBILE_YELLOW_TOUCH_ANIMATION_2 = 1626; + public static final int MOBILE_FINGER_ON_INTERFACE = 1653; /* Unmapped: 1627~1701 */ public static final int BUTTON_FRIENDS = 1702; public static final int BUTTON_IGNORES = 1703; diff --git a/runelite-api/src/main/java/net/runelite/api/TileObject.java b/runelite-api/src/main/java/net/runelite/api/TileObject.java index 604b54f51d..c78fe05622 100644 --- a/runelite-api/src/main/java/net/runelite/api/TileObject.java +++ b/runelite-api/src/main/java/net/runelite/api/TileObject.java @@ -28,7 +28,7 @@ import net.runelite.api.coords.LocalPoint; import net.runelite.api.coords.WorldPoint; import java.awt.Graphics2D; import java.awt.Polygon; -import java.awt.geom.Area; +import java.awt.Shape; import javax.annotation.Nullable; /** @@ -132,5 +132,5 @@ public interface TileObject extends Locatable * @return the clickable area */ @Nullable - Area getClickbox(); + Shape getClickbox(); } diff --git a/runelite-api/src/main/java/net/runelite/api/VarPlayer.java b/runelite-api/src/main/java/net/runelite/api/VarPlayer.java index ba78672da5..f544845e8c 100644 --- a/runelite-api/src/main/java/net/runelite/api/VarPlayer.java +++ b/runelite-api/src/main/java/net/runelite/api/VarPlayer.java @@ -167,6 +167,10 @@ public enum VarPlayer MUSIC_TRACKS_UNLOCKED_18(1681), MUSIC_TRACKS_UNLOCKED_19(2065), + MUSIC_VOLUME(168), + SOUND_EFFECT_VOLUME(169), + AREA_EFFECT_VOLUME(872), + /** * f2p Quest varbits, these don't hold the completion value. */ diff --git a/runelite-api/src/main/java/net/runelite/api/WallObject.java b/runelite-api/src/main/java/net/runelite/api/WallObject.java index e5ff07a587..4e477ecc0c 100644 --- a/runelite-api/src/main/java/net/runelite/api/WallObject.java +++ b/runelite-api/src/main/java/net/runelite/api/WallObject.java @@ -24,6 +24,8 @@ */ package net.runelite.api; +import java.awt.Shape; + /** * Represents the wall of a tile, which is an un-passable boundary. */ @@ -55,4 +57,12 @@ public interface WallObject extends TileObject Model getModelA(); Model getModelB(); + + /** + * Gets the convex hull of the objects model. + * + * @return the convex hull + * @see net.runelite.api.model.Jarvis + */ + Shape getConvexHull(); } diff --git a/runelite-api/src/main/java/net/runelite/api/geometry/RectangleUnion.java b/runelite-api/src/main/java/net/runelite/api/geometry/RectangleUnion.java new file mode 100644 index 0000000000..e71f80c6b1 --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/geometry/RectangleUnion.java @@ -0,0 +1,415 @@ +/* + * Copyright (c) 2019 Abex + * 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.geometry; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import javax.annotation.Nullable; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.RequiredArgsConstructor; +import lombok.ToString; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class RectangleUnion +{ + private RectangleUnion() + { + } + + @RequiredArgsConstructor + @Getter + @ToString + public static class Rectangle + { + private final int x1, y1, x2, y2; + } + + /** + * Returns a polygon representing the union of all of the passed rectangles. + * the passed List will be modified + */ + @Nullable + public static Shapes union(List lefts) + { + // https://stackoverflow.com/a/35362615/2977136 + if (lefts.size() == 0) + { + return null; + } + + boolean trace = log.isTraceEnabled(); + + // Sort all of the rectangles so they are ordered by their left edge + lefts.sort(Comparator.comparing(Rectangle::getX1)); + + // Again, but for the right edge + // this should be relatively fast if the rectangles are similar sizes because timsort deals with partially + // presorted data well + List rights = new ArrayList<>(lefts); + rights.sort(Comparator.comparing(Rectangle::getX2)); + + // ranges of our scan line with how many rectangles it is occluding + Segments segments = new Segments(); + Shapes out = new Shapes<>(new ArrayList<>()); + ChangingState cs = new ChangingState(out); + + // Walk a beam left to right, colliding with any vertical edges of rectangles + for (int l = 0, r = 0; ; ) + { + Rectangle lr = null, rr = null; + if (l < lefts.size()) + { + lr = lefts.get(l); + } + if (r < rights.size()) + { + rr = rights.get(r); + } + if (lr == null && rr == null) + { + break; + } + + // get the next edge, preferring + edges + Rectangle rect; + boolean remove = lr == null || (rr != null && rr.x2 < lr.x1); + if (remove) + { + cs.delta = -1; + cs.x = rr.x2; + r++; + rect = rr; + } + else + { + cs.delta = 1; + cs.x = lr.x1; + l++; + rect = lr; + } + if (trace) + { + log.trace("{}{}", remove ? "-" : "+", rect); + } + + int y1 = rect.y1; + int y2 = rect.y2; + + // Find or create the y1 edge + Segment n = segments.findLE(y1); + if (n == null) + { + n = segments.insertAfter(null, y1); + } + if (n.y != y1) + { + n = segments.insertAfter(n, y1); + n.value = n.previous.value; + } + + for (; ; ) + { + // create the y2 edge if the next edge is past + if (n.next == null || n.next.y > y2) + { + segments.insertAfter(n, y2); + } + cs.touch(n); + n = n.next; + if (n.y == y2) + { + cs.finish(n); + + if (trace) + { + for (Segment s = segments.first; s != null; s = s.next) + { + String chunk = ""; + if (s.chunk != null) + { + chunk = (s.left ? ">" : "[") + System.identityHashCode(s.chunk) + (s.left ? "]" : "<"); + } + log.trace("{} = {} {}", s.y, s.value, chunk); + } + log.trace(""); + } + break; + } + } + } + + assert segments.allZero(); + + return out; + } + + @RequiredArgsConstructor + private static class ChangingState + { + final Shapes out; + + int x; + int delta; + + Segment first; + + void touch(Segment s) + { + int oldValue = s.value; + s.value += delta; + if (oldValue <= 0 ^ s.value <= 0) + { + if (first == null) + { + first = s; + } + } + else + { + finish(s); + } + } + + void finish(Segment s) + { + if (first == null) + { + return; + } + + if (first.chunk != null && s.chunk != null) + { + push(first); + push(s); + + if (first.chunk == s.chunk) + { + Chunk c = first.chunk; + first.chunk = null; + s.chunk = null; + c.left = null; + c.right = null; + out.getShapes().add(c); + } + else + { + Chunk leftChunk, rightChunk; + if (!s.left) + { + leftChunk = s.chunk; + rightChunk = first.chunk; + } + else + { + leftChunk = first.chunk; + rightChunk = s.chunk; + } + + log.trace("Joining {} onto {}", System.identityHashCode(rightChunk), System.identityHashCode(leftChunk)); + if (first.left == s.left) + { + log.trace("reverse"); + if (first.left) + { + leftChunk.reverse(); + } + else + { + rightChunk.reverse(); + } + } + log.trace("{} {}", first.y, s.y); + rightChunk.appendTo(leftChunk); + + first.chunk = null; + s.chunk = null; + leftChunk.right.chunk = null; + rightChunk.left.chunk = null; + leftChunk.right = rightChunk.right; + leftChunk.left.chunk = leftChunk; + leftChunk.right.chunk = leftChunk; + } + } + else if (first.chunk == null && s.chunk == null) + { + first.chunk = new Chunk(); + first.chunk.right = first; + first.left = false; + s.chunk = first.chunk; + first.chunk.left = s; + s.left = true; + + push(first); + push(s); + } + else if (first.chunk == null) + { + push(s); + move(first, s); + push(first); + } + else + { + push(first); + move(s, first); + push(s); + } + + first = null; + } + + private void move(Segment dst, Segment src) + { + dst.chunk = src.chunk; + dst.left = src.left; + src.chunk = null; + if (dst.left) + { + assert dst.chunk.left == src; + dst.chunk.left = dst; + } + else + { + assert dst.chunk.right == src; + dst.chunk.right = dst; + } + } + + private void push(Segment s) + { + if (s.left) + { + s.chunk.pushLeft(x, s.y); + assert s.chunk.left == s; + } + else + { + s.chunk.pushRight(x, s.y); + assert s.chunk.right == s; + } + } + } + + @NoArgsConstructor + private static class Segment + { + Segment next, previous; + + Chunk chunk; + boolean left; + int y; + int value; + } + + @NoArgsConstructor + private static class Segments + { + Segment first; + + Segment findLE(int y) + { + Segment s = first; + if (s == null || s.y > y) + { + return null; + } + for (; ; ) + { + if (s.y == y) + { + return s; + } + + Segment n = s.next; + if (n == null || n.y > y) + { + return s; + } + + s = n; + } + } + + Segment insertAfter(Segment before, int y) + { + Segment n = new Segment(); + n.y = y; + if (before != null) + { + if (before.next != null) + { + n.next = before.next; + n.next.previous = n; + } + n.value = before.value; + before.next = n; + n.previous = before; + } + else + { + if (first != null) + { + n.next = first; + first.previous = n; + } + first = n; + } + return n; + } + + boolean allZero() + { + for (Segment s = first; s != null; s = s.next) + { + if (s.value != 0 || s.chunk != null) + { + return false; + } + } + return true; + } + } + + private static class Chunk extends SimplePolygon + { + Segment left, right; + + @Override + public void reverse() + { + super.reverse(); + assert right.left == false; + assert left.left == true; + Segment tr = left; + left = right; + right = tr; + right.left = false; + left.left = true; + } + } +} diff --git a/runelite-api/src/main/java/net/runelite/api/geometry/Shapes.java b/runelite-api/src/main/java/net/runelite/api/geometry/Shapes.java new file mode 100644 index 0000000000..2e02a1cf62 --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/geometry/Shapes.java @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2019 Abex + * 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.geometry; + +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.PathIterator; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public class Shapes implements Shape +{ + public Shapes(T ...shape) + { + this(Arrays.asList(shape)); + } + + @Getter + private final List shapes; + + @Override + public Rectangle getBounds() + { + int + minX = Integer.MAX_VALUE, + minY = Integer.MAX_VALUE, + maxX = Integer.MIN_VALUE, + maxY = Integer.MIN_VALUE; + + for (Shape shape : shapes) + { + Rectangle bounds = shape.getBounds(); + minX = Math.min(bounds.x, minX); + minY = Math.min(bounds.y, minY); + maxX = Math.max(bounds.x + bounds.width, maxX); + maxY = Math.max(bounds.y + bounds.height, maxY); + } + + return new Rectangle(minX, minY, maxX - minX, maxY - minY); + } + + @Override + public Rectangle2D getBounds2D() + { + double + minX = Double.MAX_VALUE, + minY = Double.MAX_VALUE, + maxX = Double.MIN_VALUE, + maxY = Double.MIN_VALUE; + + for (Shape shape : shapes) + { + Rectangle2D bounds = shape.getBounds2D(); + minX = Math.min(bounds.getX(), minX); + minY = Math.min(bounds.getY(), minY); + maxX = Math.max(bounds.getMaxX(), maxX); + maxY = Math.max(bounds.getMaxY(), maxY); + } + + return new Rectangle2D.Double(minX, minY, maxX - minX, maxY - minY); + } + + @Override + public boolean contains(double x, double y) + { + return shapes.stream().anyMatch(s -> s.contains(x, y)); + } + + @Override + public boolean contains(Point2D p) + { + return shapes.stream().anyMatch(s -> s.contains(p)); + } + + @Override + public boolean intersects(double x, double y, double w, double h) + { + return shapes.stream().anyMatch(s -> s.intersects(x, y, w, h)); + } + + @Override + public boolean intersects(Rectangle2D r) + { + return shapes.stream().anyMatch(s -> s.intersects(r)); + } + + @Override + public boolean contains(double x, double y, double w, double h) + { + return shapes.stream().anyMatch(s -> s.contains(x, y, w, h)); + } + + @Override + public boolean contains(Rectangle2D r) + { + return shapes.stream().anyMatch(s -> s.contains(r)); + } + + @Override + public PathIterator getPathIterator(AffineTransform at) + { + return new ShapeIterator(shapes.stream() + .map(s -> s.getPathIterator(at)) + .iterator()); + } + + @Override + public PathIterator getPathIterator(AffineTransform at, double flatness) + { + return new ShapeIterator(shapes.stream() + .map(s -> s.getPathIterator(at, flatness)) + .iterator()); + } + + private static class ShapeIterator implements PathIterator + { + private final Iterator iter; + private PathIterator current = null; + private final int windingRule; + + ShapeIterator(Iterator iter) + { + this.iter = iter; + if (iter.hasNext()) + { + current = iter.next(); + windingRule = current.getWindingRule(); + checkDone(); + } + else + { + windingRule = 0; + } + } + + @Override + public int getWindingRule() + { + return windingRule; + } + + @Override + public boolean isDone() + { + return current == null; + } + + @Override + public void next() + { + current.next(); + checkDone(); + } + + private void checkDone() + { + for (; current != null && current.isDone(); ) + { + if (iter.hasNext()) + { + current = iter.next(); + assert windingRule == current.getWindingRule(); + } + else + { + current = null; + } + } + } + + @Override + public int currentSegment(float[] coords) + { + return current.currentSegment(coords); + } + + @Override + public int currentSegment(double[] coords) + { + return current.currentSegment(coords); + } + } +} diff --git a/runelite-api/src/main/java/net/runelite/api/geometry/SimplePolygon.java b/runelite-api/src/main/java/net/runelite/api/geometry/SimplePolygon.java new file mode 100644 index 0000000000..bfd136d948 --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/geometry/SimplePolygon.java @@ -0,0 +1,496 @@ +/* + * Copyright (c) 2019 Abex + * 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.geometry; + +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.PathIterator; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.util.ArrayList; +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; +import net.runelite.api.Point; + +/** + * A simple list of vertices that can be append or prepended to + */ +@AllArgsConstructor +@Getter +@Setter +public class SimplePolygon implements Shape +{ + private static final int GROW = 16; + + protected int[] x, y; + protected int left, right; + + public SimplePolygon() + { + this(new int[32], new int[32], 16, 15); + } + + public SimplePolygon(int[] x, int[] y, int length) + { + this(x, y, 0, length - 1); + } + + public void pushLeft(int xCoord, int yCoord) + { + left--; + if (left < 0) + { + expandLeft(GROW); + } + x[left] = xCoord; + y[left] = yCoord; + } + + public void popLeft() + { + left++; + } + + protected void expandLeft(int grow) + { + int[] nx = new int[x.length + grow]; + System.arraycopy(x, 0, nx, grow, x.length); + x = nx; + int[] ny = new int[nx.length]; + System.arraycopy(y, 0, ny, grow, y.length); + y = ny; + left += grow; + right += grow; + } + + public void pushRight(int xCoord, int yCoord) + { + right++; + if (right >= x.length) + { + expandRight(GROW); + } + x[right] = xCoord; + y[right] = yCoord; + } + + public void popRight() + { + right--; + } + + protected void expandRight(int grow) + { + int[] nx = new int[x.length + grow]; + System.arraycopy(x, 0, nx, 0, x.length); + x = nx; + int[] ny = new int[nx.length]; + System.arraycopy(y, 0, ny, 0, y.length); + y = ny; + } + + public int getX(int index) + { + return x[left + index]; + } + + public int getY(int index) + { + return y[left + index]; + } + + public int size() + { + return right - left + 1; + } + + public List toRuneLitePointList() + { + List out = new ArrayList<>(size()); + for (int i = left; i <= right; i++) + { + out.add(new Point(x[i], y[i])); + } + return out; + } + + public void copyTo(int[] xDest, int[] yDest, int offset) + { + System.arraycopy(x, left, xDest, offset, size()); + System.arraycopy(y, left, yDest, offset, size()); + } + + public void appendTo(SimplePolygon other) + { + int size = size(); + if (size <= 0) + { + return; + } + other.expandRight(size); + copyTo(other.x, other.y, other.right + 1); + other.right += size; + } + + public void reverse() + { + int half = size() / 2; + for (int i = 0; i < half; i++) + { + int li = left + i; + int ri = right - i; + int tx = x[li]; + int ty = y[li]; + x[li] = x[ri]; + y[li] = y[ri]; + x[ri] = tx; + y[ri] = ty; + } + } + + /** + * Clips the polygon with the passed convex polygon + */ + public void intersectWithConvex(SimplePolygon convex) + { + // Sutherland-Hodgman + int[] tx = new int[size()]; + int[] ty = new int[tx.length]; + + int cx1 = convex.x[convex.right]; + int cy1 = convex.y[convex.right]; + for (int ci = convex.left; ci <= convex.right; ci++) + { + if (size() < 3) + { + return; + } + + int tRight = this.right; + int tLeft = this.left; + + int[] tmpX = x; + int[] tmpY = y; + + this.x = tx; + this.y = ty; + this.left = 0; + this.right = -1; + tx = tmpX; + ty = tmpY; + + int cx2 = convex.x[ci]; + int cy2 = convex.y[ci]; + + int tx1 = tx[tRight]; + int ty1 = ty[tRight]; + + for (int ti = tLeft; ti <= tRight; ti++) + { + int tx2 = tx[ti]; + int ty2 = ty[ti]; + + int p1 = (cx2 - cx1) * (ty1 - cy1) - (cy2 - cy1) * (tx1 - cx1); + int p2 = (cx2 - cx1) * (ty2 - cy1) - (cy2 - cy1) * (tx2 - cx1); + + if (p1 < 0 && p2 < 0) + { + pushRight(tx2, ty2); + } + else if (p1 >= 0 != p2 >= 0) + { + long nota = cx1 * cy2 - cy1 * cx2; + long clue = tx1 * ty2 - ty1 * tx2; + long div = ((cx1 - cx2) * (ty1 - ty2) - (cy1 - cy2) * (tx1 - tx2)); + pushRight((int) ((nota * (tx1 - tx2) - (cx1 - cx2) * clue) / div), + (int) ((nota * (ty1 - ty2) - (cy1 - cy2) * clue) / div)); + + if (p1 >= 0) + { + pushRight(tx2, ty2); + } + } + + tx1 = tx2; + ty1 = ty2; + } + + cx1 = cx2; + cy1 = cy2; + } + } + + @Override + public Rectangle getBounds() + { + int + minX = Integer.MAX_VALUE, + minY = Integer.MAX_VALUE, + maxX = Integer.MIN_VALUE, + maxY = Integer.MIN_VALUE; + + for (int i = left; i <= right; i++) + { + final int xs = x[i]; + final int ys = y[i]; + + if (xs < minX) + { + minX = xs; + } + if (xs > maxX) + { + maxX = xs; + } + if (ys < minY) + { + minY = ys; + } + if (ys > maxY) + { + maxY = ys; + } + } + + return new Rectangle(minX, minY, maxX - minX, maxY - minY); + } + + @Override + public Rectangle2D getBounds2D() + { + Rectangle b = getBounds(); + return new Rectangle2D.Float(b.x, b.y, b.width, b.height); + } + + @Override + public boolean contains(double cx, double cy) + { + if (size() < 3) + { + return false; + } + + return (crossings(cx, cy, false) & 1) != 0; + } + + private int crossings(double cx, double cy, boolean swap) + { + int collisions = 0; + + int[] x = this.x; + int[] y = this.y; + if (swap) + { + y = this.x; + x = this.y; + } + + for (int x0 = x[right], y0 = y[right], x1, y1, i = left; i <= right; i++, x0 = x1, y0 = y1) + { + x1 = x[i]; + y1 = y[i]; + + if (y0 == y1) + { + continue; + } + + double dy0 = y0, dy1 = y1; + + if (cy <= dy0 == cy <= dy1) + { + continue; + } + + double dx0 = x0, dx1 = x1; + + boolean left = cx < dx0; + if (left == cx < dx1) + { + if (!left) + { + collisions++; + } + continue; + } + + if ((dx1 - dx0) * (cy - dy0) - (cx - dx0) * (dy1 - dy0) > 0 == dy0 > dy1) + { + collisions++; + } + } + return collisions; + } + + @Override + public boolean contains(Point2D p) + { + return contains(p.getX(), p.getY()); + } + + @Override + public boolean intersects(double x0, double y0, double w, double h) + { + // this is horribly inefficient, but I don't think it will be called anywhere + + double x1 = x0 + w; + double y1 = y0 + h; + + return crossings(x0, y0, false) != crossings(x1, y0, false) // top + || crossings(x0, y1, false) != crossings(x1, y1, false) // bottom + || crossings(x0, y0, true) != crossings(x0, y1, true) // left + || crossings(x1, y0, true) != crossings(x1, y1, true); // right + + } + + @Override + public boolean intersects(Rectangle2D r) + { + return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight()); + } + + @Override + public boolean contains(double x, double y, double w, double h) + { + if (!getBounds().contains(x, y, w, h)) + { + return false; + } + + return !intersects(x, y, w, h); + } + + @Override + public boolean contains(Rectangle2D r) + { + return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight()); + } + + + @Override + public PathIterator getPathIterator(AffineTransform at) + { + if (at == null) + { + return new SimpleIterator(); + } + return new TransformIterator(at); + } + + @Override + public PathIterator getPathIterator(AffineTransform at, double flatness) + { + return getPathIterator(at); + } + + private class SimpleIterator implements PathIterator + { + private int i = -1; + + @Override + public int getWindingRule() + { + return WIND_EVEN_ODD; + } + + @Override + public boolean isDone() + { + return size() == 0 || i > right; + } + + @Override + public void next() + { + if (i == -1) + { + i = left; + } + else + { + i++; + } + } + + @Override + public int currentSegment(float[] coords) + { + if (i == -1) + { + coords[0] = x[right]; + coords[1] = y[right]; + return SEG_MOVETO; + } + + coords[0] = x[i]; + coords[1] = y[i]; + return SEG_LINETO; + } + + @Override + public int currentSegment(double[] coords) + { + if (i == -1) + { + coords[0] = x[right]; + coords[1] = y[right]; + return SEG_MOVETO; + } + + coords[0] = x[i]; + coords[1] = y[i]; + return SEG_LINETO; + } + } + + private class TransformIterator extends SimpleIterator + { + private final AffineTransform transform; + + TransformIterator(AffineTransform transform) + { + this.transform = transform; + } + + @Override + public int currentSegment(float[] coords) + { + int v = super.currentSegment(coords); + transform.transform(coords, 0, coords, 0, 2); + return v; + } + + @Override + public int currentSegment(double[] coords) + { + int v = super.currentSegment(coords); + transform.transform(coords, 0, coords, 0, 2); + return v; + } + } +} diff --git a/runelite-api/src/main/java/net/runelite/api/model/Jarvis.java b/runelite-api/src/main/java/net/runelite/api/model/Jarvis.java index 5435470c37..3d2cd2b6aa 100644 --- a/runelite-api/src/main/java/net/runelite/api/model/Jarvis.java +++ b/runelite-api/src/main/java/net/runelite/api/model/Jarvis.java @@ -24,9 +24,9 @@ */ package net.runelite.api.model; -import net.runelite.api.Point; -import java.util.ArrayList; import java.util.List; +import net.runelite.api.Point; +import net.runelite.api.geometry.SimplePolygon; /** * Provides utility methods for computing the convex hull of a list of @@ -41,91 +41,147 @@ public class Jarvis /** * Computes and returns the convex hull of the passed points. *

- * The size of the list must be at least 4, otherwise this method will + * The size of the list must be at least 3, otherwise this method will * return null. * * @param points list of points * @return list containing the points part of the convex hull */ + @Deprecated public static List convexHull(List points) { - if (points.size() < 3) + int[] xs = new int[points.size()]; + int[] ys = new int[xs.length]; + for (int i = 0; i < xs.length; i++) + { + Point p = points.get(i); + xs[i] = p.getX(); + ys[i] = p.getY(); + } + + SimplePolygon poly = convexHull(xs, ys); + if (poly == null) { return null; } - List ch = new ArrayList<>(); + return poly.toRuneLitePointList(); + } + + /** + * Computes and returns the convex hull of the passed points. + *

+ * The size of the list must be at least 3, otherwise this method will + * return null. + * + * @return a shape the points part of the convex hull + */ + public static SimplePolygon convexHull(int[] xs, int[] ys) + { + int length = xs.length; + + // remove any invalid entries + { + int i = 0, offset = 0; + for (; i < length; i++) + { + if (xs[i] == Integer.MIN_VALUE) + { + offset++; + i++; + break; + } + } + for (; i < length; i++) + { + if (xs[i] == Integer.MIN_VALUE) + { + offset++; + continue; + } + xs[i - offset] = xs[i]; + ys[i - offset] = ys[i]; + } + length -= offset; + } + + if (length < 3) + { + return null; + } // find the left most point - Point left = findLeftMost(points); + int left = findLeftMost(xs, ys, length); // current point we are on - Point current = left; + int current = left; + + SimplePolygon out = new SimplePolygon(new int[16], new int[16], 0); do { - ch.add(current); - assert ch.size() <= points.size() : "hull has more points than graph"; - if (ch.size() > points.size()) + int cx = xs[current]; + int cy = ys[current]; + out.pushRight(cx, cy); + + if (out.size() > length) { - // Just to make sure we never somehow get stuck in this loop return null; } // the next point - all points are to the right of the // line between current and next - Point next = null; + int next = 0; + int nx = xs[next]; + int ny = ys[next]; - for (Point p : points) + for (int i = 1; i < length; i++) { - if (next == null) + long cp = crossProduct(cx, cy, xs[i], ys[i], nx, ny); + if (cp > 0 || (cp == 0 && square(cx - xs[i]) + square(cy - ys[i]) > square(cx - nx) + square(cy - ny))) { - next = p; - continue; + next = i; + nx = xs[next]; + ny = ys[next]; } - - long cp = crossProduct(current, p, next); - if (cp > 0 || (cp == 0 && current.distanceTo(p) > current.distanceTo(next))) - { - next = p; - } - } - - // Points can be null if they are behind or very close to the camera. - if (next == null) - { - return null; } current = next; } while (current != left); - return ch; + return out; } - private static Point findLeftMost(List points) + private static int square(int x) { - Point left = null; + return x * x; + } - for (Point p : points) + private static int findLeftMost(int[] xs, int[] ys, int length) + { + int idx = 0; + int x = xs[idx]; + int y = ys[idx]; + + for (int i = 1; i < length; i++) { - if (left == null || p.getX() < left.getX()) + int ix = xs[i]; + if (ix < x || ix == x && ys[i] < y) { - left = p; - } - else if (p.getX() == left.getX() && p.getY() < left.getY()) - { - left = p; + idx = i; + x = xs[idx]; + y = ys[idx]; } } - return left; + return idx; } - private static long crossProduct(Point p, Point q, Point r) + private static long crossProduct(int px, int py, int qx, int qy, int rx, int ry) { - return (long)(q.getY() - p.getY()) * (r.getX() - q.getX()) - - (long)(q.getX() - p.getX()) * (r.getY() - q.getY()); + long val = (long) (qy - py) * (rx - qx) + - (long) (qx - px) * (ry - qy); + return val; } -} +} \ No newline at end of file diff --git a/runelite-api/src/test/java/net/runelite/api/geometry/RectangleUnionTest.java b/runelite-api/src/test/java/net/runelite/api/geometry/RectangleUnionTest.java new file mode 100644 index 0000000000..df678b350a --- /dev/null +++ b/runelite-api/src/test/java/net/runelite/api/geometry/RectangleUnionTest.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2019 Abex + * 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.geometry; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import javax.imageio.ImageIO; +import org.junit.Assert; +import org.junit.Test; + +public class RectangleUnionTest +{ + private static final int ITERATIONS = 100; + private static final int WIDTH = 1000; + private static final int MAX_RECTS = 50; + + @Test + public void test() throws IOException + { + for (int count = 1; count < MAX_RECTS; count++) + { + for (int r = 0; r < ITERATIONS; r++) + { + Random rand = new Random(count << 16 | r); + String id = count + "rects_iteration" + r; + + BufferedImage wanted = new BufferedImage(WIDTH, WIDTH, BufferedImage.TYPE_BYTE_BINARY); + BufferedImage got = new BufferedImage(WIDTH, WIDTH, BufferedImage.TYPE_BYTE_BINARY); + + Graphics2D wg = wanted.createGraphics(); + wg.setColor(Color.WHITE); + Graphics2D gg = got.createGraphics(); + gg.setColor(Color.WHITE); + + List rects = new ArrayList<>(count); + + for (int i = 0; i < count; i++) + { + int x1, y1, x2, y2; + + do + { + x1 = rand.nextInt(WIDTH); + x2 = rand.nextInt(WIDTH); + } + while (x1 >= x2); + + do + { + y1 = rand.nextInt(WIDTH); + y2 = rand.nextInt(WIDTH); + } + while (y1 >= y2); + + RectangleUnion.Rectangle rect = new RectangleUnion.Rectangle(x1, y1, x2, y2); + rects.add(rect); + + wg.fillRect(x1, y1, x2 - x1, y2 - y1); + } + + Shape union = RectangleUnion.union(rects); + + gg.fill(union); + + loop: + for (int x = 0; x < WIDTH; x++) + { + for (int y = 0; y < WIDTH; y++) + { + if (wanted.getRGB(x, y) != got.getRGB(x, y)) + { + File tmp = new File(System.getProperty("java.io.tmpdir")); + ImageIO.write(wanted, "png", new File(tmp, id + "_wanted.png")); + ImageIO.write(got, "png", new File(tmp, id + "_got.png")); + + Assert.fail(id); + break loop; + } + } + } + } + } + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/RuneLite.java b/runelite-client/src/main/java/net/runelite/client/RuneLite.java index 38f37f4e7e..511b00f1a2 100644 --- a/runelite-client/src/main/java/net/runelite/client/RuneLite.java +++ b/runelite-client/src/main/java/net/runelite/client/RuneLite.java @@ -46,11 +46,14 @@ import joptsimple.util.EnumConverter; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import net.runelite.api.Client; +import net.runelite.api.events.GameStateChanged; import net.runelite.client.account.SessionManager; +import net.runelite.client.callback.Hooks; import net.runelite.client.chat.ChatMessageManager; import net.runelite.client.chat.CommandManager; import net.runelite.client.config.ConfigManager; import net.runelite.client.discord.DiscordService; +import net.runelite.client.eventbus.EventBus; import net.runelite.client.game.ClanManager; import net.runelite.client.game.ItemManager; import net.runelite.client.game.LootManager; @@ -148,6 +151,12 @@ public class RuneLite @Inject private Provider chatboxPanelManager; + @Inject + private Hooks hooks; + + @Inject + private EventBus eventBus; + @Inject @Nullable private Client client; @@ -348,6 +357,8 @@ public class RuneLite lootManager.get(); chatboxPanelManager.get(); + eventBus.subscribe(GameStateChanged.class, this, hooks::onGameStateChanged); + // Add core overlays WidgetOverlay.createOverlays(client).forEach(overlayManager::add); overlayManager.add(infoBoxOverlay.get()); diff --git a/runelite-client/src/main/java/net/runelite/client/RuneLiteModule.java b/runelite-client/src/main/java/net/runelite/client/RuneLiteModule.java index 611064f162..d6749dcdb3 100644 --- a/runelite-client/src/main/java/net/runelite/client/RuneLiteModule.java +++ b/runelite-client/src/main/java/net/runelite/client/RuneLiteModule.java @@ -28,6 +28,7 @@ import com.google.inject.AbstractModule; import com.google.inject.Provides; import com.google.inject.name.Names; import java.applet.Applet; +import java.io.File; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import javax.annotation.Nullable; @@ -51,12 +52,15 @@ import net.runelite.client.task.Scheduler; import net.runelite.client.util.DeferredEventBus; import net.runelite.client.util.ExecutorServiceExceptionLogger; import net.runelite.http.api.RuneLiteAPI; +import okhttp3.Cache; import okhttp3.OkHttpClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class RuneLiteModule extends AbstractModule { + private static final int MAX_OKHTTP_CACHE_SIZE = 20 * 1024 * 1024; // 20mb + private final ClientUpdateCheckMode updateCheckMode; private final boolean developerMode; @@ -72,7 +76,9 @@ public class RuneLiteModule extends AbstractModule bindConstant().annotatedWith(Names.named("updateCheckMode")).to(updateCheckMode); bindConstant().annotatedWith(Names.named("developerMode")).to(developerMode); bind(ScheduledExecutorService.class).toInstance(new ExecutorServiceExceptionLogger(Executors.newSingleThreadScheduledExecutor())); - bind(OkHttpClient.class).toInstance(RuneLiteAPI.CLIENT); + bind(OkHttpClient.class).toInstance(RuneLiteAPI.CLIENT.newBuilder() + .cache(new Cache(new File(RuneLite.RUNELITE_DIR, "cache" + File.separator + "okhttp"), MAX_OKHTTP_CACHE_SIZE)) + .build()); bind(MenuManager.class); bind(ChatMessageManager.class); bind(ItemManager.class); diff --git a/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java b/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java index 1a97b5ea6c..94648a1f68 100644 --- a/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java +++ b/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java @@ -51,6 +51,7 @@ import net.runelite.api.WorldMapManager; import net.runelite.api.events.BeforeMenuRender; import net.runelite.api.events.BeforeRender; import net.runelite.api.events.Event; +import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.GameTick; import net.runelite.api.hooks.Callbacks; import net.runelite.api.hooks.DrawCallbacks; @@ -126,6 +127,7 @@ public class Hooks implements Callbacks private Graphics2D stretchedGraphics; private long lastCheck; + private boolean ignoreNextNpcUpdate; private boolean shouldProcessGameTick; private static MainBufferProvider lastMainBufferProvider; @@ -459,15 +461,36 @@ public class Hooks implements Callbacks overlayManager.getItemWidgets().clear(); } + public void onGameStateChanged(GameStateChanged gameStateChanged) + { + switch (gameStateChanged.getGameState()) + { + case LOGGING_IN: + case HOPPING: + ignoreNextNpcUpdate = true; + } + } + @Override public void updateNpcs() { - // The NPC update event seem to run every server tick, - // but having the game tick event after all packets - // have been processed is typically more useful. - shouldProcessGameTick = true; + if (ignoreNextNpcUpdate) + { + // After logging in an NPC update happens outside of the normal game tick, which + // is sent prior to skills and vars being bursted, so ignore it. + ignoreNextNpcUpdate = false; + log.debug("Skipping login updateNpc"); + } + else + { + // The NPC update event seem to run every server tick, + // but having the game tick event after all packets + // have been processed is typically more useful. + shouldProcessGameTick = true; + } + // Replay deferred events, otherwise if two npc - // update packets get processed in one frame, a + // update packets get processed in one client tick, a // despawn event could be published prior to the // spawn event, which is deferred deferredEventBus.replay(); diff --git a/runelite-client/src/main/java/net/runelite/client/game/ItemManager.java b/runelite-client/src/main/java/net/runelite/client/game/ItemManager.java index 3b8df74e93..ae4885842d 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/ItemManager.java +++ b/runelite-client/src/main/java/net/runelite/client/game/ItemManager.java @@ -136,7 +136,7 @@ public class ItemManager private final Client client; private final ScheduledExecutorService scheduledExecutorService; private final ClientThread clientThread; - private final ItemClient itemClient = new ItemClient(); + private final ItemClient itemClient; private final ImmutableMap itemStatMap; private final LoadingCache itemImages; private final LoadingCache itemDefinitions; @@ -149,12 +149,14 @@ public class ItemManager Client client, ScheduledExecutorService executor, ClientThread clientThread, - EventBus eventbus + EventBus eventbus, + ItemClient itemClient ) { this.client = client; this.scheduledExecutorService = executor; this.clientThread = clientThread; + this.itemClient = itemClient; scheduledExecutorService.scheduleWithFixedDelay(this::loadPrices, 0, 30, TimeUnit.MINUTES); scheduledExecutorService.submit(this::loadStats); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityOverlay.java index 7180914d79..9323ae0b44 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityOverlay.java @@ -29,7 +29,7 @@ import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Polygon; -import java.awt.geom.Area; +import java.awt.Shape; import java.util.List; import javax.inject.Inject; import javax.inject.Singleton; @@ -90,7 +90,7 @@ class AgilityOverlay extends Overlay } return; } - Area objectClickbox = object.getClickbox(); + Shape objectClickbox = object.getClickbox(); if (objectClickbox != null) { AgilityShortcut agilityShortcut = obstacle.getShortcut(); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/blastfurnace/BlastFurnaceClickBoxOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/blastfurnace/BlastFurnaceClickBoxOverlay.java index 4e7b818f90..7d2dce821d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/blastfurnace/BlastFurnaceClickBoxOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/blastfurnace/BlastFurnaceClickBoxOverlay.java @@ -27,7 +27,7 @@ package net.runelite.client.plugins.blastfurnace; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; -import java.awt.geom.Area; +import java.awt.Shape; import javax.inject.Inject; import javax.inject.Singleton; import net.runelite.api.Client; @@ -110,7 +110,7 @@ class BlastFurnaceClickBoxOverlay extends Overlay if (localLocation.distanceTo(location) <= MAX_DISTANCE) { - Area objectClickbox = object.getClickbox(); + Shape objectClickbox = object.getClickbox(); if (objectClickbox != null) { if (objectClickbox.contains(mousePosition.getX(), mousePosition.getY())) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CoordinateClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CoordinateClue.java index 55735a3767..039e70770c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CoordinateClue.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CoordinateClue.java @@ -94,13 +94,13 @@ public class CoordinateClue extends ClueScroll implements TextClueScroll, Locati .put(new WorldPoint(3544, 3256, 0), "North-east of Burgh de Rott.") .put(new WorldPoint(2841, 3267, 0), "Crandor island.") .put(new WorldPoint(3168, 3041, 0), "Bedabin Camp.") - .put(new WorldPoint(2542, 3031, 0), "Gu'Tanoth.") + .put(new WorldPoint(2542, 3031, 0), "Gu'Tanoth, may require 20gp.") .put(new WorldPoint(2581, 3030, 0), "Gu'Tanoth island, enter cave north-west of Feldip Hills (AKS).") .put(new WorldPoint(2961, 3024, 0), "Ship yard (DKP).") .put(new WorldPoint(2339, 3311, 0), "East of Prifddinas on Arandar mountain pass.") .put(new WorldPoint(3440, 3341, 0), "Nature Spirit's grotto.") .put(new WorldPoint(2763, 2974, 0), "Cairn Isle, west of Shilo Village.") - .put(new WorldPoint(3138, 2969, 0), "West of Bandit Camp.") + .put(new WorldPoint(3138, 2969, 0), "West of Bandit Camp in Kharidian Desert.") .put(new WorldPoint(2924, 2963, 0), "On the southern part of eastern Karamja.") .put(new WorldPoint(2838, 2914, 0), "Kharazi Jungle, near water pool.") .put(new WorldPoint(3441, 3419, 0), "Mort Myre Swamp.") diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/EmoteClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/EmoteClue.java index ceb8df6df2..87deb91231 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/EmoteClue.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/EmoteClue.java @@ -142,8 +142,7 @@ public class EmoteClue extends ClueScroll implements TextClueScroll, LocationClu new EmoteClue("Panic on the pier where you catch the Fishing trawler. Have nothing equipped at all when you do.", "Fishing trawler", null, new WorldPoint(2676, 3169, 0), PANIC, emptySlot("Nothing at all", HEAD, CAPE, AMULET, WEAPON, BODY, SHIELD, LEGS, GLOVES, BOOTS, RING, AMMO)), new EmoteClue("Panic on the Wilderness volcano bridge. Beware of double agents! Equip any headband and crozier.", "Wilderness volcano", VOLCANO_IN_THE_NORTHEASTERN_WILDERNESS, new WorldPoint(3368, 3935, 0), PANIC, any("Any headband", range(RED_HEADBAND, BROWN_HEADBAND), range(WHITE_HEADBAND, GREEN_HEADBAND)), any("Any crozier", item(ANCIENT_CROZIER), item(ARMADYL_CROZIER), item(BANDOS_CROZIER), range(SARADOMIN_CROZIER, ZAMORAK_CROZIER))), new EmoteClue("Do a push up at the bank of the Warrior's guild. Beware of double agents! Equip a dragon battleaxe, a dragon defender and a slayer helm of any kind.", "Warriors' guild", WARRIORS_GUILD_BANK_29047, new WorldPoint(2843, 3543, 0), PUSH_UP, item(DRAGON_BATTLEAXE), item(DRAGON_DEFENDER), any("Any slayer helmet", item(SLAYER_HELMET), item(BLACK_SLAYER_HELMET), item(GREEN_SLAYER_HELMET), item(PURPLE_SLAYER_HELMET), item(RED_SLAYER_HELMET), item(TURQUOISE_SLAYER_HELMET), item(SLAYER_HELMET_I), item(BLACK_SLAYER_HELMET_I), item(GREEN_SLAYER_HELMET_I), item(PURPLE_SLAYER_HELMET_I), item(RED_SLAYER_HELMET_I), item(TURQUOISE_SLAYER_HELMET_I), item(HYDRA_SLAYER_HELMET), item(HYDRA_SLAYER_HELMET_I))), - new EmoteClue("Blow a raspberry at Gypsy Aris in her tent. Equip a gold ring and a gold necklace.", "Varrock", GYPSY_TENT_ENTRANCE, new WorldPoint(3203, 3424, 0), RASPBERRY, item(GOLD_RING), item(GOLD_NECKLACE)), - new EmoteClue("Blow a raspberry at the bank of the Warrior's guild. Beware of double agents! Equip a dragon battleaxe, a slayer helm of any kind and a dragon defender or avernic defender.", "Warriors' guild", WARRIORS_GUILD_BANK_29047, new WorldPoint(2843, 3543, 0), RASPBERRY, item(DRAGON_BATTLEAXE), any("Dragon defender or Avernic defender", item(DRAGON_DEFENDER), item(AVERNIC_DEFENDER)), any("Any slayer helmet", item(SLAYER_HELMET), item(BLACK_SLAYER_HELMET), item(GREEN_SLAYER_HELMET), item(PURPLE_SLAYER_HELMET), item(RED_SLAYER_HELMET), item(TURQUOISE_SLAYER_HELMET), item(SLAYER_HELMET_I), item(BLACK_SLAYER_HELMET_I), item(GREEN_SLAYER_HELMET_I), item(PURPLE_SLAYER_HELMET_I), item(RED_SLAYER_HELMET_I), item(TURQUOISE_SLAYER_HELMET_I), item(HYDRA_SLAYER_HELMET), item(HYDRA_SLAYER_HELMET_I))), + new EmoteClue("Blow a raspberry in the bank of the Warriors' Guild. Beware of double agents! Equip a dragon battleaxe, a slayer helm of any kind and a dragon defender or avernic defender.", "Warriors' guild", WARRIORS_GUILD_BANK_29047, new WorldPoint(2843, 3543, 0), RASPBERRY, item(DRAGON_BATTLEAXE), any("Dragon defender or Avernic defender", item(DRAGON_DEFENDER), item(AVERNIC_DEFENDER)), any("Any slayer helmet", item(SLAYER_HELMET), item(BLACK_SLAYER_HELMET), item(GREEN_SLAYER_HELMET), item(PURPLE_SLAYER_HELMET), item(RED_SLAYER_HELMET), item(TURQUOISE_SLAYER_HELMET), item(SLAYER_HELMET_I), item(BLACK_SLAYER_HELMET_I), item(GREEN_SLAYER_HELMET_I), item(PURPLE_SLAYER_HELMET_I), item(RED_SLAYER_HELMET_I), item(TURQUOISE_SLAYER_HELMET_I), item(HYDRA_SLAYER_HELMET), item(HYDRA_SLAYER_HELMET_I))), new EmoteClue("Blow a raspberry at the monkey cage in Ardougne Zoo. Equip a studded leather body, bronze platelegs and a normal staff with no orb.", "Ardougne Zoo", NEAR_THE_PARROTS_IN_ARDOUGNE_ZOO, new WorldPoint(2607, 3282, 0), RASPBERRY, item(STUDDED_BODY), item(BRONZE_PLATELEGS), item(STAFF)), new EmoteClue("Blow a raspberry in the Fishing Guild bank. Beware of double agents! Equip an elemental shield, blue dragonhide chaps and a rune warhammer.", "Fishing Guild", FISHING_GUILD_BANK, new WorldPoint(2588, 3419, 0), RASPBERRY, item(ELEMENTAL_SHIELD), item(BLUE_DHIDE_CHAPS), item(RUNE_WARHAMMER)), new EmoteClue("Blow raspberries outside the entrance to Keep Le Faye. Equip a coif, an iron platebody and leather gloves.", "Keep Le Faye", OUTSIDE_KEEP_LE_FAYE, new WorldPoint(2757, 3401, 0), RASPBERRY, item(COIF), item(IRON_PLATEBODY), item(LEATHER_GLOVES)), @@ -158,7 +157,7 @@ public class EmoteClue extends ClueScroll implements TextClueScroll, LocationClu new EmoteClue("Spin at Flynn's Mace Shop.", "Falador", null, new WorldPoint(2950, 3387, 0), SPIN), new EmoteClue("Spin at the crossroads north of Rimmington. Equip a green gnome hat, cream gnome top and leather chaps.", "Rimmington", ROAD_JUNCTION_NORTH_OF_RIMMINGTON, new WorldPoint(2981, 3276, 0), SPIN, item(GREEN_HAT), item(CREAM_ROBE_TOP), item(LEATHER_CHAPS)), new EmoteClue("Spin in Draynor Manor by the fountain. Equip an iron platebody, studded leather chaps and a bronze full helmet.", "Draynor Manor", DRAYNOR_MANOR_BY_THE_FOUNTAIN, new WorldPoint(3088, 3336, 0), SPIN, item(IRON_PLATEBODY), item(STUDDED_CHAPS), item(BRONZE_FULL_HELM)), - new EmoteClue("Spin in front of the Soul altar. Beware of double agents! Equip a dragon pickaxe, helm of neitiznot and a pair of rune boots.", "Soul altar", SOUL_ALTAR, new WorldPoint(1815, 3856, 0), SPIN, any("Dragon pickaxe", item(DRAGON_PICKAXE), item(DRAGON_PICKAXE_12797), item(INFERNAL_PICKAXE), item(INFERNAL_PICKAXE_UNCHARGED), item(DRAGON_PICKAXEOR)), item(HELM_OF_NEITIZNOT), item(RUNE_BOOTS)), + new EmoteClue("Spin in front of the Soul altar. Beware of double agents! Equip a dragon pickaxe, helm of neitiznot and a pair of rune boots.", "Soul altar", SOUL_ALTAR, new WorldPoint(1815, 3856, 0), SPIN, any("Dragon or Crystal pickaxe", item(DRAGON_PICKAXE), item(DRAGON_PICKAXE_12797), item(INFERNAL_PICKAXE), item(INFERNAL_PICKAXE_UNCHARGED), item(DRAGON_PICKAXEOR), item(CRYSTAL_PICKAXE), item(CRYSTAL_PICKAXE_INACTIVE)), item(HELM_OF_NEITIZNOT), item(RUNE_BOOTS)), new EmoteClue("Spin in the Varrock Castle courtyard. Equip a black axe, a coif and a ruby ring.", "Varrock Castle", OUTSIDE_VARROCK_PALACE_COURTYARD, new WorldPoint(3213, 3463, 0), SPIN, item(BLACK_AXE), item(COIF), item(RUBY_RING)), new EmoteClue("Spin in West Ardougne Church. Equip a dragon spear and red dragonhide chaps.", "Ardougne", CHAPEL_IN_WEST_ARDOUGNE, new WorldPoint(2530, 3290, 0), SPIN, item(DRAGON_SPEAR), item(RED_DHIDE_CHAPS)), new EmoteClue("Spin on the bridge by the Barbarian Village. Salute before you talk to me. Equip purple gloves, a steel kiteshield and a mithril full helmet.", "Barbarian Village", EAST_OF_THE_BARBARIAN_VILLAGE_BRIDGE, new WorldPoint(3105, 3420, 0), SPIN, SALUTE, item(PURPLE_GLOVES), item(STEEL_KITESHIELD), item(MITHRIL_FULL_HELM)), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/SkillChallengeClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/SkillChallengeClue.java index df10aa06cc..2c75d1a49e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/SkillChallengeClue.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/SkillChallengeClue.java @@ -140,7 +140,7 @@ public class SkillChallengeClue extends ClueScroll implements NpcClueScroll new SkillChallengeClue("Chop a yew tree.", ANY_AXE), new SkillChallengeClue("Fix a magical lamp in Dorgesh-Kaan.", item(ItemID.LIGHT_ORB)), new SkillChallengeClue("Burn a yew log.", item(ItemID.YEW_LOGS), item(ItemID.TINDERBOX)), - new SkillChallengeClue("Catch and cook a swordfish.", "cook a swordfish.", ANY_HARPOON), + new SkillChallengeClue("Cook a swordfish", "cook a swordfish", item(ItemID.RAW_SWORDFISH)), new SkillChallengeClue("Craft multiple cosmic runes from a single essence.", item(ItemID.PURE_ESSENCE)), new SkillChallengeClue("Plant a watermelon seed.", item(ItemID.RAKE), item(ItemID.SEED_DIBBER), xOfItem(ItemID.WATERMELON_SEED, 3)), new SkillChallengeClue("Activate the Chivalry prayer."), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/defaultworld/DefaultWorldPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/defaultworld/DefaultWorldPlugin.java index 39614234bd..cb5272a491 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/defaultworld/DefaultWorldPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/defaultworld/DefaultWorldPlugin.java @@ -63,7 +63,9 @@ public class DefaultWorldPlugin extends Plugin @Inject private ClientThread clientThread; - private final WorldClient worldClient = new WorldClient(); + @Inject + private WorldClient worldClient; + private int worldCache; private boolean worldChangeRequired; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsOverlay.java index 268f7784ff..eba53c5838 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsOverlay.java @@ -32,6 +32,7 @@ import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.Polygon; import java.awt.Rectangle; +import java.awt.Shape; import java.awt.geom.Rectangle2D; import java.util.List; import javax.inject.Inject; @@ -326,10 +327,10 @@ class DevToolsOverlay extends Overlay // Draw a polygon around the convex hull // of the model vertices - Polygon p = gameObject.getConvexHull(); + Shape p = gameObject.getConvexHull(); if (p != null) { - graphics.drawPolygon(p); + graphics.draw(p); } // This is incredibly taxing to run, only uncomment if you know what you're doing. /*renderGameObjectWireframe(graphics, gameObject, Color.CYAN);*/ @@ -372,16 +373,16 @@ class DevToolsOverlay extends Overlay OverlayUtil.renderTileOverlay(graphics, decorObject, "ID: " + decorObject.getId(), DEEP_PURPLE); } - Polygon p = decorObject.getConvexHull(); + Shape p = decorObject.getConvexHull(); if (p != null) { - graphics.drawPolygon(p); + graphics.draw(p); } p = decorObject.getConvexHull2(); if (p != null) { - graphics.drawPolygon(p); + graphics.draw(p); } } } @@ -553,23 +554,6 @@ class DevToolsOverlay extends Overlay graphics.drawString(text, textX, textY); } - private void renderGameObjectWireframe(Graphics2D graphics, GameObject gameObject, Color color) - { - Polygon[] polys = gameObject.getPolygons(); - - if (polys == null) - { - return; - } - - graphics.setColor(color); - - for (Polygon p : polys) - { - graphics.drawPolygon(p); - } - } - private void renderPlayerWireframe(Graphics2D graphics, Player player, Color color) { Polygon[] polys = player.getPolygons(); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/feed/FeedPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/feed/FeedPlugin.java index f7a6337aa5..6032056fc8 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/feed/FeedPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/feed/FeedPlugin.java @@ -66,13 +66,15 @@ public class FeedPlugin extends Plugin @Inject private ScheduledExecutorService executorService; + @Inject + private FeedClient feedClient; + @Inject private EventBus eventBus; private FeedPanel feedPanel; private NavigationButton navButton; - private final FeedClient feedClient = new FeedClient(); private final Supplier feedSupplier = Suppliers.memoizeWithExpiration(() -> { try diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/gauntlet/GauntletOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/gauntlet/GauntletOverlay.java index 5345b5ced3..a65a72a335 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/gauntlet/GauntletOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/gauntlet/GauntletOverlay.java @@ -32,6 +32,7 @@ import java.awt.Font; import java.awt.Graphics2D; import java.awt.Polygon; import java.awt.Rectangle; +import java.awt.Shape; import java.awt.image.BufferedImage; import java.util.ArrayList; import java.util.List; @@ -201,7 +202,7 @@ public class GauntletOverlay extends Overlay if (plugin.isOverlayBoss()) { - Polygon polygon = boss.getConvexHull(); + Shape polygon = boss.getConvexHull(); if (polygon == null) { @@ -315,7 +316,7 @@ public class GauntletOverlay extends Overlay { // Don't use Convex Hull click box. As the room start to fill up, your FPS will dip. - Polygon polygon = object.getGameObject().getConvexHull(); + Shape polygon = object.getGameObject().getConvexHull(); if (polygon == null) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcSceneOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcSceneOverlay.java index a9a687d3bc..89d3cf051d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcSceneOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcSceneOverlay.java @@ -30,6 +30,7 @@ import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Polygon; +import java.awt.Shape; import java.text.DecimalFormat; import java.text.NumberFormat; import java.time.Instant; @@ -46,12 +47,12 @@ import net.runelite.api.Point; import net.runelite.api.coords.LocalPoint; import net.runelite.api.coords.WorldArea; import net.runelite.api.coords.WorldPoint; +import net.runelite.api.util.Text; import net.runelite.client.graphics.ModelOutlineRenderer; 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.OverlayUtil; -import net.runelite.api.util.Text; @Singleton public class NpcSceneOverlay extends Overlay @@ -181,8 +182,9 @@ public class NpcSceneOverlay extends Overlay renderPoly(graphics, color, tilePoly); break; case HULL: - final Polygon objectClickbox = actor.getConvexHull(); - renderPoly(graphics, color, objectClickbox); + final Shape objectClickbox = actor.getConvexHull(); + graphics.setColor(color); + graphics.draw(objectClickbox); break; case THIN_OUTLINE: modelOutliner.drawOutline(actor, 1, color); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/objectindicators/ObjectIndicatorsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/objectindicators/ObjectIndicatorsOverlay.java index e9ac6d354a..7e5e58701d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/objectindicators/ObjectIndicatorsOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/objectindicators/ObjectIndicatorsOverlay.java @@ -28,8 +28,7 @@ package net.runelite.client.plugins.objectindicators; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; -import java.awt.Polygon; -import java.awt.geom.Area; +import java.awt.Shape; import static java.lang.Math.floor; import javax.inject.Inject; import javax.inject.Singleton; @@ -101,8 +100,8 @@ class ObjectIndicatorsOverlay extends Overlay } break; case HULL: - final Polygon polygon; - Polygon polygon2 = null; + final Shape polygon; + Shape polygon2 = null; if (object instanceof GameObject) { @@ -129,7 +128,7 @@ class ObjectIndicatorsOverlay extends Overlay } break; case CLICKBOX: - Area clickbox = object.getClickbox(); + Shape clickbox = object.getClickbox(); if (clickbox != null) { OverlayUtil.renderHoverableArea(graphics, object.getClickbox(), client.getMouseCanvasPosition(), TRANSPARENT, objectColor, objectColor.darker()); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoConfig.java index 07a84629c8..9f08e128af 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoConfig.java @@ -63,4 +63,15 @@ public interface OpponentInfoConfig extends Config { return true; } + + @ConfigItem( + keyName = "showOpponentsInMenu", + name = "Show opponents in menu", + description = "Marks opponents names in the menu which you are attacking or are attacking you (NPC only)", + position = 3 + ) + default boolean showOpponentsInMenu() + { + return false; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoPlugin.java index 4b1a5a223f..8c79904a96 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoPlugin.java @@ -36,11 +36,15 @@ import lombok.Getter; import net.runelite.api.Actor; import net.runelite.api.Client; import net.runelite.api.GameState; +import net.runelite.api.MenuEntry; +import net.runelite.api.MenuOpcode; +import net.runelite.api.NPC; import net.runelite.api.WorldType; import net.runelite.api.events.ConfigChanged; import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.GameTick; import net.runelite.api.events.InteractingChanged; +import net.runelite.api.events.MenuEntryAdded; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.EventBus; import net.runelite.client.plugins.Plugin; @@ -124,6 +128,7 @@ public class OpponentInfoPlugin extends Plugin eventBus.subscribe(GameStateChanged.class, this, this::onGameStateChanged); eventBus.subscribe(InteractingChanged.class, this, this::onInteractingChanged); eventBus.subscribe(GameTick.class, this, this::onGameTick); + eventBus.subscribe(MenuEntryAdded.class, this, this::onMenuEntryAdded); } private void onGameStateChanged(GameStateChanged gameStateChanged) @@ -198,4 +203,28 @@ public class OpponentInfoPlugin extends Plugin this.hitpointsDisplayStyle = config.hitpointsDisplayStyle(); this.showOpponentsOpponent = config.showOpponentsOpponent(); } + + private void onMenuEntryAdded(MenuEntryAdded menuEntryAdded) + { + if (menuEntryAdded.getType() != MenuOpcode.NPC_SECOND_OPTION.getId() + || !menuEntryAdded.getOption().equals("Attack") + || !config.showOpponentsInMenu()) + { + return; + } + + int npcIndex = menuEntryAdded.getIdentifier(); + NPC npc = client.getCachedNPCs()[npcIndex]; + if (npc == null) + { + return; + } + + if (npc.getInteracting() == client.getLocalPlayer() || lastOpponent == npc) + { + MenuEntry[] menuEntries = client.getMenuEntries(); + menuEntries[menuEntries.length - 1].setTarget("*" + menuEntryAdded.getTarget()); + client.setMenuEntries(menuEntries); + } + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/pestcontrol/GangplankOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/pestcontrol/GangplankOverlay.java index 31191088bd..1e1b24b13a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/pestcontrol/GangplankOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/pestcontrol/GangplankOverlay.java @@ -30,7 +30,7 @@ import java.awt.BasicStroke; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; -import java.awt.Polygon; +import java.awt.Shape; import lombok.extern.slf4j.Slf4j; import net.runelite.api.Client; import net.runelite.api.Player; @@ -92,12 +92,12 @@ public class GangplankOverlay extends Overlay if (noviceGangplankTile != null) { - Polygon polygon = noviceGangplankTile.getGameObjects()[0].getConvexHull(); + Shape polygon = noviceGangplankTile.getGameObjects()[0].getConvexHull(); if (polygon != null) { graphics.setColor(noviceCbColor); graphics.setStroke(new BasicStroke(2)); - graphics.drawPolygon(polygon); + graphics.draw(polygon); graphics.setColor(setColorAlpha(noviceCbColor, 45)); graphics.fill(polygon); @@ -112,12 +112,12 @@ public class GangplankOverlay extends Overlay if (intermediateGangplankTile != null) { - Polygon polygon = intermediateGangplankTile.getGameObjects()[0].getConvexHull(); + Shape polygon = intermediateGangplankTile.getGameObjects()[0].getConvexHull(); if (polygon != null) { graphics.setColor(intermediateCbColor); graphics.setStroke(new BasicStroke(2)); - graphics.drawPolygon(polygon); + graphics.draw(polygon); graphics.setColor(setColorAlpha(intermediateCbColor, 45)); graphics.fill(polygon); @@ -132,12 +132,12 @@ public class GangplankOverlay extends Overlay if (veteranGangplankTile != null) { - Polygon polygon = veteranGangplankTile.getGameObjects()[0].getConvexHull(); + Shape polygon = veteranGangplankTile.getGameObjects()[0].getConvexHull(); if (polygon != null) { graphics.setColor(veteranCbColor); graphics.setStroke(new BasicStroke(2)); - graphics.drawPolygon(polygon); + graphics.draw(polygon); graphics.setColor(setColorAlpha(veteranCbColor, 45)); graphics.fill(polygon); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/pestcontrol/NpcHighlightOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/pestcontrol/NpcHighlightOverlay.java index 540134714b..b66085995d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/pestcontrol/NpcHighlightOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/pestcontrol/NpcHighlightOverlay.java @@ -31,6 +31,7 @@ import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Polygon; +import java.awt.Shape; import java.util.HashMap; import lombok.extern.slf4j.Slf4j; import net.runelite.api.Client; @@ -141,7 +142,7 @@ public class NpcHighlightOverlay extends Overlay private void renderHullOverlay(Graphics2D graphics, NPC npc, Color color) { - Polygon objectClickbox = npc.getConvexHull(); + Shape objectClickbox = npc.getConvexHull(); if (objectClickbox != null) { graphics.setColor(color); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/pestcontrol/RepairOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/pestcontrol/RepairOverlay.java index 458337fb33..2e96070a4f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/pestcontrol/RepairOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/pestcontrol/RepairOverlay.java @@ -30,7 +30,7 @@ import java.awt.BasicStroke; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; -import java.awt.geom.Area; +import java.awt.Shape; import net.runelite.api.Client; import net.runelite.api.Constants; import net.runelite.api.GameObject; @@ -185,7 +185,7 @@ public class RepairOverlay extends Overlay return null; } - private void renderObjectOverlay(Graphics2D graphics, Area area, Color color, Point mousePosition) + private void renderObjectOverlay(Graphics2D graphics, Shape area, Color color, Point mousePosition) { if (area == null) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/pyramidplunder/PyramidPlunderOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/pyramidplunder/PyramidPlunderOverlay.java index 99ea4f9fcb..971b765126 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/pyramidplunder/PyramidPlunderOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/pyramidplunder/PyramidPlunderOverlay.java @@ -27,7 +27,7 @@ package net.runelite.client.plugins.pyramidplunder; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; -import java.awt.geom.Area; +import java.awt.Shape; import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.Locale; @@ -119,7 +119,7 @@ public class PyramidPlunderOverlay extends Overlay objectID = impostor.getId(); } - Area objectClickbox = object.getClickbox(); + Shape objectClickbox = object.getClickbox(); if (objectClickbox != null) { Color configColor = Color.GREEN; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raids/shortcuts/ShortcutOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/raids/shortcuts/ShortcutOverlay.java index 2ba5cd8d1b..f98f739f2d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raids/shortcuts/ShortcutOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raids/shortcuts/ShortcutOverlay.java @@ -2,7 +2,7 @@ package net.runelite.client.plugins.raids.shortcuts; import java.awt.Dimension; import java.awt.Graphics2D; -import java.awt.Polygon; +import java.awt.Shape; import java.awt.image.BufferedImage; import javax.inject.Inject; import javax.inject.Singleton; @@ -48,7 +48,7 @@ public class ShortcutOverlay extends Overlay { if (shortcut.getPlane() == client.getPlane()) { - Polygon poly; + Shape poly; if ((shortcut instanceof GameObject)) { poly = ((GameObject) shortcut).getConvexHull(); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/roguesden/RoguesDenOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/roguesden/RoguesDenOverlay.java index 2a4775fdce..dd9c5f6a33 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/roguesden/RoguesDenOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/roguesden/RoguesDenOverlay.java @@ -28,7 +28,7 @@ import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Polygon; -import java.awt.geom.Area; +import java.awt.Shape; import javax.inject.Inject; import javax.inject.Singleton; import net.runelite.api.Client; @@ -74,7 +74,7 @@ public class RoguesDenOverlay extends Overlay { if (tile.getPlane() == client.getPlane()) { - final Area clickBox = obstacle.getClickbox(); + final Shape clickBox = obstacle.getClickbox(); if (clickBox != null) { final Point mouse = client.getMouseCanvasPosition(); @@ -93,7 +93,7 @@ public class RoguesDenOverlay extends Overlay } else { - Polygon p; + Shape p; if (obstacle instanceof GameObject) { p = ((GameObject) obstacle).getConvexHull(); @@ -106,7 +106,7 @@ public class RoguesDenOverlay extends Overlay if (p != null) { graphics.setColor(OBJECT_COLOR); - graphics.drawPolygon(p); + graphics.draw(p); } } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/AbyssOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/AbyssOverlay.java index 9dd2dd5e8d..6336656d6d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/AbyssOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/AbyssOverlay.java @@ -30,7 +30,7 @@ import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Polygon; -import java.awt.geom.Area; +import java.awt.Shape; import net.runelite.api.Client; import net.runelite.api.DecorativeObject; import net.runelite.api.NPC; @@ -105,7 +105,7 @@ class AbyssOverlay extends Overlay } Point mousePosition = client.getMouseCanvasPosition(); - Area objectClickbox = object.getClickbox(); + Shape objectClickbox = object.getClickbox(); if (objectClickbox != null) { if (objectClickbox.contains(mousePosition.getX(), mousePosition.getY())) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TargetClickboxOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TargetClickboxOverlay.java index c8a1d223b6..f199816f21 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TargetClickboxOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/TargetClickboxOverlay.java @@ -31,6 +31,7 @@ import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Polygon; +import java.awt.Shape; import java.util.List; import java.util.Set; import javax.inject.Inject; @@ -43,12 +44,12 @@ import net.runelite.api.Point; import net.runelite.api.coords.LocalPoint; import net.runelite.api.coords.WorldArea; import net.runelite.api.coords.WorldPoint; +import net.runelite.api.util.Text; import net.runelite.client.graphics.ModelOutlineRenderer; 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.OverlayUtil; -import net.runelite.api.util.Text; @Singleton public class TargetClickboxOverlay extends Overlay @@ -129,7 +130,7 @@ public class TargetClickboxOverlay extends Overlay break; case HULL: - Polygon objectClickbox = actor.getConvexHull(); + Shape objectClickbox = actor.getConvexHull(); if (objectClickbox == null) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/tarnslair/TarnsLairOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/tarnslair/TarnsLairOverlay.java index 01670c2fdf..8201c4270d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/tarnslair/TarnsLairOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/tarnslair/TarnsLairOverlay.java @@ -28,6 +28,7 @@ import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Polygon; +import java.awt.Shape; import javax.inject.Inject; import javax.inject.Singleton; import lombok.extern.slf4j.Slf4j; @@ -69,11 +70,11 @@ public class TarnsLairOverlay extends Overlay { if (tile.getPlane() == client.getPlane() && obstacle.getLocalLocation().distanceTo(playerLocation) < MAX_DISTANCE) { - Polygon p = tile.getGameObjects()[0].getConvexHull(); + Shape p = tile.getGameObjects()[0].getConvexHull(); if (p != null) { graphics.setColor(Color.GREEN); - graphics.drawPolygon(p); + graphics.draw(p); } } }); @@ -82,11 +83,11 @@ public class TarnsLairOverlay extends Overlay { if (tile.getPlane() == client.getPlane() && obstacle.getLocalLocation().distanceTo(playerLocation) < MAX_DISTANCE) { - Polygon p = tile.getGameObjects()[0].getConvexHull(); + Shape p = tile.getGameObjects()[0].getConvexHull(); if (p != null) { graphics.setColor(Color.CYAN); - graphics.drawPolygon(p); + graphics.draw(p); } } }); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/theatre/rooms/nylocas/NyloHandler.java b/runelite-client/src/main/java/net/runelite/client/plugins/theatre/rooms/nylocas/NyloHandler.java index 278d5fc1e2..fb4c37d4c0 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/theatre/rooms/nylocas/NyloHandler.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/theatre/rooms/nylocas/NyloHandler.java @@ -5,6 +5,7 @@ import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.Polygon; +import java.awt.Shape; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -248,7 +249,7 @@ public class NyloHandler extends RoomHandler { try { - Polygon objectClickbox = npc.getConvexHull(); + Shape objectClickbox = npc.getConvexHull(); Color color; String name = npc.getName() != null ? npc.getName() : ""; @@ -266,7 +267,8 @@ public class NyloHandler extends RoomHandler color = Color.LIGHT_GRAY; } - renderPoly(graphics, color, objectClickbox); + graphics.setColor(color); + graphics.draw(objectClickbox); } catch (Exception ex) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperPlugin.java index a46b0c07f5..c654c53429 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperPlugin.java @@ -141,6 +141,9 @@ public class WorldHopperPlugin extends Plugin @Inject private WorldHopperPingOverlay worldHopperOverlay; + @Inject + private WorldClient worldClient; + private ScheduledExecutorService hopperExecutorService; private NavigationButton navButton; @@ -533,7 +536,7 @@ public class WorldHopperPlugin extends Plugin { log.debug("Fetching worlds"); - new WorldClient().lookupWorlds() + worldClient.lookupWorlds() .subscribeOn(Schedulers.io()) .take(1) .subscribe( diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/zalcano/ZalcanoOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/zalcano/ZalcanoOverlay.java index b0c97ef371..2bb2c14120 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/zalcano/ZalcanoOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/zalcano/ZalcanoOverlay.java @@ -30,6 +30,7 @@ import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Polygon; +import java.awt.Shape; import java.util.List; import lombok.extern.slf4j.Slf4j; import net.runelite.api.AnimationID; @@ -174,7 +175,7 @@ public class ZalcanoOverlay extends Overlay { if (plugin.getGolem() != null) { - Polygon hull = plugin.getGolem().getConvexHull(); + Shape hull = plugin.getGolem().getConvexHull(); if (hull != null) { OverlayUtil.renderPolygon(graphics, hull, new Color(206, 41, 231)); @@ -187,7 +188,7 @@ public class ZalcanoOverlay extends Overlay { if (plugin.getZalcano() != null) { - Polygon hull = plugin.getZalcano().getConvexHull(); + Shape hull = plugin.getZalcano().getConvexHull(); if (hull != null) { OverlayUtil.renderPolygon(graphics, hull, config.zalcanoHullColor()); diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayUtil.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayUtil.java index 61c95ea785..4ea4c471ee 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayUtil.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayUtil.java @@ -33,8 +33,8 @@ import java.awt.Graphics2D; import java.awt.Polygon; import java.awt.Rectangle; import java.awt.RenderingHints; +import java.awt.Shape; import java.awt.Stroke; -import java.awt.geom.Area; import java.awt.image.BufferedImage; import java.util.List; import net.runelite.api.Actor; @@ -61,14 +61,14 @@ public class OverlayUtil private static final int MINIMAP_DOT_RADIUS = 4; private static final double UNIT = Math.PI / 1024.0d; - public static void renderPolygon(Graphics2D graphics, Polygon poly, Color color) + public static void renderPolygon(Graphics2D graphics, Shape poly, Color color) { graphics.setColor(color); final Stroke originalStroke = graphics.getStroke(); graphics.setStroke(new BasicStroke(2)); - graphics.drawPolygon(poly); + graphics.draw(poly); graphics.setColor(new Color(0, 0, 0, 50)); - graphics.fillPolygon(poly); + graphics.fill(poly); graphics.setStroke(originalStroke); } @@ -211,7 +211,7 @@ public class OverlayUtil renderImageLocation(client, graphics, localLocation, image, 0); } - public static void renderHoverableArea(Graphics2D graphics, Area area, net.runelite.api.Point mousePosition, Color fillColor, Color borderColor, Color borderHoverColor) + public static void renderHoverableArea(Graphics2D graphics, Shape area, net.runelite.api.Point mousePosition, Color fillColor, Color borderColor, Color borderHoverColor) { if (area != null) { @@ -326,7 +326,7 @@ public class OverlayUtil } } - public static void renderClickBox(Graphics2D graphics, Point mousePosition, Area objectClickbox, Color configColor) + public static void renderClickBox(Graphics2D graphics, Point mousePosition, Shape objectClickbox, Color configColor) { if (objectClickbox.contains(mousePosition.getX(), mousePosition.getY())) { diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSBoundaryObjectMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSBoundaryObjectMixin.java index 26f9b68998..aa3e32b502 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSBoundaryObjectMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSBoundaryObjectMixin.java @@ -1,14 +1,17 @@ package net.runelite.mixins; -import net.runelite.api.Entity; +import java.awt.Polygon; +import java.awt.Shape; import net.runelite.api.Model; import net.runelite.api.Perspective; -import java.awt.geom.Area; +import net.runelite.api.coords.LocalPoint; import net.runelite.api.mixins.Inject; import net.runelite.api.mixins.Mixin; import net.runelite.api.mixins.Shadow; import net.runelite.rs.api.RSBoundaryObject; import net.runelite.rs.api.RSClient; +import net.runelite.rs.api.RSEntity; +import net.runelite.rs.api.RSModel; @Mixin(RSBoundaryObject.class) public abstract class RSBoundaryObjectMixin implements RSBoundaryObject @@ -34,9 +37,9 @@ public abstract class RSBoundaryObjectMixin implements RSBoundaryObject } @Inject - public Model getModelA() + public RSModel getModelA() { - Entity entity = getEntity1(); + RSEntity entity = getEntity1(); if (entity == null) { return null; @@ -44,7 +47,7 @@ public abstract class RSBoundaryObjectMixin implements RSBoundaryObject if (entity instanceof Model) { - return (Model) entity; + return (RSModel) entity; } else { @@ -53,9 +56,9 @@ public abstract class RSBoundaryObjectMixin implements RSBoundaryObject } @Inject - public Model getModelB() + public RSModel getModelB() { - Entity entity = getEntity2(); + RSEntity entity = getEntity2(); if (entity == null) { return null; @@ -63,7 +66,7 @@ public abstract class RSBoundaryObjectMixin implements RSBoundaryObject if (entity instanceof Model) { - return (Model) entity; + return (RSModel) entity; } else { @@ -73,12 +76,10 @@ public abstract class RSBoundaryObjectMixin implements RSBoundaryObject @Inject @Override - public Area getClickbox() + public Shape getClickbox() { - Area clickbox = new Area(); - - Area clickboxA = Perspective.getClickbox(client, getModelA(), 0, getLocalLocation()); - Area clickboxB = Perspective.getClickbox(client, getModelB(), 0, getLocalLocation()); + Shape clickboxA = Perspective.getClickbox(client, getModelA(), 0, getLocalLocation()); + Shape clickboxB = Perspective.getClickbox(client, getModelB(), 0, getLocalLocation()); if (clickboxA == null && clickboxB == null) { @@ -87,14 +88,26 @@ public abstract class RSBoundaryObjectMixin implements RSBoundaryObject if (clickboxA != null) { - clickbox.add(clickboxA); + return clickboxA; } - if (clickboxB != null) + return clickboxB; + } + + + + @Inject + @Override + public Polygon getConvexHull() + { + RSModel model = getModelA(); + + if (model == null) { - clickbox.add(clickboxB); + return null; } - return clickbox; + int tileHeight = Perspective.getTileHeight(client, new LocalPoint(getX(), getY()), client.getPlane()); + return model.getConvexHull(getX(), getY(), 0, tileHeight); } } diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSFloorDecorationMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSFloorDecorationMixin.java index 16245b40aa..f1149980ef 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSFloorDecorationMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSFloorDecorationMixin.java @@ -1,14 +1,17 @@ package net.runelite.mixins; +import java.awt.Polygon; +import java.awt.Shape; import net.runelite.api.Model; import net.runelite.api.Perspective; -import net.runelite.api.Entity; -import java.awt.geom.Area; +import net.runelite.api.coords.LocalPoint; 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.RSEntity; import net.runelite.rs.api.RSFloorDecoration; +import net.runelite.rs.api.RSModel; @Mixin(RSFloorDecoration.class) public abstract class RSFloorDecorationMixin implements RSFloorDecoration @@ -35,9 +38,9 @@ public abstract class RSFloorDecorationMixin implements RSFloorDecoration @Inject @Override - public Model getModel() + public RSModel getModel() { - Entity entity = getEntity(); + RSEntity entity = getEntity(); if (entity == null) { return null; @@ -45,7 +48,7 @@ public abstract class RSFloorDecorationMixin implements RSFloorDecoration if (entity instanceof Model) { - return (Model) entity; + return (RSModel) entity; } else { @@ -53,9 +56,26 @@ public abstract class RSFloorDecorationMixin implements RSFloorDecoration } } + + @Inject @Override - public Area getClickbox() + public Polygon getConvexHull() + { + RSModel model = getModel(); + + if (model == null) + { + return null; + } + + int tileHeight = Perspective.getTileHeight(client, new LocalPoint(getX(), getY()), client.getPlane()); + return model.getConvexHull(getX(), getY(), 0, tileHeight); + } + + @Inject + @Override + public Shape getClickbox() { return Perspective.getClickbox(client, getModel(), 0, getLocalLocation()); } diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSGameObjectMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSGameObjectMixin.java index b0128249fb..1b34663f6f 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSGameObjectMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSGameObjectMixin.java @@ -25,10 +25,7 @@ package net.runelite.mixins; import java.awt.Polygon; -import java.awt.geom.Area; -import java.util.ArrayList; -import java.util.List; -import net.runelite.api.Model; +import java.awt.Shape; import net.runelite.api.Perspective; import net.runelite.api.Point; import net.runelite.api.coords.Angle; @@ -36,8 +33,6 @@ import net.runelite.api.coords.LocalPoint; import net.runelite.api.mixins.Inject; import net.runelite.api.mixins.Mixin; import net.runelite.api.mixins.Shadow; -import net.runelite.api.model.Triangle; -import net.runelite.api.model.Vertex; import net.runelite.rs.api.RSClient; import net.runelite.rs.api.RSEntity; import net.runelite.rs.api.RSGameObject; @@ -85,94 +80,11 @@ public abstract class RSGameObjectMixin implements RSGameObject @Inject @Override - public Area getClickbox() + public Shape getClickbox() { return Perspective.getClickbox(client, getModel(), getRsOrientation(), getLocalLocation()); } - @Inject - @Override - public Polygon[] getPolygons() - { - Model model = getModel(); - - if (model == null) - { - return null; - } - - int localX = getX(); - int localY = getY(); - - int orientation = getRsOrientation(); - - final int tileHeight = Perspective.getTileHeight(client, new LocalPoint(localX, localY), client.getPlane()); - - List triangles = model.getTriangles(); - - triangles = rotate(triangles, orientation); - - List polys = new ArrayList(); - for (Triangle triangle : triangles) - { - Vertex vx = triangle.getA(); - Vertex vy = triangle.getB(); - Vertex vz = triangle.getC(); - - Point x = Perspective.localToCanvas(client, - localX - vx.getX(), - localY - vx.getZ(), - tileHeight + vx.getY()); - - Point y = Perspective.localToCanvas(client, - localX - vy.getX(), - localY - vy.getZ(), - tileHeight + vy.getY()); - - Point z = Perspective.localToCanvas(client, - localX - vz.getX(), - localY - vz.getZ(), - tileHeight + vz.getY()); - - if (x == null || y == null || z == null) - { - return null; - } - - 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[0]); - } - - @Inject - private List rotate(List triangles, int orientation) - { - List 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; - } - @Inject @Override public Polygon getConvexHull() diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSPlayerMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSPlayerMixin.java index c500884e73..7d04713ff3 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSPlayerMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSPlayerMixin.java @@ -24,6 +24,9 @@ */ package net.runelite.mixins; +import java.awt.Polygon; +import java.util.ArrayList; +import java.util.List; import net.runelite.api.HeadIcon; import static net.runelite.api.HeadIcon.MAGIC; import static net.runelite.api.HeadIcon.MELEE; @@ -43,17 +46,14 @@ import static net.runelite.api.SkullIcon.DEAD_MAN_TWO; import static net.runelite.api.SkullIcon.SKULL; import static net.runelite.api.SkullIcon.SKULL_FIGHT_PIT; import net.runelite.api.coords.LocalPoint; -import net.runelite.api.mixins.MethodHook; -import net.runelite.api.model.Triangle; -import net.runelite.api.model.Vertex; -import java.awt.Polygon; -import java.util.ArrayList; -import java.util.List; import net.runelite.api.mixins.Copy; import net.runelite.api.mixins.Inject; +import net.runelite.api.mixins.MethodHook; import net.runelite.api.mixins.Mixin; import net.runelite.api.mixins.Replace; import net.runelite.api.mixins.Shadow; +import net.runelite.api.model.Triangle; +import net.runelite.api.model.Vertex; import net.runelite.rs.api.RSClient; import net.runelite.rs.api.RSModel; import net.runelite.rs.api.RSPlayer; @@ -169,28 +169,28 @@ public abstract class RSPlayerMixin implements RSPlayer System.err.println("vx: " + vx.getX() + " localX: " + localX); Point x = Perspective.localToCanvas(client, - localX - vx.getX(), - localY - vx.getZ(), - tileHeight + vx.getY()); + localX - vx.getX(), + localY - vx.getZ(), + tileHeight + vx.getY()); Point y = Perspective.localToCanvas(client, - localX - vy.getX(), - localY - vy.getZ(), - tileHeight + vy.getY()); + localX - vy.getX(), + localY - vy.getZ(), + tileHeight + vy.getY()); Point z = Perspective.localToCanvas(client, - localX - vz.getX(), - localY - vz.getZ(), - tileHeight + vz.getY()); + localX - vz.getX(), + localY - vz.getZ(), + tileHeight + vz.getY()); int[] xx = - { - x.getX(), y.getX(), z.getX() - }; + { + x.getX(), y.getX(), z.getX() + }; int[] yy = - { - x.getY(), y.getY(), z.getY() - }; + { + x.getY(), y.getY(), z.getY() + }; polys.add(new Polygon(xx, yy, 3)); } @@ -222,9 +222,9 @@ public abstract class RSPlayerMixin implements RSPlayer Vertex c = triangle.getC(); Triangle rotatedTriangle = new Triangle( - a.rotate(orientation), - b.rotate(orientation), - c.rotate(orientation) + a.rotate(orientation), + b.rotate(orientation), + c.rotate(orientation) ); rotatedTriangles.add(rotatedTriangle); } diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSWallDecorationMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSWallDecorationMixin.java index 2e36340a3a..c1395bc3c0 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSWallDecorationMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSWallDecorationMixin.java @@ -1,10 +1,11 @@ package net.runelite.mixins; +import java.awt.Polygon; +import java.awt.Shape; +import java.awt.geom.Area; import net.runelite.api.Model; import net.runelite.api.Perspective; import net.runelite.api.coords.LocalPoint; -import java.awt.Polygon; -import java.awt.geom.Area; import net.runelite.api.mixins.Inject; import net.runelite.api.mixins.Mixin; import net.runelite.api.mixins.Shadow; @@ -86,14 +87,14 @@ public abstract class RSWallDecorationMixin implements RSWallDecoration @Inject @Override - public Area getClickbox() + public Shape getClickbox() { Area clickbox = new Area(); LocalPoint lp = getLocalLocation(); - Area clickboxA = Perspective.getClickbox(client, getModel1(), 0, + Shape clickboxA = Perspective.getClickbox(client, getModel1(), 0, new LocalPoint(lp.getX() + getXOffset(), lp.getY() + getYOffset())); - Area clickboxB = Perspective.getClickbox(client, getModel2(), 0, lp); + Shape clickboxB = Perspective.getClickbox(client, getModel2(), 0, lp); if (clickboxA == null && clickboxB == null) { @@ -102,15 +103,10 @@ public abstract class RSWallDecorationMixin implements RSWallDecoration if (clickboxA != null) { - clickbox.add(clickboxA); + return clickboxA; } - if (clickboxB != null) - { - clickbox.add(clickboxB); - } - - return clickbox; + return clickboxB; } @Inject diff --git a/runescape-client/.DS_Store b/runescape-client/.DS_Store deleted file mode 100644 index 8f70268247..0000000000 Binary files a/runescape-client/.DS_Store and /dev/null differ diff --git a/runescape-client/src/main/java/Actor.java b/runescape-client/src/main/java/Actor.java index bd3ae411e4..12ee43e023 100644 --- a/runescape-client/src/main/java/Actor.java +++ b/runescape-client/src/main/java/Actor.java @@ -29,7 +29,8 @@ public abstract class Actor extends Entity { @Export("isWalking") boolean isWalking; @ObfuscatedName("ax") - int field932; + @Export("size") + int size; @ObfuscatedName("as") @ObfuscatedGetter( intValue = -334562759 @@ -315,7 +316,7 @@ public abstract class Actor extends Entity { Actor() { this.isWalking = false; - this.field932 = 772175475; + this.size = 772175475; this.readySequence = -1; this.turnLeftSequence = -1; this.turnRightSequence = -1; diff --git a/runescape-client/src/main/java/Client.java b/runescape-client/src/main/java/Client.java index b257375fb5..24b99a25e1 100644 --- a/runescape-client/src/main/java/Client.java +++ b/runescape-client/src/main/java/Client.java @@ -2110,7 +2110,7 @@ public final class Client extends GameShell implements Usernamed { } ViewportMouse.client = this; - class319.field3843 = clientType; + ClientType.clientType = clientType; this.startThread(765, 503, 184); } } catch (RuntimeException var22) { @@ -5267,9 +5267,9 @@ public final class Client extends GameShell implements Usernamed { garbageValue = "1638335073" ) @Export("openMenu") - final void openMenu(int var1, int var2) { - UserComparator6.calculateMenuBounds(var1, var2); - PacketWriter.scene.menuOpen(WorldMapRectangle.plane, var1, var2, false); + final void openMenu(int screenX, int screenY) { + UserComparator6.calculateMenuBounds(screenX, screenY); + PacketWriter.scene.menuOpen(WorldMapRectangle.plane, screenX, screenY, false); isMenuOpen = true; } diff --git a/runescape-client/src/main/java/class319.java b/runescape-client/src/main/java/ClientType.java similarity index 50% rename from runescape-client/src/main/java/class319.java rename to runescape-client/src/main/java/ClientType.java index 0912083a75..be8cae3aba 100644 --- a/runescape-client/src/main/java/class319.java +++ b/runescape-client/src/main/java/ClientType.java @@ -1,11 +1,16 @@ +import net.runelite.mapping.Export; +import net.runelite.mapping.Implements; import net.runelite.mapping.ObfuscatedGetter; import net.runelite.mapping.ObfuscatedName; @ObfuscatedName("ln") -public class class319 { +@Implements("ClientType") +public class ClientType +{ @ObfuscatedName("u") @ObfuscatedGetter( intValue = 2052078695 ) - public static int field3843; + @Export("clientType") + public static int clientType; } diff --git a/runescape-client/src/main/java/HealthBar.java b/runescape-client/src/main/java/HealthBar.java index 38bee8e26c..011d9edae6 100644 --- a/runescape-client/src/main/java/HealthBar.java +++ b/runescape-client/src/main/java/HealthBar.java @@ -169,10 +169,10 @@ public class HealthBar extends Node { if (var0.field976 == Client.cycle || var0.sequence == -1 || var0.sequenceDelay != 0 || var0.sequenceFrameCycle + 1 > GrandExchangeOfferUnitPriceComparator.SequenceDefinition_get(var0.sequence).frameLengths[var0.sequenceFrame]) { int var1 = var0.field976 - var0.field948; int var2 = Client.cycle - var0.field948; - int var3 = var0.field932 * -527978816 + var0.field971 * 128; - int var4 = var0.field932 * -527978816 + var0.field973 * 128; - int var5 = var0.field972 * 128 + var0.field932 * -527978816; - int var6 = var0.field932 * -527978816 + var0.field974 * 128; + int var3 = var0.size * -527978816 + var0.field971 * 128; + int var4 = var0.size * -527978816 + var0.field973 * 128; + int var5 = var0.field972 * 128 + var0.size * -527978816; + int var6 = var0.size * -527978816 + var0.field974 * 128; var0.x = (var2 * var5 + var3 * (var1 - var2)) / var1; var0.y = (var6 * var2 + var4 * (var1 - var2)) / var1; } diff --git a/runescape-client/src/main/java/InterfaceParent.java b/runescape-client/src/main/java/InterfaceParent.java index 0235d4f201..5db3af8647 100644 --- a/runescape-client/src/main/java/InterfaceParent.java +++ b/runescape-client/src/main/java/InterfaceParent.java @@ -212,7 +212,7 @@ public class InterfaceParent extends Node { var9 = var1.readBits(1); var4.definition = PacketBufferNode.getNpcDefinition(var1.readBits(14)); - var4.field932 = var4.definition.size * 772175475; + var4.size = var4.definition.size * 772175475; var4.field982 = var4.definition.rotation; if (var4.field982 == 0) { var4.rotation = 0; @@ -317,7 +317,7 @@ public class InterfaceParent extends Node { if ((var5 & 32) != 0) { var4.definition = PacketBufferNode.getNpcDefinition(var1.method5647()); - var4.field932 = var4.definition.size * 772175475; + var4.size = var4.definition.size * 772175475; var4.field982 = var4.definition.rotation; var4.walkSequence = var4.definition.walkSequence; var4.walkBackSequence = var4.definition.walkBackSequence; diff --git a/runescape-client/src/main/java/NPC.java b/runescape-client/src/main/java/NPC.java index 2105a08667..30b27fc115 100644 --- a/runescape-client/src/main/java/NPC.java +++ b/runescape-client/src/main/java/NPC.java @@ -122,8 +122,8 @@ public final class NPC extends Actor { super.field949 = 0; super.pathX[0] = var1; super.pathY[0] = var2; - super.x = super.pathX[0] * 128 + super.field932 * -527978816; - super.y = super.pathY[0] * 128 + super.field932 * -527978816; + super.x = super.pathX[0] * 128 + super.size * -527978816; + super.y = super.pathY[0] * 128 + super.size * -527978816; } @ObfuscatedName("y") diff --git a/runescape-client/src/main/java/Scene.java b/runescape-client/src/main/java/Scene.java index 6432a085c2..cde552f69b 100644 --- a/runescape-client/src/main/java/Scene.java +++ b/runescape-client/src/main/java/Scene.java @@ -317,39 +317,42 @@ public class Scene { @ObfuscatedName("p") @Export("addTile") - public void addTile(int var1, int var2, int var3, int var4, int var5, int var6, int var7, int var8, int var9, int var10, int var11, int var12, int var13, int var14, int var15, int var16, int var17, int var18, int var19, int var20) { + public void addTile(int z, int x, int y, int shape, int rotation, int texture, int heightSw, int heightNw, + int heightNe, int heightSe, int underlaySwColor, int underlayNwColor, int underlayNeColor, + int underlaySeColor, int overlaySwColor, int overlayNwColor, int overlayNeColor, + int overlaySeColor, int underlayRgb, int overlayRgb) { TilePaint var21; int var22; - if (var4 == 0) { - var21 = new TilePaint(var11, var12, var13, var14, -1, var19, false); + if (shape == 0) { + var21 = new TilePaint(underlaySwColor, underlayNwColor, underlayNeColor, underlaySeColor, -1, underlayRgb, false); - for (var22 = var1; var22 >= 0; --var22) { - if (this.tiles[var22][var2][var3] == null) { - this.tiles[var22][var2][var3] = new Tile(var22, var2, var3); + for (var22 = z; var22 >= 0; --var22) { + if (this.tiles[var22][x][y] == null) { + this.tiles[var22][x][y] = new Tile(var22, x, y); } } - this.tiles[var1][var2][var3].paint = var21; - } else if (var4 != 1) { - TileModel var23 = new TileModel(var4, var5, var6, var2, var3, var7, var8, var9, var10, var11, var12, var13, var14, var15, var16, var17, var18, var19, var20); + this.tiles[z][x][y].paint = var21; + } else if (shape != 1) { + TileModel var23 = new TileModel(shape, rotation, texture, x, y, heightSw, heightNw, heightNe, heightSe, underlaySwColor, underlayNwColor, underlayNeColor, underlaySeColor, overlaySwColor, overlayNwColor, overlayNeColor, overlaySeColor, underlayRgb, overlayRgb); - for (var22 = var1; var22 >= 0; --var22) { - if (this.tiles[var22][var2][var3] == null) { - this.tiles[var22][var2][var3] = new Tile(var22, var2, var3); + for (var22 = z; var22 >= 0; --var22) { + if (this.tiles[var22][x][y] == null) { + this.tiles[var22][x][y] = new Tile(var22, x, y); } } - this.tiles[var1][var2][var3].model = var23; + this.tiles[z][x][y].model = var23; } else { - var21 = new TilePaint(var15, var16, var17, var18, var6, var20, var8 == var7 && var7 == var9 && var10 == var7); + var21 = new TilePaint(overlaySwColor, overlayNwColor, overlayNeColor, overlaySeColor, texture, overlayRgb, heightNw == heightSw && heightSw == heightNe && heightSe == heightSw); - for (var22 = var1; var22 >= 0; --var22) { - if (this.tiles[var22][var2][var3] == null) { - this.tiles[var22][var2][var3] = new Tile(var22, var2, var3); + for (var22 = z; var22 >= 0; --var22) { + if (this.tiles[var22][x][y] == null) { + this.tiles[var22][x][y] = new Tile(var22, x, y); } } - this.tiles[var1][var2][var3].paint = var21; + this.tiles[z][x][y].paint = var21; } } @@ -970,61 +973,61 @@ public class Scene { @ObfuscatedName("ai") @Export("drawTileMinimap") - public void drawTileMinimap(int[] var1, int var2, int var3, int var4, int var5, int var6) { - Tile var7 = this.tiles[var4][var5][var6]; - if (var7 != null) { - TilePaint var8 = var7.paint; - int var10; - if (var8 != null) { - int var9 = var8.rgb; - if (var9 != 0) { - for (var10 = 0; var10 < 4; ++var10) { - var1[var2] = var9; - var1[var2 + 1] = var9; - var1[var2 + 2] = var9; - var1[var2 + 3] = var9; - var2 += var3; + public void drawTileMinimap(int[] pixels, int index, int width, int plane, int x, int y) { + Tile tile = this.tiles[plane][x][y]; + if (tile != null) { + TilePaint tilePaint = tile.paint; + int shape; + if (tilePaint != null) { + int rgb = tilePaint.rgb; + if (rgb != 0) { + for (shape = 0; shape < 4; ++shape) { + pixels[index] = rgb; + pixels[index + 1] = rgb; + pixels[index + 2] = rgb; + pixels[index + 3] = rgb; + index += width; } } } else { - TileModel var18 = var7.model; - if (var18 != null) { - var10 = var18.shape; - int var11 = var18.rotation; - int var12 = var18.underlayRgb; - int var13 = var18.overlayRgb; - int[] var14 = this.tileShape2D[var10]; - int[] var15 = this.tileRotation2D[var11]; + TileModel tileModel = tile.model; + if (tileModel != null) { + shape = tileModel.shape; + int rotation = tileModel.rotation; + int underlayRgb = tileModel.underlayRgb; + int overlayRgb = tileModel.overlayRgb; + int[] shapes = this.tileShape2D[shape]; + int[] rotations = this.tileRotation2D[rotation]; int var16 = 0; int var17; - if (var12 != 0) { + if (underlayRgb != 0) { for (var17 = 0; var17 < 4; ++var17) { - var1[var2] = var14[var15[var16++]] == 0 ? var12 : var13; - var1[var2 + 1] = var14[var15[var16++]] == 0 ? var12 : var13; - var1[var2 + 2] = var14[var15[var16++]] == 0 ? var12 : var13; - var1[var2 + 3] = var14[var15[var16++]] == 0 ? var12 : var13; - var2 += var3; + pixels[index] = shapes[rotations[var16++]] == 0 ? underlayRgb : overlayRgb; + pixels[index + 1] = shapes[rotations[var16++]] == 0 ? underlayRgb : overlayRgb; + pixels[index + 2] = shapes[rotations[var16++]] == 0 ? underlayRgb : overlayRgb; + pixels[index + 3] = shapes[rotations[var16++]] == 0 ? underlayRgb : overlayRgb; + index += width; } } else { for (var17 = 0; var17 < 4; ++var17) { - if (var14[var15[var16++]] != 0) { - var1[var2] = var13; + if (shapes[rotations[var16++]] != 0) { + pixels[index] = overlayRgb; } - if (var14[var15[var16++]] != 0) { - var1[var2 + 1] = var13; + if (shapes[rotations[var16++]] != 0) { + pixels[index + 1] = overlayRgb; } - if (var14[var15[var16++]] != 0) { - var1[var2 + 2] = var13; + if (shapes[rotations[var16++]] != 0) { + pixels[index + 2] = overlayRgb; } - if (var14[var15[var16++]] != 0) { - var1[var2 + 3] = var13; + if (shapes[rotations[var16++]] != 0) { + pixels[index + 3] = overlayRgb; } - var2 += var3; + index += width; } } @@ -1035,13 +1038,13 @@ public class Scene { @ObfuscatedName("am") @Export("menuOpen") - public void menuOpen(int var1, int var2, int var3, boolean var4) { - if (!method3085() || var4) { + public void menuOpen(int plane, int screenX, int screenY, boolean walking) { + if (!method3085() || walking) { checkClick = true; - viewportWalking = var4; - Scene_selectedPlane = var1; - Scene_selectedScreenX = var2; - Scene_selectedScreenY = var3; + viewportWalking = walking; + Scene_selectedPlane = plane; + Scene_selectedScreenX = screenX; + Scene_selectedScreenY = screenY; Scene_selectedX = -1; Scene_selectedY = -1; } diff --git a/runescape-client/src/main/java/Sprite.java b/runescape-client/src/main/java/Sprite.java index e55638f17f..1b8816f5e1 100644 --- a/runescape-client/src/main/java/Sprite.java +++ b/runescape-client/src/main/java/Sprite.java @@ -109,25 +109,25 @@ public final class Sprite extends Rasterizer2D { @ObfuscatedName("r") @Export("pad") - public void pad(int var1) { + public void pad(int amount) { if (this.subWidth != this.width || this.subHeight != this.height) { - int var2 = var1; - if (var1 > this.xOffset) { + int var2 = amount; + if (amount > this.xOffset) { var2 = this.xOffset; } - int var3 = var1; - if (var1 + this.xOffset + this.subWidth > this.width) { + int var3 = amount; + if (amount + this.xOffset + this.subWidth > this.width) { var3 = this.width - this.xOffset - this.subWidth; } - int var4 = var1; - if (var1 > this.yOffset) { + int var4 = amount; + if (amount > this.yOffset) { var4 = this.yOffset; } - int var5 = var1; - if (var1 + this.yOffset + this.subHeight > this.height) { + int var5 = amount; + if (amount + this.yOffset + this.subHeight > this.height) { var5 = this.height - this.yOffset - this.subHeight; } @@ -183,7 +183,7 @@ public final class Sprite extends Rasterizer2D { @ObfuscatedName("m") @Export("outline") - public void outline(int var1) { + public void outline(int color) { int[] var2 = new int[this.subWidth * this.subHeight]; int var3 = 0; @@ -192,13 +192,13 @@ public final class Sprite extends Rasterizer2D { int var6 = this.pixels[var3]; if (var6 == 0) { if (var5 > 0 && this.pixels[var3 - 1] != 0) { - var6 = var1; + var6 = color; } else if (var4 > 0 && this.pixels[var3 - this.subWidth] != 0) { - var6 = var1; + var6 = color; } else if (var5 < this.subWidth - 1 && this.pixels[var3 + 1] != 0) { - var6 = var1; + var6 = color; } else if (var4 < this.subHeight - 1 && this.pixels[var3 + this.subWidth] != 0) { - var6 = var1; + var6 = color; } } @@ -226,40 +226,40 @@ public final class Sprite extends Rasterizer2D { @ObfuscatedName("i") @Export("drawAt") - public void drawAt(int var1, int var2) { - var1 += this.xOffset; - var2 += this.yOffset; - int var3 = var1 + var2 * Rasterizer2D.Rasterizer2D_width; + public void drawAt(int x, int y) { + x += this.xOffset; + y += this.yOffset; + int var3 = x + y * Rasterizer2D.Rasterizer2D_width; int var4 = 0; int var5 = this.subHeight; int var6 = this.subWidth; int var7 = Rasterizer2D.Rasterizer2D_width - var6; int var8 = 0; int var9; - if (var2 < Rasterizer2D.Rasterizer2D_yClipStart) { - var9 = Rasterizer2D.Rasterizer2D_yClipStart - var2; + if (y < Rasterizer2D.Rasterizer2D_yClipStart) { + var9 = Rasterizer2D.Rasterizer2D_yClipStart - y; var5 -= var9; - var2 = Rasterizer2D.Rasterizer2D_yClipStart; + y = Rasterizer2D.Rasterizer2D_yClipStart; var4 += var9 * var6; var3 += var9 * Rasterizer2D.Rasterizer2D_width; } - if (var5 + var2 > Rasterizer2D.Rasterizer2D_yClipEnd) { - var5 -= var5 + var2 - Rasterizer2D.Rasterizer2D_yClipEnd; + if (var5 + y > Rasterizer2D.Rasterizer2D_yClipEnd) { + var5 -= var5 + y - Rasterizer2D.Rasterizer2D_yClipEnd; } - if (var1 < Rasterizer2D.Rasterizer2D_xClipStart) { - var9 = Rasterizer2D.Rasterizer2D_xClipStart - var1; + if (x < Rasterizer2D.Rasterizer2D_xClipStart) { + var9 = Rasterizer2D.Rasterizer2D_xClipStart - x; var6 -= var9; - var1 = Rasterizer2D.Rasterizer2D_xClipStart; + x = Rasterizer2D.Rasterizer2D_xClipStart; var4 += var9; var3 += var9; var8 += var9; var7 += var9; } - if (var6 + var1 > Rasterizer2D.Rasterizer2D_xClipEnd) { - var9 = var6 + var1 - Rasterizer2D.Rasterizer2D_xClipEnd; + if (var6 + x > Rasterizer2D.Rasterizer2D_xClipEnd) { + var9 = var6 + x - Rasterizer2D.Rasterizer2D_xClipEnd; var6 -= var9; var8 += var9; var7 += var9; @@ -272,40 +272,40 @@ public final class Sprite extends Rasterizer2D { @ObfuscatedName("b") @Export("drawTransBgAt") - public void drawTransBgAt(int var1, int var2) { - var1 += this.xOffset; - var2 += this.yOffset; - int var3 = var1 + var2 * Rasterizer2D.Rasterizer2D_width; + public void drawTransBgAt(int x, int y) { + x += this.xOffset; + y += this.yOffset; + int var3 = x + y * Rasterizer2D.Rasterizer2D_width; int var4 = 0; int var5 = this.subHeight; int var6 = this.subWidth; int var7 = Rasterizer2D.Rasterizer2D_width - var6; int var8 = 0; int var9; - if (var2 < Rasterizer2D.Rasterizer2D_yClipStart) { - var9 = Rasterizer2D.Rasterizer2D_yClipStart - var2; + if (y < Rasterizer2D.Rasterizer2D_yClipStart) { + var9 = Rasterizer2D.Rasterizer2D_yClipStart - y; var5 -= var9; - var2 = Rasterizer2D.Rasterizer2D_yClipStart; + y = Rasterizer2D.Rasterizer2D_yClipStart; var4 += var9 * var6; var3 += var9 * Rasterizer2D.Rasterizer2D_width; } - if (var5 + var2 > Rasterizer2D.Rasterizer2D_yClipEnd) { - var5 -= var5 + var2 - Rasterizer2D.Rasterizer2D_yClipEnd; + if (var5 + y > Rasterizer2D.Rasterizer2D_yClipEnd) { + var5 -= var5 + y - Rasterizer2D.Rasterizer2D_yClipEnd; } - if (var1 < Rasterizer2D.Rasterizer2D_xClipStart) { - var9 = Rasterizer2D.Rasterizer2D_xClipStart - var1; + if (x < Rasterizer2D.Rasterizer2D_xClipStart) { + var9 = Rasterizer2D.Rasterizer2D_xClipStart - x; var6 -= var9; - var1 = Rasterizer2D.Rasterizer2D_xClipStart; + x = Rasterizer2D.Rasterizer2D_xClipStart; var4 += var9; var3 += var9; var8 += var9; var7 += var9; } - if (var6 + var1 > Rasterizer2D.Rasterizer2D_xClipEnd) { - var9 = var6 + var1 - Rasterizer2D.Rasterizer2D_xClipEnd; + if (var6 + x > Rasterizer2D.Rasterizer2D_xClipEnd) { + var9 = var6 + x - Rasterizer2D.Rasterizer2D_xClipEnd; var6 -= var9; var8 += var9; var7 += var9; @@ -318,275 +318,275 @@ public final class Sprite extends Rasterizer2D { @ObfuscatedName("a") @Export("drawScaledAt") - public void drawScaledAt(int var1, int var2, int var3, int var4) { - if (var3 > 0 && var4 > 0) { + public void drawScaledAt(int x, int y, int width, int height) { + if (width > 0 && height > 0) { int var5 = this.subWidth; int var6 = this.subHeight; int var7 = 0; int var8 = 0; int var9 = this.width; int var10 = this.height; - int var11 = (var9 << 16) / var3; - int var12 = (var10 << 16) / var4; + int var11 = (var9 << 16) / width; + int var12 = (var10 << 16) / height; int var13; if (this.xOffset > 0) { var13 = (var11 + (this.xOffset << 16) - 1) / var11; - var1 += var13; + x += var13; var7 += var13 * var11 - (this.xOffset << 16); } if (this.yOffset > 0) { var13 = (var12 + (this.yOffset << 16) - 1) / var12; - var2 += var13; + y += var13; var8 += var13 * var12 - (this.yOffset << 16); } if (var5 < var9) { - var3 = (var11 + ((var5 << 16) - var7) - 1) / var11; + width = (var11 + ((var5 << 16) - var7) - 1) / var11; } if (var6 < var10) { - var4 = (var12 + ((var6 << 16) - var8) - 1) / var12; + height = (var12 + ((var6 << 16) - var8) - 1) / var12; } - var13 = var1 + var2 * Rasterizer2D.Rasterizer2D_width; - int var14 = Rasterizer2D.Rasterizer2D_width - var3; - if (var2 + var4 > Rasterizer2D.Rasterizer2D_yClipEnd) { - var4 -= var2 + var4 - Rasterizer2D.Rasterizer2D_yClipEnd; + var13 = x + y * Rasterizer2D.Rasterizer2D_width; + int var14 = Rasterizer2D.Rasterizer2D_width - width; + if (y + height > Rasterizer2D.Rasterizer2D_yClipEnd) { + height -= y + height - Rasterizer2D.Rasterizer2D_yClipEnd; } int var15; - if (var2 < Rasterizer2D.Rasterizer2D_yClipStart) { - var15 = Rasterizer2D.Rasterizer2D_yClipStart - var2; - var4 -= var15; + if (y < Rasterizer2D.Rasterizer2D_yClipStart) { + var15 = Rasterizer2D.Rasterizer2D_yClipStart - y; + height -= var15; var13 += var15 * Rasterizer2D.Rasterizer2D_width; var8 += var12 * var15; } - if (var3 + var1 > Rasterizer2D.Rasterizer2D_xClipEnd) { - var15 = var3 + var1 - Rasterizer2D.Rasterizer2D_xClipEnd; - var3 -= var15; + if (width + x > Rasterizer2D.Rasterizer2D_xClipEnd) { + var15 = width + x - Rasterizer2D.Rasterizer2D_xClipEnd; + width -= var15; var14 += var15; } - if (var1 < Rasterizer2D.Rasterizer2D_xClipStart) { - var15 = Rasterizer2D.Rasterizer2D_xClipStart - var1; - var3 -= var15; + if (x < Rasterizer2D.Rasterizer2D_xClipStart) { + var15 = Rasterizer2D.Rasterizer2D_xClipStart - x; + width -= var15; var13 += var15; var7 += var11 * var15; var14 += var15; } - Sprite_drawScaled(Rasterizer2D.Rasterizer2D_pixels, this.pixels, 0, var7, var8, var13, var14, var3, var4, var11, var12, var5); + Sprite_drawScaled(Rasterizer2D.Rasterizer2D_pixels, this.pixels, 0, var7, var8, var13, var14, width, height, var11, var12, var5); } } @ObfuscatedName("x") @Export("drawTransOverlayAt") - public void drawTransOverlayAt(int var1, int var2, int var3, int var4) { - if (var3 == 256) { - this.drawTransBgAt(var1, var2); + public void drawTransOverlayAt(int x, int y, int overlayOpacity, int overlayColor) { + if (overlayOpacity == 256) { + this.drawTransBgAt(x, y); } else { - var1 += this.xOffset; - var2 += this.yOffset; - int var5 = var1 + var2 * Rasterizer2D.Rasterizer2D_width; + x += this.xOffset; + y += this.yOffset; + int var5 = x + y * Rasterizer2D.Rasterizer2D_width; int var6 = 0; int var7 = this.subHeight; int var8 = this.subWidth; int var9 = Rasterizer2D.Rasterizer2D_width - var8; int var10 = 0; int var11; - if (var2 < Rasterizer2D.Rasterizer2D_yClipStart) { - var11 = Rasterizer2D.Rasterizer2D_yClipStart - var2; + if (y < Rasterizer2D.Rasterizer2D_yClipStart) { + var11 = Rasterizer2D.Rasterizer2D_yClipStart - y; var7 -= var11; - var2 = Rasterizer2D.Rasterizer2D_yClipStart; + y = Rasterizer2D.Rasterizer2D_yClipStart; var6 += var11 * var8; var5 += var11 * Rasterizer2D.Rasterizer2D_width; } - if (var7 + var2 > Rasterizer2D.Rasterizer2D_yClipEnd) { - var7 -= var7 + var2 - Rasterizer2D.Rasterizer2D_yClipEnd; + if (var7 + y > Rasterizer2D.Rasterizer2D_yClipEnd) { + var7 -= var7 + y - Rasterizer2D.Rasterizer2D_yClipEnd; } - if (var1 < Rasterizer2D.Rasterizer2D_xClipStart) { - var11 = Rasterizer2D.Rasterizer2D_xClipStart - var1; + if (x < Rasterizer2D.Rasterizer2D_xClipStart) { + var11 = Rasterizer2D.Rasterizer2D_xClipStart - x; var8 -= var11; - var1 = Rasterizer2D.Rasterizer2D_xClipStart; + x = Rasterizer2D.Rasterizer2D_xClipStart; var6 += var11; var5 += var11; var10 += var11; var9 += var11; } - if (var8 + var1 > Rasterizer2D.Rasterizer2D_xClipEnd) { - var11 = var8 + var1 - Rasterizer2D.Rasterizer2D_xClipEnd; + if (var8 + x > Rasterizer2D.Rasterizer2D_xClipEnd) { + var11 = var8 + x - Rasterizer2D.Rasterizer2D_xClipEnd; var8 -= var11; var10 += var11; var9 += var11; } if (var8 > 0 && var7 > 0) { - Sprite_drawTransOverlay(Rasterizer2D.Rasterizer2D_pixels, this.pixels, 0, var6, var5, var8, var7, var9, var10, var3, var4); + Sprite_drawTransOverlay(Rasterizer2D.Rasterizer2D_pixels, this.pixels, 0, var6, var5, var8, var7, var9, var10, overlayOpacity, overlayColor); } } } @ObfuscatedName("s") @Export("drawTransAt") - public void drawTransAt(int var1, int var2, int var3) { - var1 += this.xOffset; - var2 += this.yOffset; - int var4 = var1 + var2 * Rasterizer2D.Rasterizer2D_width; + public void drawTransAt(int x, int y, int opacity) { + x += this.xOffset; + y += this.yOffset; + int var4 = x + y * Rasterizer2D.Rasterizer2D_width; int var5 = 0; int var6 = this.subHeight; int var7 = this.subWidth; int var8 = Rasterizer2D.Rasterizer2D_width - var7; int var9 = 0; int var10; - if (var2 < Rasterizer2D.Rasterizer2D_yClipStart) { - var10 = Rasterizer2D.Rasterizer2D_yClipStart - var2; + if (y < Rasterizer2D.Rasterizer2D_yClipStart) { + var10 = Rasterizer2D.Rasterizer2D_yClipStart - y; var6 -= var10; - var2 = Rasterizer2D.Rasterizer2D_yClipStart; + y = Rasterizer2D.Rasterizer2D_yClipStart; var5 += var10 * var7; var4 += var10 * Rasterizer2D.Rasterizer2D_width; } - if (var6 + var2 > Rasterizer2D.Rasterizer2D_yClipEnd) { - var6 -= var6 + var2 - Rasterizer2D.Rasterizer2D_yClipEnd; + if (var6 + y > Rasterizer2D.Rasterizer2D_yClipEnd) { + var6 -= var6 + y - Rasterizer2D.Rasterizer2D_yClipEnd; } - if (var1 < Rasterizer2D.Rasterizer2D_xClipStart) { - var10 = Rasterizer2D.Rasterizer2D_xClipStart - var1; + if (x < Rasterizer2D.Rasterizer2D_xClipStart) { + var10 = Rasterizer2D.Rasterizer2D_xClipStart - x; var7 -= var10; - var1 = Rasterizer2D.Rasterizer2D_xClipStart; + x = Rasterizer2D.Rasterizer2D_xClipStart; var5 += var10; var4 += var10; var9 += var10; var8 += var10; } - if (var7 + var1 > Rasterizer2D.Rasterizer2D_xClipEnd) { - var10 = var7 + var1 - Rasterizer2D.Rasterizer2D_xClipEnd; + if (var7 + x > Rasterizer2D.Rasterizer2D_xClipEnd) { + var10 = var7 + x - Rasterizer2D.Rasterizer2D_xClipEnd; var7 -= var10; var9 += var10; var8 += var10; } if (var7 > 0 && var6 > 0) { - Sprite_drawTransparent(Rasterizer2D.Rasterizer2D_pixels, this.pixels, 0, var5, var4, var7, var6, var8, var9, var3); + Sprite_drawTransparent(Rasterizer2D.Rasterizer2D_pixels, this.pixels, 0, var5, var4, var7, var6, var8, var9, opacity); } } @ObfuscatedName("j") @Export("drawTransScaledAt") - public void drawTransScaledAt(int var1, int var2, int var3, int var4, int var5) { - if (var3 > 0 && var4 > 0) { + public void drawTransScaledAt(int x, int y, int width, int height, int opacity) { + if (width > 0 && height > 0) { int var6 = this.subWidth; int var7 = this.subHeight; int var8 = 0; int var9 = 0; int var10 = this.width; int var11 = this.height; - int var12 = (var10 << 16) / var3; - int var13 = (var11 << 16) / var4; + int var12 = (var10 << 16) / width; + int var13 = (var11 << 16) / height; int var14; if (this.xOffset > 0) { var14 = (var12 + (this.xOffset << 16) - 1) / var12; - var1 += var14; + x += var14; var8 += var14 * var12 - (this.xOffset << 16); } if (this.yOffset > 0) { var14 = (var13 + (this.yOffset << 16) - 1) / var13; - var2 += var14; + y += var14; var9 += var14 * var13 - (this.yOffset << 16); } if (var6 < var10) { - var3 = (var12 + ((var6 << 16) - var8) - 1) / var12; + width = (var12 + ((var6 << 16) - var8) - 1) / var12; } if (var7 < var11) { - var4 = (var13 + ((var7 << 16) - var9) - 1) / var13; + height = (var13 + ((var7 << 16) - var9) - 1) / var13; } - var14 = var1 + var2 * Rasterizer2D.Rasterizer2D_width; - int var15 = Rasterizer2D.Rasterizer2D_width - var3; - if (var2 + var4 > Rasterizer2D.Rasterizer2D_yClipEnd) { - var4 -= var2 + var4 - Rasterizer2D.Rasterizer2D_yClipEnd; + var14 = x + y * Rasterizer2D.Rasterizer2D_width; + int var15 = Rasterizer2D.Rasterizer2D_width - width; + if (y + height > Rasterizer2D.Rasterizer2D_yClipEnd) { + height -= y + height - Rasterizer2D.Rasterizer2D_yClipEnd; } int var16; - if (var2 < Rasterizer2D.Rasterizer2D_yClipStart) { - var16 = Rasterizer2D.Rasterizer2D_yClipStart - var2; - var4 -= var16; + if (y < Rasterizer2D.Rasterizer2D_yClipStart) { + var16 = Rasterizer2D.Rasterizer2D_yClipStart - y; + height -= var16; var14 += var16 * Rasterizer2D.Rasterizer2D_width; var9 += var13 * var16; } - if (var3 + var1 > Rasterizer2D.Rasterizer2D_xClipEnd) { - var16 = var3 + var1 - Rasterizer2D.Rasterizer2D_xClipEnd; - var3 -= var16; + if (width + x > Rasterizer2D.Rasterizer2D_xClipEnd) { + var16 = width + x - Rasterizer2D.Rasterizer2D_xClipEnd; + width -= var16; var15 += var16; } - if (var1 < Rasterizer2D.Rasterizer2D_xClipStart) { - var16 = Rasterizer2D.Rasterizer2D_xClipStart - var1; - var3 -= var16; + if (x < Rasterizer2D.Rasterizer2D_xClipStart) { + var16 = Rasterizer2D.Rasterizer2D_xClipStart - x; + width -= var16; var14 += var16; var8 += var12 * var16; var15 += var16; } - Sprite_drawTransScaled(Rasterizer2D.Rasterizer2D_pixels, this.pixels, 0, var8, var9, var14, var15, var3, var4, var12, var13, var6, var5); + Sprite_drawTransScaled(Rasterizer2D.Rasterizer2D_pixels, this.pixels, 0, var8, var9, var14, var15, width, height, var12, var13, var6, opacity); } } @ObfuscatedName("l") - public void method6082(int var1, int var2, int var3) { - var1 += this.xOffset; - var2 += this.yOffset; - int var4 = var1 + var2 * Rasterizer2D.Rasterizer2D_width; + public void method6082(int x, int y, int opacity) { + x += this.xOffset; + y += this.yOffset; + int var4 = x + y * Rasterizer2D.Rasterizer2D_width; int var5 = 0; int var6 = this.subHeight; int var7 = this.subWidth; int var8 = Rasterizer2D.Rasterizer2D_width - var7; int var9 = 0; int var10; - if (var2 < Rasterizer2D.Rasterizer2D_yClipStart) { - var10 = Rasterizer2D.Rasterizer2D_yClipStart - var2; + if (y < Rasterizer2D.Rasterizer2D_yClipStart) { + var10 = Rasterizer2D.Rasterizer2D_yClipStart - y; var6 -= var10; - var2 = Rasterizer2D.Rasterizer2D_yClipStart; + y = Rasterizer2D.Rasterizer2D_yClipStart; var5 += var10 * var7; var4 += var10 * Rasterizer2D.Rasterizer2D_width; } - if (var6 + var2 > Rasterizer2D.Rasterizer2D_yClipEnd) { - var6 -= var6 + var2 - Rasterizer2D.Rasterizer2D_yClipEnd; + if (var6 + y > Rasterizer2D.Rasterizer2D_yClipEnd) { + var6 -= var6 + y - Rasterizer2D.Rasterizer2D_yClipEnd; } - if (var1 < Rasterizer2D.Rasterizer2D_xClipStart) { - var10 = Rasterizer2D.Rasterizer2D_xClipStart - var1; + if (x < Rasterizer2D.Rasterizer2D_xClipStart) { + var10 = Rasterizer2D.Rasterizer2D_xClipStart - x; var7 -= var10; - var1 = Rasterizer2D.Rasterizer2D_xClipStart; + x = Rasterizer2D.Rasterizer2D_xClipStart; var5 += var10; var4 += var10; var9 += var10; var8 += var10; } - if (var7 + var1 > Rasterizer2D.Rasterizer2D_xClipEnd) { - var10 = var7 + var1 - Rasterizer2D.Rasterizer2D_xClipEnd; + if (var7 + x > Rasterizer2D.Rasterizer2D_xClipEnd) { + var10 = var7 + x - Rasterizer2D.Rasterizer2D_xClipEnd; var7 -= var10; var9 += var10; var8 += var10; } if (var7 > 0 && var6 > 0) { - if (var3 == 256) { + if (opacity == 256) { method6071(0, 0, 0, Rasterizer2D.Rasterizer2D_pixels, this.pixels, var5, 0, var4, 0, var7, var6, var8, var9); } else { - method6084(0, 0, 0, Rasterizer2D.Rasterizer2D_pixels, this.pixels, var5, 0, var4, 0, var7, var6, var8, var9, var3); + method6084(0, 0, 0, Rasterizer2D.Rasterizer2D_pixels, this.pixels, var5, 0, var4, 0, var7, var6, var8, var9, opacity); } } @@ -711,25 +711,25 @@ public final class Sprite extends Rasterizer2D { @ObfuscatedName("ax") @Export("drawRotatedMaskedCenteredAround") - public void drawRotatedMaskedCenteredAround(int var1, int var2, int var3, int var4, int var5, int var6, int var7, int var8, int[] var9, int[] var10) { + public void drawRotatedMaskedCenteredAround(int x, int y, int width, int height, int xOffset, int yOffset, int rotation, int zoom, int[] xOffsets, int[] yOffsets) { try { - int var11 = -var3 / 2; - int var12 = -var4 / 2; - int var13 = (int)(Math.sin((double)var7 / 326.11D) * 65536.0D); - int var14 = (int)(Math.cos((double)var7 / 326.11D) * 65536.0D); - var13 = var13 * var8 >> 8; - var14 = var14 * var8 >> 8; - int var15 = var12 * var13 + var11 * var14 + (var5 << 16); - int var16 = var12 * var14 - var11 * var13 + (var6 << 16); - int var17 = var1 + var2 * Rasterizer2D.Rasterizer2D_width; + int var11 = -width / 2; + int var12 = -height / 2; + int var13 = (int)(Math.sin((double)rotation / 326.11D) * 65536.0D); + int var14 = (int)(Math.cos((double)rotation / 326.11D) * 65536.0D); + var13 = var13 * zoom >> 8; + var14 = var14 * zoom >> 8; + int var15 = var12 * var13 + var11 * var14 + (xOffset << 16); + int var16 = var12 * var14 - var11 * var13 + (yOffset << 16); + int var17 = x + y * Rasterizer2D.Rasterizer2D_width; - for (var2 = 0; var2 < var4; ++var2) { - int var18 = var9[var2]; + for (y = 0; y < height; ++y) { + int var18 = xOffsets[y]; int var19 = var17 + var18; int var20 = var15 + var14 * var18; int var21 = var16 - var13 * var18; - for (var1 = -var10[var2]; var1 < 0; ++var1) { + for (x = -yOffsets[y]; x < 0; ++x) { Rasterizer2D.Rasterizer2D_pixels[var19++] = this.pixels[this.subWidth * (var21 >> 16) + (var20 >> 16)]; var20 += var14; var21 -= var13; diff --git a/runescape-client/src/main/java/class191.java b/runescape-client/src/main/java/class191.java index cf1181948e..4a991ac441 100644 --- a/runescape-client/src/main/java/class191.java +++ b/runescape-client/src/main/java/class191.java @@ -49,8 +49,8 @@ public class class191 { ) static final void method3639(Actor var0) { int var1 = var0.field948 - Client.cycle; - int var2 = var0.field932 * -527978816 + var0.field971 * 128; - int var3 = var0.field932 * -527978816 + var0.field973 * 128; + int var2 = var0.size * -527978816 + var0.field971 * 128; + int var3 = var0.size * -527978816 + var0.field973 * 128; var0.x += (var2 - var0.x) / var1; var0.y += (var3 - var0.y) / var1; var0.field949 = 0; diff --git a/runescape-client/src/main/java/class32.java b/runescape-client/src/main/java/class32.java index 285f0c56a2..290e8c7952 100644 --- a/runescape-client/src/main/java/class32.java +++ b/runescape-client/src/main/java/class32.java @@ -46,7 +46,7 @@ public class class32 { return; } - URL var3 = new URL(RunException.RunException_applet.getCodeBase(), "clienterror.ws?c=" + RunException.RunException_revision + "&u=" + RunException.localPlayerName + "&v1=" + TaskHandler.javaVendor + "&v2=" + TaskHandler.javaVersion + "&ct=" + class319.field3843 + "&e=" + var2); + URL var3 = new URL(RunException.RunException_applet.getCodeBase(), "clienterror.ws?c=" + RunException.RunException_revision + "&u=" + RunException.localPlayerName + "&v1=" + TaskHandler.javaVendor + "&v2=" + TaskHandler.javaVersion + "&ct=" + ClientType.clientType + "&e=" + var2); DataInputStream var4 = new DataInputStream(var3.openStream()); var4.read(); var4.close(); diff --git a/runescape-client/src/main/java/class325.java b/runescape-client/src/main/java/class325.java index 0c4d47df79..226d7e4e1c 100644 --- a/runescape-client/src/main/java/class325.java +++ b/runescape-client/src/main/java/class325.java @@ -63,8 +63,8 @@ public class class325 { var11 = var0.x; var12 = var0.y; - var4 = var0.pathX[var0.pathLength - 1] * 128 + var0.field932 * -527978816; - int var5 = var0.field932 * -527978816 + var0.pathY[var0.pathLength - 1] * 128; + var4 = var0.pathX[var0.pathLength - 1] * 128 + var0.size * -527978816; + int var5 = var0.size * -527978816 + var0.pathY[var0.pathLength - 1] * 128; if (var11 < var4) { if (var12 < var5) { var0.orientation = 1280; @@ -203,8 +203,8 @@ public class class325 { var0.spotAnimation = -1; var0.field948 = 0; var0.field976 = 0; - var0.x = var0.pathX[0] * 128 + var0.field932 * -527978816; - var0.y = var0.field932 * -527978816 + var0.pathY[0] * 128; + var0.x = var0.pathX[0] * 128 + var0.size * -527978816; + var0.y = var0.size * -527978816 + var0.pathY[0] * 128; var0.method1765(); } @@ -213,8 +213,8 @@ public class class325 { var0.spotAnimation = -1; var0.field948 = 0; var0.field976 = 0; - var0.x = var0.field932 * -527978816 + var0.pathX[0] * 128; - var0.y = var0.field932 * -527978816 + var0.pathY[0] * 128; + var0.x = var0.size * -527978816 + var0.pathX[0] * 128; + var0.y = var0.size * -527978816 + var0.pathY[0] * 128; var0.method1765(); } diff --git a/runescape-client/src/main/java/class4.java b/runescape-client/src/main/java/class4.java index f26b1b5cad..dc7e3353df 100644 --- a/runescape-client/src/main/java/class4.java +++ b/runescape-client/src/main/java/class4.java @@ -152,7 +152,7 @@ final class class4 implements class0 { int var3 = var2.x >> 7; int var4 = var2.y >> 7; if (var3 >= 0 && var3 < 104 && var4 >= 0 && var4 < 104) { - if (var2.field932 * 1669471931 == 1 && (var2.x & 127) == 64 && (var2.y & 127) == 64) { + if (var2.size * 1669471931 == 1 && (var2.x & 127) == 64 && (var2.y & 127) == 64) { if (Client.tileLastDrawnActor[var3][var4] == Client.viewportDrawCount) { continue; } @@ -162,7 +162,7 @@ final class class4 implements class0 { long var5 = class267.calculateTag(0, 0, 1, !var2.definition.isInteractable, Client.npcIndices[var1]); var2.playerCycle = Client.cycle; - PacketWriter.scene.drawEntity(WorldMapRectangle.plane, var2.x, var2.y, MusicPatchPcmStream.getTileHeight(var2.field932 * -527978816 - 64 + var2.x, var2.field932 * -527978816 - 64 + var2.y, WorldMapRectangle.plane), var2.field932 * -527978816 - 64 + 60, var2, var2.rotation, var5, var2.isWalking); + PacketWriter.scene.drawEntity(WorldMapRectangle.plane, var2.x, var2.y, MusicPatchPcmStream.getTileHeight(var2.size * -527978816 - 64 + var2.x, var2.size * -527978816 - 64 + var2.y, WorldMapRectangle.plane), var2.size * -527978816 - 64 + 60, var2, var2.rotation, var5, var2.isWalking); } } }