Merge pull request #1707 from Owain94/0310-merge
project: Merge upstream
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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())
|
||||
{
|
||||
|
||||
@@ -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())
|
||||
{
|
||||
|
||||
@@ -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<WorldResult> 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())
|
||||
{
|
||||
|
||||
@@ -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<FeedResult> 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Integer, Integer> cachedEmpty = CacheBuilder.newBuilder()
|
||||
.maximumSize(1024L)
|
||||
.build();
|
||||
|
||||
private final ItemService itemService;
|
||||
|
||||
private final Supplier<ItemPrice[]> memorizedPrices;
|
||||
private final Supplier<MemoizedPrices> 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<ItemPrice[]> 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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<Triangle> 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<Vertex> 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<Triangle> 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<Vertex> 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<Point> 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<SimplePolygon> 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<SimplePolygon> 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<RectangleUnion.Rectangle> 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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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<SimplePolygon> union(List<Rectangle> 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<Rectangle> 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<SimplePolygon> 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<SimplePolygon> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
212
runelite-api/src/main/java/net/runelite/api/geometry/Shapes.java
Normal file
212
runelite-api/src/main/java/net/runelite/api/geometry/Shapes.java
Normal file
@@ -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<T extends Shape> implements Shape
|
||||
{
|
||||
public Shapes(T ...shape)
|
||||
{
|
||||
this(Arrays.asList(shape));
|
||||
}
|
||||
|
||||
@Getter
|
||||
private final List<T> 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<PathIterator> iter;
|
||||
private PathIterator current = null;
|
||||
private final int windingRule;
|
||||
|
||||
ShapeIterator(Iterator<PathIterator> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<Point> toRuneLitePointList()
|
||||
{
|
||||
List<Point> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
* <p>
|
||||
* 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<Point> convexHull(List<Point> 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<Point> ch = new ArrayList<>();
|
||||
return poly.toRuneLitePointList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes and returns the convex hull of the passed points.
|
||||
* <p>
|
||||
* 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<Point> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<RectangleUnion.Rectangle> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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> 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());
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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<Integer, ItemStats> itemStatMap;
|
||||
private final LoadingCache<ImageKey, AsyncBufferedImage> itemImages;
|
||||
private final LoadingCache<Integer, ItemDefinition> 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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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()))
|
||||
|
||||
@@ -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.")
|
||||
|
||||
@@ -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)),
|
||||
|
||||
@@ -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."),
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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<FeedResult> feedSupplier = Suppliers.memoizeWithExpiration(() ->
|
||||
{
|
||||
try
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()))
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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()))
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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<Triangle> triangles = model.getTriangles();
|
||||
|
||||
triangles = rotate(triangles, orientation);
|
||||
|
||||
List<Polygon> polys = new ArrayList<Polygon>();
|
||||
for (Triangle triangle : triangles)
|
||||
{
|
||||
Vertex vx = triangle.getA();
|
||||
Vertex vy = triangle.getB();
|
||||
Vertex vz = triangle.getC();
|
||||
|
||||
Point x = Perspective.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<Triangle> rotate(List<Triangle> triangles, int orientation)
|
||||
{
|
||||
List<Triangle> rotatedTriangles = new ArrayList<Triangle>();
|
||||
for (Triangle triangle : triangles)
|
||||
{
|
||||
Vertex a = triangle.getA();
|
||||
Vertex b = triangle.getB();
|
||||
Vertex c = triangle.getC();
|
||||
|
||||
Triangle rotatedTriangle = new Triangle(
|
||||
a.rotate(orientation),
|
||||
b.rotate(orientation),
|
||||
c.rotate(orientation)
|
||||
);
|
||||
rotatedTriangles.add(rotatedTriangle);
|
||||
}
|
||||
return rotatedTriangles;
|
||||
}
|
||||
|
||||
@Inject
|
||||
@Override
|
||||
public Polygon getConvexHull()
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
BIN
runescape-client/.DS_Store
vendored
BIN
runescape-client/.DS_Store
vendored
Binary file not shown.
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user