Move npc highlight overlay to core

This allows the other plugins which depend on the npc overaly to work
when npc highlight plugin is off, while still letting them use the
consistent highlight style of the central overlay.
This commit is contained in:
Adam
2021-09-03 20:08:33 -04:00
parent 99100979df
commit c52667a5cc
11 changed files with 355 additions and 223 deletions

View File

@@ -22,10 +22,12 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package net.runelite.client.plugins.npchighlight; package net.runelite.client.game.npcoverlay;
import java.awt.Color; import java.awt.Color;
import java.util.function.Predicate;
import lombok.Builder; import lombok.Builder;
import lombok.NonNull;
import lombok.Value; import lombok.Value;
import net.runelite.api.NPC; import net.runelite.api.NPC;
@@ -33,13 +35,20 @@ import net.runelite.api.NPC;
@Builder @Builder
public class HighlightedNpc public class HighlightedNpc
{ {
@NonNull
NPC npc; NPC npc;
@NonNull
Color highlightColor; Color highlightColor;
Color fillColor; @Builder.Default
Color fillColor = new Color(0, 0, 0, 50);
boolean hull; boolean hull;
boolean tile; boolean tile;
boolean swTile; boolean swTile;
boolean outline; boolean outline;
boolean name; boolean name;
boolean nameOnMinimap; boolean nameOnMinimap;
@Builder.Default
float borderWidth = 2.0f;
int outlineFeather;
Predicate<NPC> render;
} }

View File

@@ -23,12 +23,13 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package net.runelite.client.plugins.npchighlight; package net.runelite.client.game.npcoverlay;
import java.awt.Color; import java.awt.Color;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import javax.inject.Inject; import java.util.Map;
import java.util.function.Predicate;
import net.runelite.api.NPC; import net.runelite.api.NPC;
import net.runelite.api.NPCComposition; import net.runelite.api.NPCComposition;
import net.runelite.api.Point; import net.runelite.api.Point;
@@ -38,16 +39,13 @@ import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.OverlayUtil; import net.runelite.client.ui.overlay.OverlayUtil;
import net.runelite.client.util.Text; import net.runelite.client.util.Text;
public class NpcMinimapOverlay extends Overlay class NpcMinimapOverlay extends Overlay
{ {
private final NpcIndicatorsConfig config; private final Map<NPC, HighlightedNpc> highlightedNpcs;
private final NpcIndicatorsPlugin plugin;
@Inject NpcMinimapOverlay(Map<NPC, HighlightedNpc> highlightedNpcs)
NpcMinimapOverlay(NpcIndicatorsConfig config, NpcIndicatorsPlugin plugin)
{ {
this.config = config; this.highlightedNpcs = highlightedNpcs;
this.plugin = plugin;
setPosition(OverlayPosition.DYNAMIC); setPosition(OverlayPosition.DYNAMIC);
setLayer(OverlayLayer.ABOVE_WIDGETS); setLayer(OverlayLayer.ABOVE_WIDGETS);
} }
@@ -55,7 +53,7 @@ public class NpcMinimapOverlay extends Overlay
@Override @Override
public Dimension render(Graphics2D graphics) public Dimension render(Graphics2D graphics)
{ {
for (HighlightedNpc highlightedNpc : plugin.getHighlightedNpcs().values()) for (HighlightedNpc highlightedNpc : highlightedNpcs.values())
{ {
renderNpcOverlay(graphics, highlightedNpc); renderNpcOverlay(graphics, highlightedNpc);
} }
@@ -67,8 +65,13 @@ public class NpcMinimapOverlay extends Overlay
{ {
NPC actor = highlightedNpc.getNpc(); NPC actor = highlightedNpc.getNpc();
NPCComposition npcComposition = actor.getTransformedComposition(); NPCComposition npcComposition = actor.getTransformedComposition();
if (npcComposition == null || !npcComposition.isInteractible() if (npcComposition == null || !npcComposition.isInteractible())
|| (actor.isDead() && config.ignoreDeadNpcs())) {
return;
}
Predicate<NPC> render = highlightedNpc.getRender();
if (render != null && !render.test(actor))
{ {
return; return;
} }

View File

@@ -0,0 +1,147 @@
/*
* Copyright (c) 2018, James Swindle <wilingua@gmail.com>
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* 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.client.game.npcoverlay;
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 java.util.Map;
import java.util.function.Predicate;
import net.runelite.api.Client;
import net.runelite.api.NPC;
import net.runelite.api.NPCComposition;
import net.runelite.api.Perspective;
import net.runelite.api.Point;
import net.runelite.api.coords.LocalPoint;
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.client.ui.overlay.outline.ModelOutlineRenderer;
import net.runelite.client.util.Text;
class NpcOverlay extends Overlay
{
private final Client client;
private final ModelOutlineRenderer modelOutlineRenderer;
private final Map<NPC, HighlightedNpc> highlightedNpcs;
NpcOverlay(Client client, ModelOutlineRenderer modelOutlineRenderer, Map<NPC, HighlightedNpc> highlightedNpcs)
{
this.client = client;
this.modelOutlineRenderer = modelOutlineRenderer;
this.highlightedNpcs = highlightedNpcs;
setPosition(OverlayPosition.DYNAMIC);
setLayer(OverlayLayer.ABOVE_SCENE);
}
@Override
public Dimension render(Graphics2D graphics)
{
for (HighlightedNpc highlightedNpc : highlightedNpcs.values())
{
renderNpcOverlay(graphics, highlightedNpc);
}
return null;
}
private void renderNpcOverlay(Graphics2D graphics, HighlightedNpc highlightedNpc)
{
NPC actor = highlightedNpc.getNpc();
NPCComposition npcComposition = actor.getTransformedComposition();
if (npcComposition == null || !npcComposition.isInteractible())
{
return;
}
Predicate<NPC> render = highlightedNpc.getRender();
if (render != null && !render.test(actor))
{
return;
}
final Color borderColor = highlightedNpc.getHighlightColor();
float borderWidth = highlightedNpc.getBorderWidth();
final Color fillColor = highlightedNpc.getFillColor();
if (highlightedNpc.isHull())
{
Shape objectClickbox = actor.getConvexHull();
renderPoly(graphics, borderColor, borderWidth, fillColor, objectClickbox);
}
if (highlightedNpc.isTile())
{
Polygon tilePoly = actor.getCanvasTilePoly();
renderPoly(graphics, borderColor, borderWidth, fillColor, tilePoly);
}
if (highlightedNpc.isSwTile())
{
int size = npcComposition.getSize();
LocalPoint lp = actor.getLocalLocation();
int x = lp.getX() - ((size - 1) * Perspective.LOCAL_TILE_SIZE / 2);
int y = lp.getY() - ((size - 1) * Perspective.LOCAL_TILE_SIZE / 2);
Polygon southWestTilePoly = Perspective.getCanvasTilePoly(client, new LocalPoint(x, y));
renderPoly(graphics, borderColor, borderWidth, fillColor, southWestTilePoly);
}
if (highlightedNpc.isOutline())
{
modelOutlineRenderer.drawOutline(actor, (int) highlightedNpc.getBorderWidth(), borderColor, highlightedNpc.getOutlineFeather());
}
if (highlightedNpc.isName() && actor.getName() != null)
{
String npcName = Text.removeTags(actor.getName());
Point textLocation = actor.getCanvasTextLocation(graphics, npcName, actor.getLogicalHeight() + 40);
if (textLocation != null)
{
OverlayUtil.renderTextLocation(graphics, textLocation, npcName, borderColor);
}
}
}
private void renderPoly(Graphics2D graphics, Color borderColor, float borderWidth, Color fillColor, Shape polygon)
{
if (polygon != null)
{
graphics.setColor(borderColor);
graphics.setStroke(new BasicStroke(borderWidth));
graphics.draw(polygon);
graphics.setColor(fillColor);
graphics.fill(polygon);
}
}
}

View File

@@ -0,0 +1,142 @@
/*
* Copyright (c) 2018, James Swindle <wilingua@gmail.com>
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* 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.client.game.npcoverlay;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import javax.inject.Inject;
import javax.inject.Singleton;
import net.runelite.api.Client;
import net.runelite.api.NPC;
import net.runelite.api.events.NpcChanged;
import net.runelite.api.events.NpcDespawned;
import net.runelite.api.events.NpcSpawned;
import net.runelite.client.callback.ClientThread;
import net.runelite.client.eventbus.EventBus;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.ui.overlay.OverlayManager;
import net.runelite.client.ui.overlay.outline.ModelOutlineRenderer;
@Singleton
public class NpcOverlayService
{
private final Client client;
private final ClientThread clientThread;
private final List<Function<NPC, HighlightedNpc>> highlightFunctions = new ArrayList<>();
private final Map<NPC, HighlightedNpc> highlightedNpcs = new HashMap<>();
@Inject
private NpcOverlayService(Client client, ClientThread clientThread,
OverlayManager overlayManager, ModelOutlineRenderer modelOutlineRenderer, EventBus eventBus)
{
this.client = client;
this.clientThread = clientThread;
overlayManager.add(new NpcOverlay(client, modelOutlineRenderer, highlightedNpcs));
overlayManager.add(new NpcMinimapOverlay(highlightedNpcs));
eventBus.register(this);
}
@Subscribe(
// Run after plugins, which typically capture NPCs on spawn and reference them in the highlight functions
priority = -1
)
private void onNpcSpawned(NpcSpawned npcSpawned)
{
final NPC npc = npcSpawned.getNpc();
for (Function<NPC, HighlightedNpc> f : highlightFunctions)
{
HighlightedNpc highlightedNpc = f.apply(npc);
if (highlightedNpc != null)
{
highlightedNpcs.put(npc, highlightedNpc);
return;
}
}
}
@Subscribe
private void onNpcDespawned(NpcDespawned npcDespawned)
{
final NPC npc = npcDespawned.getNpc();
highlightedNpcs.remove(npc);
}
@Subscribe
private void onNpcChanged(NpcChanged event)
{
final NPC npc = event.getNpc();
highlightedNpcs.remove(npc);
for (Function<NPC, HighlightedNpc> f : highlightFunctions)
{
HighlightedNpc highlightedNpc = f.apply(npc);
if (highlightedNpc != null)
{
highlightedNpcs.put(npc, highlightedNpc);
return;
}
}
}
public void rebuild()
{
clientThread.invoke(() ->
{
highlightedNpcs.clear();
outer:
for (NPC npc : client.getNpcs())
{
for (Function<NPC, HighlightedNpc> f : highlightFunctions)
{
HighlightedNpc highlightedNpc = f.apply(npc);
if (highlightedNpc != null)
{
highlightedNpcs.put(npc, highlightedNpc);
continue outer;
}
}
}
});
}
public void registerHighlighter(Function<NPC, HighlightedNpc> p)
{
highlightFunctions.add(p);
rebuild();
}
public void unregisterHighlighter(Function<NPC, HighlightedNpc> p)
{
highlightFunctions.remove(p);
rebuild();
}
}

View File

@@ -32,16 +32,13 @@ import net.runelite.api.NPC;
import net.runelite.api.events.NpcChanged; import net.runelite.api.events.NpcChanged;
import net.runelite.api.events.NpcSpawned; import net.runelite.api.events.NpcSpawned;
import net.runelite.client.Notifier; import net.runelite.client.Notifier;
import net.runelite.client.callback.ClientThread;
import net.runelite.client.config.ConfigManager; import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe; import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.events.ConfigChanged; import net.runelite.client.events.ConfigChanged;
import net.runelite.client.game.npcoverlay.HighlightedNpc;
import net.runelite.client.game.npcoverlay.NpcOverlayService;
import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDependency;
import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.plugins.npchighlight.HighlightedNpc;
import net.runelite.client.plugins.npchighlight.NpcIndicatorsPlugin;
import net.runelite.client.plugins.npchighlight.NpcIndicatorsService;
import net.runelite.client.ui.overlay.OverlayManager; import net.runelite.client.ui.overlay.OverlayManager;
@PluginDescriptor( @PluginDescriptor(
@@ -49,7 +46,6 @@ import net.runelite.client.ui.overlay.OverlayManager;
description = "Highlight nearby implings on the minimap and on-screen", description = "Highlight nearby implings on the minimap and on-screen",
tags = {"hunter", "minimap", "overlay", "imp"} tags = {"hunter", "minimap", "overlay", "imp"}
) )
@PluginDependency(NpcIndicatorsPlugin.class)
public class ImplingsPlugin extends Plugin public class ImplingsPlugin extends Plugin
{ {
@Inject @Inject
@@ -65,10 +61,7 @@ public class ImplingsPlugin extends Plugin
private Notifier notifier; private Notifier notifier;
@Inject @Inject
private NpcIndicatorsService npcIndicatorsService; private NpcOverlayService npcOverlayService;
@Inject
private ClientThread clientThread;
public final Function<NPC, HighlightedNpc> isTarget = (npc) -> public final Function<NPC, HighlightedNpc> isTarget = (npc) ->
{ {
@@ -79,7 +72,6 @@ public class ImplingsPlugin extends Plugin
return HighlightedNpc.builder() return HighlightedNpc.builder()
.npc(npc) .npc(npc)
.highlightColor(color) .highlightColor(color)
.fillColor(new Color(0, 0, 0, 50))
.tile(true) .tile(true)
.name(true) .name(true)
.nameOnMinimap(config.showName()) .nameOnMinimap(config.showName())
@@ -98,13 +90,13 @@ public class ImplingsPlugin extends Plugin
protected void startUp() protected void startUp()
{ {
overlayManager.add(overlay); overlayManager.add(overlay);
npcIndicatorsService.registerHighlighter(isTarget); npcOverlayService.registerHighlighter(isTarget);
} }
@Override @Override
protected void shutDown() protected void shutDown()
{ {
npcIndicatorsService.unregisterHighlighter(isTarget); npcOverlayService.unregisterHighlighter(isTarget);
overlayManager.remove(overlay); overlayManager.remove(overlay);
} }
@@ -116,7 +108,7 @@ public class ImplingsPlugin extends Plugin
return; return;
} }
clientThread.invoke(npcIndicatorsService::rebuild); npcOverlayService.rebuild();
} }
@Subscribe @Subscribe

View File

@@ -27,7 +27,6 @@ package net.runelite.client.plugins.npchighlight;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.inject.Binder;
import com.google.inject.Provides; import com.google.inject.Provides;
import java.awt.Color; import java.awt.Color;
import java.time.Instant; import java.time.Instant;
@@ -66,6 +65,8 @@ import net.runelite.client.callback.ClientThread;
import net.runelite.client.config.ConfigManager; import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe; import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.events.ConfigChanged; import net.runelite.client.events.ConfigChanged;
import net.runelite.client.game.npcoverlay.HighlightedNpc;
import net.runelite.client.game.npcoverlay.NpcOverlayService;
import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.OverlayManager; import net.runelite.client.ui.overlay.OverlayManager;
@@ -79,7 +80,7 @@ import net.runelite.client.util.WildcardMatcher;
tags = {"highlight", "minimap", "npcs", "overlay", "respawn", "tags"} tags = {"highlight", "minimap", "npcs", "overlay", "respawn", "tags"}
) )
@Slf4j @Slf4j
public class NpcIndicatorsPlugin extends Plugin implements NpcIndicatorsService public class NpcIndicatorsPlugin extends Plugin
{ {
private static final int MAX_ACTOR_VIEW_RANGE = 15; private static final int MAX_ACTOR_VIEW_RANGE = 15;
@@ -104,14 +105,14 @@ public class NpcIndicatorsPlugin extends Plugin implements NpcIndicatorsService
private OverlayManager overlayManager; private OverlayManager overlayManager;
@Inject @Inject
private NpcSceneOverlay npcSceneOverlay; private NpcRespawnOverlay npcRespawnOverlay;
@Inject
private NpcMinimapOverlay npcMinimapOverlay;
@Inject @Inject
private ClientThread clientThread; private ClientThread clientThread;
@Inject
private NpcOverlayService npcOverlayService;
/** /**
* NPCs to highlight * NPCs to highlight
*/ */
@@ -175,7 +176,7 @@ public class NpcIndicatorsPlugin extends Plugin implements NpcIndicatorsService
*/ */
private boolean skipNextSpawnCheck = false; private boolean skipNextSpawnCheck = false;
private final List<Function<NPC, HighlightedNpc>> higlightPredicates = new ArrayList<>(); private final Function<NPC, HighlightedNpc> isHighlighted = highlightedNpcs::get;
@Provides @Provides
NpcIndicatorsConfig provideConfig(ConfigManager configManager) NpcIndicatorsConfig provideConfig(ConfigManager configManager)
@@ -183,17 +184,11 @@ public class NpcIndicatorsPlugin extends Plugin implements NpcIndicatorsService
return configManager.getConfig(NpcIndicatorsConfig.class); return configManager.getConfig(NpcIndicatorsConfig.class);
} }
@Override
public void configure(Binder binder)
{
binder.bind(NpcIndicatorsService.class).toInstance(this);
}
@Override @Override
protected void startUp() throws Exception protected void startUp() throws Exception
{ {
overlayManager.add(npcSceneOverlay); npcOverlayService.registerHighlighter(isHighlighted);
overlayManager.add(npcMinimapOverlay); overlayManager.add(npcRespawnOverlay);
clientThread.invoke(() -> clientThread.invoke(() ->
{ {
skipNextSpawnCheck = true; skipNextSpawnCheck = true;
@@ -204,8 +199,8 @@ public class NpcIndicatorsPlugin extends Plugin implements NpcIndicatorsService
@Override @Override
protected void shutDown() throws Exception protected void shutDown() throws Exception
{ {
overlayManager.remove(npcSceneOverlay); npcOverlayService.unregisterHighlighter(isHighlighted);
overlayManager.remove(npcMinimapOverlay); overlayManager.remove(npcRespawnOverlay);
clientThread.invoke(() -> clientThread.invoke(() ->
{ {
deadNpcsToDisplay.clear(); deadNpcsToDisplay.clear();
@@ -367,10 +362,13 @@ public class NpcIndicatorsPlugin extends Plugin implements NpcIndicatorsService
} }
highlightedNpcs.put(npc, highlightedNpc(npc)); highlightedNpcs.put(npc, highlightedNpc(npc));
} }
npcOverlayService.rebuild();
} }
else else
{ {
final String name = npc.getName(); final String name = npc.getName();
// this trips a config change which triggers the overlay rebuild
updateNpcsToHighlight(name); updateNpcsToHighlight(name);
} }
@@ -404,24 +402,7 @@ public class NpcIndicatorsPlugin extends Plugin implements NpcIndicatorsService
memorizeNpc(npc); memorizeNpc(npc);
spawnedNpcsThisTick.add(npc); spawnedNpcsThisTick.add(npc);
} }
return;
} }
for (Function<NPC, HighlightedNpc> predicate : higlightPredicates)
{
HighlightedNpc highlightedNpc = predicate.apply(npc);
if (highlightedNpc != null)
{
highlightedNpcs.put(npc, highlightedNpc);
if (!client.isInInstancedRegion())
{
memorizeNpc(npc);
spawnedNpcsThisTick.add(npc);
}
return;
}
}
} }
@Subscribe @Subscribe
@@ -454,17 +435,6 @@ public class NpcIndicatorsPlugin extends Plugin implements NpcIndicatorsService
|| highlightMatchesNPCName(npcName)) || highlightMatchesNPCName(npcName))
{ {
highlightedNpcs.put(npc, highlightedNpc(npc)); highlightedNpcs.put(npc, highlightedNpc(npc));
return;
}
for (Function<NPC, HighlightedNpc> predicate : higlightPredicates)
{
HighlightedNpc highlightedNpc = predicate.apply(npc);
if (highlightedNpc != null)
{
highlightedNpcs.put(npc, highlightedNpc);
return;
}
} }
} }
@@ -572,8 +542,7 @@ public class NpcIndicatorsPlugin extends Plugin implements NpcIndicatorsService
return Text.fromCSV(configNpcs); return Text.fromCSV(configNpcs);
} }
@Override void rebuild()
public void rebuild()
{ {
highlights = getHighlights(); highlights = getHighlights();
highlightedNpcs.clear(); highlightedNpcs.clear();
@@ -586,7 +555,6 @@ public class NpcIndicatorsPlugin extends Plugin implements NpcIndicatorsService
return; return;
} }
outer:
for (NPC npc : client.getNpcs()) for (NPC npc : client.getNpcs())
{ {
final String npcName = npc.getName(); final String npcName = npc.getName();
@@ -612,23 +580,11 @@ public class NpcIndicatorsPlugin extends Plugin implements NpcIndicatorsService
continue; continue;
} }
for (Function<NPC, HighlightedNpc> predicate : higlightPredicates)
{
HighlightedNpc highlightedNpc = predicate.apply(npc);
if (highlightedNpc != null)
{
if (!client.isInInstancedRegion())
{
memorizeNpc(npc);
}
highlightedNpcs.put(npc, highlightedNpc);
continue outer;
}
}
// NPC is not highlighted // NPC is not highlighted
memorizedNpcs.remove(npc.getIndex()); memorizedNpcs.remove(npc.getIndex());
} }
npcOverlayService.rebuild();
} }
private boolean highlightMatchesNPCName(String npcName) private boolean highlightMatchesNPCName(String npcName)
@@ -746,18 +702,9 @@ public class NpcIndicatorsPlugin extends Plugin implements NpcIndicatorsService
.outline(config.highlightOutline()) .outline(config.highlightOutline())
.name(config.drawNames()) .name(config.drawNames())
.nameOnMinimap(config.drawMinimapNames()) .nameOnMinimap(config.drawMinimapNames())
.borderWidth((float) config.borderWidth())
.outlineFeather(config.outlineFeather())
.render(n -> !n.isDead() || !config.ignoreDeadNpcs())
.build(); .build();
} }
@Override
public void registerHighlighter(Function<NPC, HighlightedNpc> p)
{
higlightPredicates.add(p);
}
@Override
public void unregisterHighlighter(Function<NPC, HighlightedNpc> p)
{
higlightPredicates.remove(p);
}
} }

View File

@@ -1,35 +0,0 @@
/*
* Copyright (c) 2021, Adam <Adam@sigterm.info>
* 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.client.plugins.npchighlight;
import java.util.function.Function;
import net.runelite.api.NPC;
public interface NpcIndicatorsService
{
void registerHighlighter(Function<NPC, HighlightedNpc> p);
void unregisterHighlighter(Function<NPC, HighlightedNpc> p);
void rebuild();
}

View File

@@ -38,8 +38,6 @@ import java.util.Locale;
import javax.inject.Inject; import javax.inject.Inject;
import net.runelite.api.Client; import net.runelite.api.Client;
import net.runelite.api.Constants; import net.runelite.api.Constants;
import net.runelite.api.NPC;
import net.runelite.api.NPCComposition;
import net.runelite.api.Perspective; import net.runelite.api.Perspective;
import net.runelite.api.Point; import net.runelite.api.Point;
import net.runelite.api.coords.LocalPoint; import net.runelite.api.coords.LocalPoint;
@@ -48,10 +46,8 @@ 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;
import net.runelite.client.ui.overlay.OverlayUtil; import net.runelite.client.ui.overlay.OverlayUtil;
import net.runelite.client.ui.overlay.outline.ModelOutlineRenderer;
import net.runelite.client.util.Text;
public class NpcSceneOverlay extends Overlay class NpcRespawnOverlay extends Overlay
{ {
// Anything but white text is quite hard to see since it is drawn on // Anything but white text is quite hard to see since it is drawn on
// a dark background // a dark background
@@ -67,16 +63,13 @@ public class NpcSceneOverlay extends Overlay
private final Client client; private final Client client;
private final NpcIndicatorsConfig config; private final NpcIndicatorsConfig config;
private final NpcIndicatorsPlugin plugin; private final NpcIndicatorsPlugin plugin;
private final ModelOutlineRenderer modelOutlineRenderer;
@Inject @Inject
NpcSceneOverlay(Client client, NpcIndicatorsConfig config, NpcIndicatorsPlugin plugin, NpcRespawnOverlay(Client client, NpcIndicatorsConfig config, NpcIndicatorsPlugin plugin)
ModelOutlineRenderer modelOutlineRenderer)
{ {
this.client = client; this.client = client;
this.config = config; this.config = config;
this.plugin = plugin; this.plugin = plugin;
this.modelOutlineRenderer = modelOutlineRenderer;
setPosition(OverlayPosition.DYNAMIC); setPosition(OverlayPosition.DYNAMIC);
setLayer(OverlayLayer.ABOVE_SCENE); setLayer(OverlayLayer.ABOVE_SCENE);
} }
@@ -89,11 +82,6 @@ public class NpcSceneOverlay extends Overlay
plugin.getDeadNpcsToDisplay().forEach((id, npc) -> renderNpcRespawn(npc, graphics)); plugin.getDeadNpcsToDisplay().forEach((id, npc) -> renderNpcRespawn(npc, graphics));
} }
for (HighlightedNpc highlightedNpc : plugin.getHighlightedNpcs().values())
{
renderNpcOverlay(graphics, highlightedNpc);
}
return null; return null;
} }
@@ -141,61 +129,6 @@ public class NpcSceneOverlay extends Overlay
} }
} }
private void renderNpcOverlay(Graphics2D graphics, HighlightedNpc highlightedNpc)
{
NPC actor = highlightedNpc.getNpc();
NPCComposition npcComposition = actor.getTransformedComposition();
if (npcComposition == null || !npcComposition.isInteractible()
|| (actor.isDead() && config.ignoreDeadNpcs()))
{
return;
}
final Color borderColor = highlightedNpc.getHighlightColor();
final Color fillColor = highlightedNpc.getFillColor();
if (highlightedNpc.isHull())
{
Shape objectClickbox = actor.getConvexHull();
renderPoly(graphics, borderColor, fillColor, objectClickbox);
}
if (highlightedNpc.isTile())
{
Polygon tilePoly = actor.getCanvasTilePoly();
renderPoly(graphics, borderColor, fillColor, tilePoly);
}
if (highlightedNpc.isSwTile())
{
int size = npcComposition.getSize();
LocalPoint lp = actor.getLocalLocation();
int x = lp.getX() - ((size - 1) * Perspective.LOCAL_TILE_SIZE / 2);
int y = lp.getY() - ((size - 1) * Perspective.LOCAL_TILE_SIZE / 2);
Polygon southWestTilePoly = Perspective.getCanvasTilePoly(client, new LocalPoint(x, y));
renderPoly(graphics, borderColor, fillColor, southWestTilePoly);
}
if (highlightedNpc.isOutline())
{
modelOutlineRenderer.drawOutline(actor, (int)config.borderWidth(), borderColor, config.outlineFeather());
}
if (highlightedNpc.isName() && actor.getName() != null)
{
String npcName = Text.removeTags(actor.getName());
Point textLocation = actor.getCanvasTextLocation(graphics, npcName, actor.getLogicalHeight() + 40);
if (textLocation != null)
{
OverlayUtil.renderTextLocation(graphics, textLocation, npcName, borderColor);
}
}
}
private void renderPoly(Graphics2D graphics, Color borderColor, Color fillColor, Shape polygon) private void renderPoly(Graphics2D graphics, Color borderColor, Color fillColor, Shape polygon)
{ {
if (polygon != null) if (polygon != null)

View File

@@ -83,12 +83,10 @@ import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.events.ChatInput; import net.runelite.client.events.ChatInput;
import net.runelite.client.events.ConfigChanged; import net.runelite.client.events.ConfigChanged;
import net.runelite.client.game.ItemManager; import net.runelite.client.game.ItemManager;
import net.runelite.client.game.npcoverlay.HighlightedNpc;
import net.runelite.client.game.npcoverlay.NpcOverlayService;
import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDependency;
import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.plugins.npchighlight.HighlightedNpc;
import net.runelite.client.plugins.npchighlight.NpcIndicatorsPlugin;
import net.runelite.client.plugins.npchighlight.NpcIndicatorsService;
import net.runelite.client.ui.overlay.OverlayManager; import net.runelite.client.ui.overlay.OverlayManager;
import net.runelite.client.ui.overlay.infobox.InfoBoxManager; import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
import net.runelite.client.util.ColorUtil; import net.runelite.client.util.ColorUtil;
@@ -101,7 +99,6 @@ import org.apache.commons.lang3.ArrayUtils;
description = "Show additional slayer task related information", description = "Show additional slayer task related information",
tags = {"combat", "notifications", "overlay", "tasks"} tags = {"combat", "notifications", "overlay", "tasks"}
) )
@PluginDependency(NpcIndicatorsPlugin.class)
@Slf4j @Slf4j
public class SlayerPlugin extends Plugin public class SlayerPlugin extends Plugin
{ {
@@ -176,7 +173,7 @@ public class SlayerPlugin extends Plugin
private ChatClient chatClient; private ChatClient chatClient;
@Inject @Inject
private NpcIndicatorsService npcIndicatorsService; private NpcOverlayService npcOverlayService;
@Getter(AccessLevel.PACKAGE) @Getter(AccessLevel.PACKAGE)
private final List<NPC> targets = new ArrayList<>(); private final List<NPC> targets = new ArrayList<>();
@@ -233,7 +230,7 @@ public class SlayerPlugin extends Plugin
protected void startUp() throws Exception protected void startUp() throws Exception
{ {
chatCommandManager.registerCommandAsync(TASK_COMMAND_STRING, this::taskLookup, this::taskSubmit); chatCommandManager.registerCommandAsync(TASK_COMMAND_STRING, this::taskLookup, this::taskSubmit);
npcIndicatorsService.registerHighlighter(isTarget); npcOverlayService.registerHighlighter(isTarget);
overlayManager.add(overlay); overlayManager.add(overlay);
overlayManager.add(targetWeaknessOverlay); overlayManager.add(targetWeaknessOverlay);
@@ -259,8 +256,7 @@ public class SlayerPlugin extends Plugin
protected void shutDown() throws Exception protected void shutDown() throws Exception
{ {
chatCommandManager.unregisterCommand(TASK_COMMAND_STRING); chatCommandManager.unregisterCommand(TASK_COMMAND_STRING);
npcIndicatorsService.unregisterHighlighter(isTarget); npcOverlayService.unregisterHighlighter(isTarget);
npcIndicatorsService.rebuild();
overlayManager.remove(overlay); overlayManager.remove(overlay);
overlayManager.remove(targetWeaknessOverlay); overlayManager.remove(targetWeaknessOverlay);
@@ -350,10 +346,7 @@ public class SlayerPlugin extends Plugin
setProfileConfig(SlayerConfig.TASK_LOC_KEY, taskLocation); setProfileConfig(SlayerConfig.TASK_LOC_KEY, taskLocation);
} }
@Subscribe( @Subscribe
// Run prior to npc indicators plugin so targets is populated before the isTarget predicate is checked
priority = 1
)
public void onNpcSpawned(NpcSpawned npcSpawned) public void onNpcSpawned(NpcSpawned npcSpawned)
{ {
NPC npc = npcSpawned.getNpc(); NPC npc = npcSpawned.getNpc();
@@ -620,7 +613,7 @@ public class SlayerPlugin extends Plugin
} }
else else
{ {
clientThread.invoke(npcIndicatorsService::rebuild); npcOverlayService.rebuild();
} }
} }
@@ -746,7 +739,7 @@ public class SlayerPlugin extends Plugin
Task task = Task.getTask(name); Task task = Task.getTask(name);
rebuildTargetNames(task); rebuildTargetNames(task);
rebuildTargetList(); rebuildTargetList();
npcIndicatorsService.rebuild(); npcOverlayService.rebuild();
} }
private void addCounter() private void addCounter()

View File

@@ -78,6 +78,7 @@ public class NpcIndicatorsPluginTest
public void setUp() public void setUp()
{ {
Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this); Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this);
when(npcIndicatorsConfig.highlightColor()).thenReturn(Color.RED);
} }
@Test @Test

View File

@@ -56,7 +56,7 @@ import net.runelite.client.chat.ChatCommandManager;
import net.runelite.client.chat.ChatMessageManager; import net.runelite.client.chat.ChatMessageManager;
import net.runelite.client.config.ConfigManager; import net.runelite.client.config.ConfigManager;
import net.runelite.client.game.ItemManager; import net.runelite.client.game.ItemManager;
import net.runelite.client.plugins.npchighlight.NpcIndicatorsService; import net.runelite.client.game.npcoverlay.NpcOverlayService;
import net.runelite.client.ui.overlay.OverlayManager; import net.runelite.client.ui.overlay.OverlayManager;
import net.runelite.client.ui.overlay.infobox.InfoBoxManager; import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
import net.runelite.http.api.chat.ChatClient; import net.runelite.http.api.chat.ChatClient;
@@ -176,7 +176,7 @@ public class SlayerPluginTest
@Mock @Mock
@Bind @Bind
NpcIndicatorsService npcIndicatorsService; NpcOverlayService npcOverlayService;
@Inject @Inject
SlayerPlugin slayerPlugin; SlayerPlugin slayerPlugin;