use of net.runelite.api.coords.WorldPoint in project runelite by runelite.
the class CannonSpotOverlay method render.
@Override
public Dimension render(Graphics2D graphics) {
if (!config.showCannonSpots() || plugin.isCannonPlaced()) {
return null;
}
for (WorldPoint spot : plugin.getSpotPoints()) {
if (spot.getPlane() != client.getPlane()) {
continue;
}
LocalPoint spotPoint = LocalPoint.fromWorld(client, spot);
LocalPoint localLocation = client.getLocalPlayer().getLocalLocation();
if (spotPoint != null && localLocation.distanceTo(spotPoint) <= MAX_DISTANCE) {
renderCannonSpot(graphics, client, spotPoint, itemManager.getImage(CANNONBALL), Color.RED);
}
}
return null;
}
use of net.runelite.api.coords.WorldPoint in project runelite by runelite.
the class Library method add.
private void add(int x, int y, int z, int i) {
// 'i' is added as a parameter for readability
WorldPoint p = new WorldPoint(x, y, z);
Bookcase b = byPoint.get(p);
if (b == null) {
b = new Bookcase(p);
byPoint.put(p, b);
byLevel.computeIfAbsent(z, a -> new ArrayList<>()).add(b);
}
b.getIndex().add(i);
assert i == byIndex.size();
byIndex.add(b);
}
use of net.runelite.api.coords.WorldPoint in project runelite by runelite.
the class Library method mark.
public synchronized void mark(WorldPoint loc, Book book) {
Bookcase bookcase = byPoint.get(loc);
if (bookcase == null) {
log.debug("Requested non-existent bookcase at {}", loc);
return;
}
if (bookcase.isBookSet()) {
// Check for a mismatch, unless it is now null and had a dark manuscript
if (book != bookcase.getBook() && !(book == null && bookcase.getBook().isDarkManuscript())) {
reset();
}
} else if (state != SolvedState.NO_DATA) {
// We know all of the possible things in this shelf.
if (book != null) {
// Check to see if our guess is wrong
if (!bookcase.getPossibleBooks().contains(book)) {
reset();
}
}
}
// Everything is known, nothing to do
if (state == SolvedState.COMPLETE) {
return;
}
log.info("Setting bookcase {} to {}", bookcase.getIndex(), book);
for (; ; ) {
bookcase.setBook(book);
// Basing the sequences on null is not supported, though possible
if (book == null) {
return;
}
// This is one of the 6 bookcases with 2 ids. Not fully supported.
if (bookcase.getIndex().size() != 1) {
return;
}
int bookcaseIndex = bookcase.getIndex().get(0);
state = SolvedState.INCOMPLETE;
// Map each sequence to the number of bookcases that match the sequence
// return 0 if it is a mismatch.
// Keep in mind that Bookcases with dark manuscripts may be set to null.
int[] certainty = sequences.stream().mapToInt(sequence -> {
int zero = getBookcaseZeroIndexForSequenceWithBook(sequence, bookcaseIndex, book);
int found = 0;
for (int i = 0; i < byIndex.size(); i++) {
int ai = (i + zero) % byIndex.size();
Bookcase iBookcase = byIndex.get(ai);
if (i % step == 0) {
int seqI = i / step;
if (iBookcase.isBookSet() && seqI < sequence.size()) {
Book seqBook = sequence.get(seqI);
boolean isSeqManuscript = seqBook == null || seqBook.isDarkManuscript();
if (!((isSeqManuscript && iBookcase.getBook() == null) || (iBookcase.getBook() == seqBook))) {
log.debug("Bailing @ i={} ai={} {}; {} != {}", i, ai, iBookcase.getIndex(), iBookcase.getBook(), seqBook);
found = 0;
break;
}
found++;
}
} else {
// Only bail if this isn't a double bookcase
if (iBookcase.isBookSet() && iBookcase.getBook() != null && iBookcase.getIndex().size() == 1) {
log.debug("Bailing @ i={} ai={} {}; {} is set", i, ai, iBookcase.getIndex(), iBookcase.getBook());
found = 0;
break;
}
}
}
return found;
}).toArray();
log.info("Certainty is now {}", certainty);
for (Bookcase b : byIndex) {
b.getPossibleBooks().clear();
}
// Write the most likely sequences onto the bookcases
int max = IntStream.of(certainty).max().getAsInt();
// We have books set, but 0 sequences match, Something is wrong, reset.
if (max == 0) {
reset();
continue;
}
IntStream.range(0, sequences.size()).filter(i -> certainty[i] == max).forEach(isequence -> {
List<Book> sequence = sequences.get(isequence);
int zero = getBookcaseZeroIndexForSequenceWithBook(sequence, bookcaseIndex, book);
for (int i = 0; i < byIndex.size(); i++) {
int ai = (i + zero) % byIndex.size();
Bookcase iBookcase = byIndex.get(ai);
if (iBookcase.getBook() == null) {
int iseq = i / step;
if (i % step == 0 && iseq < sequence.size()) {
Book seqBook = sequence.get(iseq);
iBookcase.getPossibleBooks().add(seqBook);
}
}
}
});
if (IntStream.range(0, certainty.length).filter(i -> certainty[i] == max).count() == 1) {
state = SolvedState.COMPLETE;
}
return;
}
}
use of net.runelite.api.coords.WorldPoint in project runelite by runelite.
the class HunterPlugin method onGameTick.
/**
* Iterates over all the traps that were placed by the local player and
* checks if the trap is still there. If the trap is gone, it removes
* the trap from the local players trap collection.
*/
@Subscribe
public void onGameTick(GameTick event) {
// Check if all traps are still there, and remove the ones that are not.
Iterator<Map.Entry<WorldPoint, HunterTrap>> it = traps.entrySet().iterator();
Tile[][][] tiles = client.getRegion().getTiles();
Instant expire = Instant.now().minus(HunterTrap.TRAP_TIME.multipliedBy(2));
while (it.hasNext()) {
Map.Entry<WorldPoint, HunterTrap> entry = it.next();
HunterTrap trap = entry.getValue();
WorldPoint world = entry.getKey();
LocalPoint local = LocalPoint.fromWorld(client, world);
// Not within the client's viewport
if (local == null) {
// Cull very old traps
if (trap.getPlacedOn().isBefore(expire)) {
log.debug("Trap removed from personal trap collection due to timeout, {} left", traps.size());
it.remove();
continue;
}
continue;
}
Tile tile = tiles[world.getPlane()][local.getRegionX()][local.getRegionY()];
GameObject[] objects = tile.getGameObjects();
boolean containsBoulder = false;
boolean containsAnything = false;
for (GameObject object : objects) {
if (object != null) {
containsAnything = true;
if (object.getId() == ObjectID.BOULDER_19215 || object.getId() == ObjectID.LARGE_BOULDER) {
containsBoulder = true;
break;
}
}
}
if (!containsAnything) {
it.remove();
log.debug("Trap removed from personal trap collection, {} left", traps.size());
} else if (// For traps like deadfalls. This is different because when the trap is gone, there is still a GameObject (boulder)
containsBoulder) {
it.remove();
log.debug("Special trap removed from personal trap collection, {} left", traps.size());
// Case we have notifications enabled and the action was not manual, throw notification
if (config.maniacalMonkeyNotify() && trap.getObjectId() == ObjectID.MONKEY_TRAP && !trap.getState().equals(HunterTrap.State.FULL) && !trap.getState().equals(HunterTrap.State.OPEN)) {
notifier.notify("The monkey escaped.");
}
}
}
}
use of net.runelite.api.coords.WorldPoint in project runelite by runelite.
the class KourendLibraryOverlay method render.
@Override
public Dimension render(Graphics2D g) {
Player player = client.getLocalPlayer();
if (player == null) {
return null;
}
WorldPoint playerLoc = player.getWorldLocation();
if (playerLoc.distanceTo2D(LIBRARY_CENTER) > ROUGH_ENABLE_DISTANCE) {
return null;
}
List<Bookcase> allBookcases = library.getBookcasesOnLevel(client.getPlane());
if (allBookcases == null) {
return null;
}
for (Bookcase bookcase : allBookcases) {
// AABB
WorldPoint caseLoc = bookcase.getLocation();
if (Math.abs(playerLoc.getX() - caseLoc.getX()) > MAXIMUM_DISTANCE || Math.abs(playerLoc.getY() - caseLoc.getY()) > MAXIMUM_DISTANCE) {
continue;
}
LocalPoint localBookcase = LocalPoint.fromWorld(client, caseLoc);
if (localBookcase == null) {
continue;
}
Point screenBookcase = Perspective.worldToCanvas(client, localBookcase.getX(), localBookcase.getY(), caseLoc.getPlane(), 25);
if (screenBookcase != null) {
boolean bookIsKnown = bookcase.isBookSet();
Book book = bookcase.getBook();
Set<Book> possible = bookcase.getPossibleBooks();
if (bookIsKnown && book == null) {
for (Book b : possible) {
if (b != null && b.isDarkManuscript()) {
book = b;
break;
}
}
}
if (!bookIsKnown && possible.size() == 1) {
book = possible.iterator().next();
bookIsKnown = true;
}
Color color = bookIsKnown ? Color.ORANGE : Color.WHITE;
// Render the poly on the floor
if (!(bookIsKnown && book == null) && (library.getState() == SolvedState.NO_DATA || book != null || possible.size() > 0)) {
Polygon poly = getCanvasTilePoly(client, localBookcase);
if (poly != null) {
OverlayUtil.renderPolygon(g, poly, color);
}
}
int height = 0;
// If the book is singled out, render the text and the book's icon
if (bookIsKnown) {
if (book != null) {
FontMetrics fm = g.getFontMetrics();
Rectangle2D bounds = fm.getStringBounds(book.getShortName(), g);
height = (int) bounds.getHeight() + book.getIcon().getHeight() + 6;
Point textLoc = new Point((int) (screenBookcase.getX() - (bounds.getWidth() / 2)), screenBookcase.getY() - (height / 2) + (int) bounds.getHeight());
OverlayUtil.renderTextLocation(g, textLoc, book.getShortName(), color);
g.drawImage(book.getIcon(), screenBookcase.getX() - (book.getIcon().getWidth() / 2), screenBookcase.getY() + (height / 2) - book.getIcon().getHeight(), null);
}
} else {
// otherwise render up to 9 icons of the possible books in the bookcase in a square
final int BOOK_ICON_SIZE = 32;
Book[] books = possible.stream().filter(Objects::nonNull).limit(9).toArray(Book[]::new);
if (books.length > 1 && books.length <= 9) {
int cols = (int) Math.ceil(Math.sqrt(books.length));
int rows = (int) Math.ceil((double) books.length / cols);
height = rows * BOOK_ICON_SIZE;
int xbase = screenBookcase.getX() - ((cols * BOOK_ICON_SIZE) / 2);
int ybase = screenBookcase.getY() - rows * BOOK_ICON_SIZE / 2;
for (int i = 0; i < books.length; i++) {
int col = i % cols;
int row = i / cols;
int x = col * BOOK_ICON_SIZE;
int y = row * BOOK_ICON_SIZE;
if (row == rows - 1) {
x += (BOOK_ICON_SIZE * (books.length % rows)) / 2;
}
g.drawImage(books[i].getIcon(), xbase + x, ybase + y, null);
}
}
}
// Draw the bookcase's ID on top
if (KourendLibraryPlugin.debug) {
FontMetrics fm = g.getFontMetrics();
String str = bookcase.getIndex().stream().map(Object::toString).collect(Collectors.joining(", "));
Rectangle2D bounds = fm.getStringBounds(str, g);
Point textLoc = new Point((int) (screenBookcase.getX() - (bounds.getWidth() / 2)), screenBookcase.getY() - (height / 2));
OverlayUtil.renderTextLocation(g, textLoc, str, Color.WHITE);
}
}
}
// Render the customer's wanted book on their head and a poly under their feet
LibraryCustomer customer = library.getCustomer();
if (customer != null) {
client.getNpcs().stream().filter(n -> n.getId() == customer.getId()).forEach(n -> {
Book b = library.getCustomerBook();
LocalPoint local = n.getLocalLocation();
Polygon poly = getCanvasTilePoly(client, local);
OverlayUtil.renderPolygon(g, poly, Color.WHITE);
Point screen = Perspective.worldToCanvas(client, local.getX(), local.getY(), client.getPlane(), n.getLogicalHeight());
if (screen != null) {
g.drawImage(b.getIcon(), screen.getX() - (b.getIcon().getWidth() / 2), screen.getY() - b.getIcon().getHeight(), null);
}
});
}
return null;
}
Aggregations