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 java.time.Instant;
import java.util.Arrays;
import java.util.HashSet;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.Map;
import javax.inject.Inject;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
@@ -39,11 +39,12 @@ import net.runelite.api.Client;
import net.runelite.api.GameObject;
import net.runelite.api.ObjectID;
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.events.ConfigChanged;
import net.runelite.api.events.GameObjectSpawned;
import net.runelite.api.events.GameTick;
import net.runelite.api.queries.GameObjectQuery;
import net.runelite.api.queries.PlayerQuery;
import net.runelite.client.Notifier;
import net.runelite.client.config.ConfigManager;
@@ -74,7 +75,7 @@ public class HunterPlugin extends Plugin
private HunterConfig config;
@Getter
private final Set<HunterTrap> traps = new HashSet<>();
private final Map<WorldPoint, HunterTrap> traps = new HashMap<>();
@Getter
private Instant lastActionTime = Instant.ofEpochMilli(0);
@@ -102,7 +103,7 @@ public class HunterPlugin extends Plugin
public void onGameObjectSpawned(GameObjectSpawned event)
{
final GameObject gameObject = event.getGameObject();
final HunterTrap myTrap = getTrapFromCollection(gameObject);
final HunterTrap myTrap = traps.get(gameObject.getWorldLocation());
final Player localPlayer = client.getLocalPlayer();
switch (gameObject.getId())
@@ -118,7 +119,7 @@ public class HunterPlugin extends Plugin
if (localPlayer.getWorldLocation().distanceTo(gameObject.getWorldLocation()) <= 1)
{
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();
}
@@ -138,7 +139,7 @@ public class HunterPlugin extends Plugin
if (possiblePlayers.contains(localPlayer))
{
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();
}
@@ -172,7 +173,7 @@ public class HunterPlugin extends Plugin
myTrap.setState(HunterTrap.State.FULL);
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.");
}
@@ -267,35 +268,64 @@ public class HunterPlugin extends Plugin
public void onGameTick(GameTick event)
{
// Check if all traps are still there, and remove the ones that are not.
// TODO: use despawn events
Iterator<HunterTrap> it = traps.iterator();
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())
{
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
GameObjectQuery goQuery = new GameObjectQuery()
.atWorldLocation(trap.getGameObject().getWorldLocation());
// This is for placeable traps like box traps. There are no gameobjects on that location if the trap collapsed
if (queryRunner.runQuery(goQuery).length == 0)
// 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 // 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);
if (queryRunner.runQuery(goQuery).length != 0)
{
it.remove();
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
if (config.maniacalMonkeyNotify() && trap.getGameObject().getId() == ObjectID.MONKEY_TRAP &&
!trap.getState().equals(HunterTrap.State.FULL) && !trap.getState().equals(HunterTrap.State.OPEN))
{
notifier.notify("The monkey escaped.");
}
// 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.");
}
}
}
@@ -310,27 +340,4 @@ public class HunterPlugin extends Plugin
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.Instant;
import java.util.Objects;
import lombok.Getter;
import lombok.Setter;
import net.runelite.api.GameObject;
import net.runelite.api.coords.WorldPoint;
/**
* 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.
*/
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.
@@ -55,10 +55,13 @@ class HunterTrap
private State state;
/**
* The gameobject thats corresponds with this trap.
* The ID of the game object this is representing
*/
@Getter
private final GameObject gameObject;
private int objectId;
@Getter
private WorldPoint worldLocation;
/**
* The states a trap can be in.
@@ -91,8 +94,9 @@ class HunterTrap
HunterTrap(GameObject gameObject)
{
this.state = State.OPEN;
this.gameObject = gameObject;
this.placedOn = Instant.now();
this.objectId = gameObject.getId();
this.worldLocation = gameObject.getWorldLocation();
}
/**
@@ -114,27 +118,4 @@ class HunterTrap
{
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.Point;
import java.awt.geom.Arc2D;
import java.util.Iterator;
import java.util.Map;
import javax.inject.Inject;
import net.runelite.api.Client;
import net.runelite.api.Perspective;
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.OverlayLayer;
import net.runelite.client.ui.overlay.OverlayPosition;
@@ -43,8 +47,6 @@ import net.runelite.client.ui.overlay.OverlayPosition;
*/
public class TrapOverlay extends Overlay
{
private static final int MAX_DISTANCE = 2500;
/**
* Size of the trap timer.
*/
@@ -109,27 +111,26 @@ public class TrapOverlay extends Overlay
*/
private void drawTraps(Graphics2D graphics)
{
LocalPoint localLocation = client.getLocalPlayer().getLocalLocation();
for (HunterTrap trap : plugin.getTraps())
Iterator<Map.Entry<WorldPoint, HunterTrap>> it = plugin.getTraps().entrySet().iterator();
while (it.hasNext())
{
LocalPoint trapLocation = trap.getGameObject().getLocalLocation();
if (trapLocation != null && localLocation.distanceTo(trapLocation) <= MAX_DISTANCE)
Map.Entry<WorldPoint, HunterTrap> entry = it.next();
HunterTrap trap = entry.getValue();
switch (trap.getState())
{
switch (trap.getState())
{
case OPEN:
drawTimerOnTrap(graphics, trap, colorOpen, colorOpenBorder, colorEmpty, colorOpenBorder);
break;
case EMPTY:
drawTimerOnTrap(graphics, trap, colorEmpty, colorEmptyBorder, colorEmpty, colorEmptyBorder);
break;
case FULL:
drawCircleOnTrap(graphics, trap, colorFull, colorFullBorder);
break;
case TRANSITION:
drawCircleOnTrap(graphics, trap, colorTrans, colorTransBorder);
break;
}
case OPEN:
drawTimerOnTrap(graphics, trap, colorOpen, colorOpenBorder, colorEmpty, colorOpenBorder);
break;
case EMPTY:
drawTimerOnTrap(graphics, trap, colorEmpty, colorEmptyBorder, colorEmpty, colorEmptyBorder);
break;
case FULL:
drawCircleOnTrap(graphics, trap, colorFull, colorFullBorder);
break;
case TRANSITION:
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)
{
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
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)
{
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
graphics.setColor(fill);