hunter plugin: Don't iterate over all tiles
This commit is contained in:
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user