hunter plugin: Don't iterate over all tiles

This commit is contained in:
Max Weber
2018-03-09 18:27:34 -07:00
parent c3920e5814
commit 2a579a3ebf
3 changed files with 109 additions and 102 deletions

View File

@@ -28,10 +28,10 @@ import com.google.common.eventbus.Subscribe;
import com.google.inject.Provides; import com.google.inject.Provides;
import java.time.Instant; import java.time.Instant;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Map;
import javax.inject.Inject; import javax.inject.Inject;
import lombok.Getter; import lombok.Getter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -39,11 +39,12 @@ import net.runelite.api.Client;
import net.runelite.api.GameObject; import net.runelite.api.GameObject;
import net.runelite.api.ObjectID; import net.runelite.api.ObjectID;
import net.runelite.api.Player; import net.runelite.api.Player;
import net.runelite.api.Tile;
import net.runelite.api.coords.LocalPoint;
import net.runelite.api.coords.WorldPoint; import net.runelite.api.coords.WorldPoint;
import net.runelite.api.events.ConfigChanged; import net.runelite.api.events.ConfigChanged;
import net.runelite.api.events.GameObjectSpawned; import net.runelite.api.events.GameObjectSpawned;
import net.runelite.api.events.GameTick; import net.runelite.api.events.GameTick;
import net.runelite.api.queries.GameObjectQuery;
import net.runelite.api.queries.PlayerQuery; import net.runelite.api.queries.PlayerQuery;
import net.runelite.client.Notifier; import net.runelite.client.Notifier;
import net.runelite.client.config.ConfigManager; import net.runelite.client.config.ConfigManager;
@@ -74,7 +75,7 @@ public class HunterPlugin extends Plugin
private HunterConfig config; private HunterConfig config;
@Getter @Getter
private final Set<HunterTrap> traps = new HashSet<>(); private final Map<WorldPoint, HunterTrap> traps = new HashMap<>();
@Getter @Getter
private Instant lastActionTime = Instant.ofEpochMilli(0); private Instant lastActionTime = Instant.ofEpochMilli(0);
@@ -102,7 +103,7 @@ public class HunterPlugin extends Plugin
public void onGameObjectSpawned(GameObjectSpawned event) public void onGameObjectSpawned(GameObjectSpawned event)
{ {
final GameObject gameObject = event.getGameObject(); final GameObject gameObject = event.getGameObject();
final HunterTrap myTrap = getTrapFromCollection(gameObject); final HunterTrap myTrap = traps.get(gameObject.getWorldLocation());
final Player localPlayer = client.getLocalPlayer(); final Player localPlayer = client.getLocalPlayer();
switch (gameObject.getId()) switch (gameObject.getId())
@@ -118,7 +119,7 @@ public class HunterPlugin extends Plugin
if (localPlayer.getWorldLocation().distanceTo(gameObject.getWorldLocation()) <= 1) if (localPlayer.getWorldLocation().distanceTo(gameObject.getWorldLocation()) <= 1)
{ {
log.debug("Trap placed by \"{}\" on {}", localPlayer.getName(), gameObject.getWorldLocation()); log.debug("Trap placed by \"{}\" on {}", localPlayer.getName(), gameObject.getWorldLocation());
traps.add(new HunterTrap(gameObject)); traps.put(gameObject.getWorldLocation(), new HunterTrap(gameObject));
lastActionTime = Instant.now(); lastActionTime = Instant.now();
} }
@@ -138,7 +139,7 @@ public class HunterPlugin extends Plugin
if (possiblePlayers.contains(localPlayer)) if (possiblePlayers.contains(localPlayer))
{ {
log.debug("Trap placed by \"{}\" on {}", localPlayer.getName(), localPlayer.getWorldLocation()); log.debug("Trap placed by \"{}\" on {}", localPlayer.getName(), localPlayer.getWorldLocation());
traps.add(new HunterTrap(gameObject)); traps.put(gameObject.getWorldLocation(), new HunterTrap(gameObject));
lastActionTime = Instant.now(); lastActionTime = Instant.now();
} }
@@ -172,7 +173,7 @@ public class HunterPlugin extends Plugin
myTrap.setState(HunterTrap.State.FULL); myTrap.setState(HunterTrap.State.FULL);
lastActionTime = Instant.now(); lastActionTime = Instant.now();
if (config.maniacalMonkeyNotify() && myTrap.getGameObject().getId() == ObjectID.MONKEY_TRAP) if (config.maniacalMonkeyNotify() && myTrap.getObjectId() == ObjectID.MONKEY_TRAP)
{ {
notifier.notify("You've caught part of a monkey's tail."); notifier.notify("You've caught part of a monkey's tail.");
} }
@@ -267,35 +268,64 @@ public class HunterPlugin extends Plugin
public void onGameTick(GameTick event) public void onGameTick(GameTick event)
{ {
// Check if all traps are still there, and remove the ones that are not. // Check if all traps are still there, and remove the ones that are not.
// TODO: use despawn events Iterator<Map.Entry<WorldPoint, HunterTrap>> it = traps.entrySet().iterator();
Iterator<HunterTrap> it = traps.iterator(); Tile[][][] tiles = client.getRegion().getTiles();
Instant expire = Instant.now().minus(HunterTrap.TRAP_TIME.multipliedBy(2));
while (it.hasNext()) while (it.hasNext())
{ {
HunterTrap trap = it.next(); Map.Entry<WorldPoint, HunterTrap> entry = it.next();
HunterTrap trap = entry.getValue();
WorldPoint world = entry.getKey();
LocalPoint local = LocalPoint.fromWorld(client, world);
// Look for gameobjects that are on the same location as the trap // Not within the client's viewport
GameObjectQuery goQuery = new GameObjectQuery() if (local == null)
.atWorldLocation(trap.getGameObject().getWorldLocation()); {
// This is for placeable traps like box traps. There are no gameobjects on that location if the trap collapsed // Cull very old traps
if (queryRunner.runQuery(goQuery).length == 0) 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(); it.remove();
log.debug("Trap removed from personal trap collection, {} left", traps.size()); log.debug("Trap removed from personal trap collection, {} left", traps.size());
} }
else // For traps like deadfalls. This is different because when the trap is gone, there is still a GameObject (boulder) else if (containsBoulder) // For traps like deadfalls. This is different because when the trap is gone, there is still a GameObject (boulder)
{ {
goQuery = goQuery.idEquals(ObjectID.BOULDER_19215, ObjectID.LARGE_BOULDER); it.remove();
if (queryRunner.runQuery(goQuery).length != 0) log.debug("Special trap removed from personal trap collection, {} left", traps.size());
{
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 // Case we have notifications enabled and the action was not manual, throw notification
if (config.maniacalMonkeyNotify() && trap.getGameObject().getId() == ObjectID.MONKEY_TRAP && if (config.maniacalMonkeyNotify() && trap.getObjectId() == ObjectID.MONKEY_TRAP &&
!trap.getState().equals(HunterTrap.State.FULL) && !trap.getState().equals(HunterTrap.State.OPEN)) !trap.getState().equals(HunterTrap.State.FULL) && !trap.getState().equals(HunterTrap.State.OPEN))
{ {
notifier.notify("The monkey escaped."); notifier.notify("The monkey escaped.");
}
} }
} }
} }
@@ -310,27 +340,4 @@ public class HunterPlugin extends Plugin
overlay.updateConfig(); overlay.updateConfig();
} }
} }
/**
* Looks for a trap in the local players trap collection, on the same
* place as the given GameObject.
*
* @param gameObject game object
* @return A HunterTrap object if the player has a trap on the same
* location as the GameObject. Otherwise it returns null.
*/
private HunterTrap getTrapFromCollection(GameObject gameObject)
{
final WorldPoint gameObjectLocation = gameObject.getWorldLocation();
for (HunterTrap trap : traps)
{
if (gameObjectLocation.equals(trap.getGameObject().getWorldLocation()))
{
return trap;
}
}
return null;
}
} }

View File

@@ -26,10 +26,10 @@ package net.runelite.client.plugins.hunter;
import java.time.Duration; import java.time.Duration;
import java.time.Instant; import java.time.Instant;
import java.util.Objects;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import net.runelite.api.GameObject; import net.runelite.api.GameObject;
import net.runelite.api.coords.WorldPoint;
/** /**
* Wrapper class for a GameObject that represents a hunter trap. * Wrapper class for a GameObject that represents a hunter trap.
@@ -39,7 +39,7 @@ class HunterTrap
/** /**
* A hunter trap stays up 1 minute before collapsing. * A hunter trap stays up 1 minute before collapsing.
*/ */
private static final Duration TRAP_TIME = Duration.ofMinutes(1); static final Duration TRAP_TIME = Duration.ofMinutes(1);
/** /**
* The time in milliseconds when the trap was placed. * The time in milliseconds when the trap was placed.
@@ -55,10 +55,13 @@ class HunterTrap
private State state; private State state;
/** /**
* The gameobject thats corresponds with this trap. * The ID of the game object this is representing
*/ */
@Getter @Getter
private final GameObject gameObject; private int objectId;
@Getter
private WorldPoint worldLocation;
/** /**
* The states a trap can be in. * The states a trap can be in.
@@ -91,8 +94,9 @@ class HunterTrap
HunterTrap(GameObject gameObject) HunterTrap(GameObject gameObject)
{ {
this.state = State.OPEN; this.state = State.OPEN;
this.gameObject = gameObject;
this.placedOn = Instant.now(); this.placedOn = Instant.now();
this.objectId = gameObject.getId();
this.worldLocation = gameObject.getWorldLocation();
} }
/** /**
@@ -114,27 +118,4 @@ class HunterTrap
{ {
placedOn = Instant.now(); placedOn = Instant.now();
} }
@Override
public boolean equals(Object o)
{
if (o == this)
{
return true;
}
if (!(o instanceof HunterTrap))
{
return false;
}
HunterTrap t = (HunterTrap) o;
return gameObject.getWorldLocation().equals(t.getGameObject().getWorldLocation());
}
@Override
public int hashCode()
{
int hash = 7;
hash = 97 * hash + Objects.hashCode(this.gameObject.getWorldLocation());
return hash;
}
} }

View File

@@ -30,9 +30,13 @@ import java.awt.Dimension;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.Point; import java.awt.Point;
import java.awt.geom.Arc2D; import java.awt.geom.Arc2D;
import java.util.Iterator;
import java.util.Map;
import javax.inject.Inject; import javax.inject.Inject;
import net.runelite.api.Client; import net.runelite.api.Client;
import net.runelite.api.Perspective;
import net.runelite.api.coords.LocalPoint; import net.runelite.api.coords.LocalPoint;
import net.runelite.api.coords.WorldPoint;
import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayLayer; import net.runelite.client.ui.overlay.OverlayLayer;
import net.runelite.client.ui.overlay.OverlayPosition; import net.runelite.client.ui.overlay.OverlayPosition;
@@ -43,8 +47,6 @@ import net.runelite.client.ui.overlay.OverlayPosition;
*/ */
public class TrapOverlay extends Overlay public class TrapOverlay extends Overlay
{ {
private static final int MAX_DISTANCE = 2500;
/** /**
* Size of the trap timer. * Size of the trap timer.
*/ */
@@ -109,27 +111,26 @@ public class TrapOverlay extends Overlay
*/ */
private void drawTraps(Graphics2D graphics) private void drawTraps(Graphics2D graphics)
{ {
LocalPoint localLocation = client.getLocalPlayer().getLocalLocation(); Iterator<Map.Entry<WorldPoint, HunterTrap>> it = plugin.getTraps().entrySet().iterator();
for (HunterTrap trap : plugin.getTraps()) while (it.hasNext())
{ {
LocalPoint trapLocation = trap.getGameObject().getLocalLocation(); Map.Entry<WorldPoint, HunterTrap> entry = it.next();
if (trapLocation != null && localLocation.distanceTo(trapLocation) <= MAX_DISTANCE) HunterTrap trap = entry.getValue();
switch (trap.getState())
{ {
switch (trap.getState()) case OPEN:
{ drawTimerOnTrap(graphics, trap, colorOpen, colorOpenBorder, colorEmpty, colorOpenBorder);
case OPEN: break;
drawTimerOnTrap(graphics, trap, colorOpen, colorOpenBorder, colorEmpty, colorOpenBorder); case EMPTY:
break; drawTimerOnTrap(graphics, trap, colorEmpty, colorEmptyBorder, colorEmpty, colorEmptyBorder);
case EMPTY: break;
drawTimerOnTrap(graphics, trap, colorEmpty, colorEmptyBorder, colorEmpty, colorEmptyBorder); case FULL:
break; drawCircleOnTrap(graphics, trap, colorFull, colorFullBorder);
case FULL: break;
drawCircleOnTrap(graphics, trap, colorFull, colorFullBorder); case TRANSITION:
break; drawCircleOnTrap(graphics, trap, colorTrans, colorTransBorder);
case TRANSITION: break;
drawCircleOnTrap(graphics, trap, colorTrans, colorTransBorder);
break;
}
} }
} }
} }
@@ -146,7 +147,16 @@ public class TrapOverlay extends Overlay
*/ */
private void drawTimerOnTrap(Graphics2D graphics, HunterTrap trap, Color fill, Color border, Color fillTimeLow, Color borderTimeLow) private void drawTimerOnTrap(Graphics2D graphics, HunterTrap trap, Color fill, Color border, Color fillTimeLow, Color borderTimeLow)
{ {
net.runelite.api.Point loc = trap.getGameObject().getCanvasLocation(); if (trap.getWorldLocation().getPlane() != client.getPlane())
{
return;
}
LocalPoint localLoc = LocalPoint.fromWorld(client, trap.getWorldLocation());
if (localLoc == null)
{
return;
}
net.runelite.api.Point loc = Perspective.worldToCanvas(client, localLoc.getX(), localLoc.getY(), trap.getWorldLocation().getPlane());
//Construct the arc //Construct the arc
Arc2D.Float arc = new Arc2D.Float(Arc2D.PIE); Arc2D.Float arc = new Arc2D.Float(Arc2D.PIE);
@@ -175,7 +185,16 @@ public class TrapOverlay extends Overlay
*/ */
private void drawCircleOnTrap(Graphics2D graphics, HunterTrap trap, Color fill, Color border) private void drawCircleOnTrap(Graphics2D graphics, HunterTrap trap, Color fill, Color border)
{ {
net.runelite.api.Point loc = trap.getGameObject().getCanvasLocation(); if (trap.getWorldLocation().getPlane() != client.getPlane())
{
return;
}
LocalPoint localLoc = LocalPoint.fromWorld(client, trap.getWorldLocation());
if (localLoc == null)
{
return;
}
net.runelite.api.Point loc = Perspective.worldToCanvas(client, localLoc.getX(), localLoc.getY(), trap.getWorldLocation().getPlane());
//Draw the inside of the arc //Draw the inside of the arc
graphics.setColor(fill); graphics.setColor(fill);