diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/ColorTileMarker.java b/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/ColorTileMarker.java new file mode 100644 index 0000000000..8f45e9489a --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/ColorTileMarker.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2019, Jordan Atwood + * 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.groundmarkers; + +import java.awt.Color; +import lombok.Value; +import net.runelite.api.coords.WorldPoint; + +/** + * Used to denote marked tiles and their colors. + * Note: This is not used for serialization of ground markers; see {@link GroundMarkerPoint} + */ +@Value +class ColorTileMarker +{ + private WorldPoint worldPoint; + private Color color; + + boolean sameTile(final ColorTileMarker other) + { + return worldPoint.equals(other.getWorldPoint()); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerConfig.java index 394ffcf81b..ba8cb98e14 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerConfig.java @@ -44,4 +44,14 @@ public interface GroundMarkerConfig extends Config { return Color.YELLOW; } + + @ConfigItem( + keyName = "rememberTileColors", + name = "Remember color per tile", + description = "Color tiles using the color from time of placement" + ) + default boolean rememberTileColors() + { + return false; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerOverlay.java index d2b64a81d0..153fe67154 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerOverlay.java @@ -25,10 +25,11 @@ */ package net.runelite.client.plugins.groundmarkers; +import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Polygon; -import java.util.List; +import java.util.Collection; import javax.inject.Inject; import net.runelite.api.Client; import net.runelite.api.Perspective; @@ -62,21 +63,22 @@ public class GroundMarkerOverlay extends Overlay @Override public Dimension render(Graphics2D graphics) { - List points = plugin.getPoints(); - for (WorldPoint point : points) + final Collection points = plugin.getPoints(); + for (final ColorTileMarker point : points) { - if (point.getPlane() != client.getPlane()) + if (point.getWorldPoint().getPlane() != client.getPlane()) { continue; } - drawTile(graphics, point); + final Color tileColor = config.rememberTileColors() ? point.getColor() : config.markerColor(); + drawTile(graphics, point.getWorldPoint(), tileColor); } return null; } - private void drawTile(Graphics2D graphics, WorldPoint point) + private void drawTile(Graphics2D graphics, WorldPoint point, Color color) { WorldPoint playerLocation = client.getLocalPlayer().getWorldLocation(); @@ -97,6 +99,6 @@ public class GroundMarkerOverlay extends Overlay return; } - OverlayUtil.renderPolygon(graphics, poly, config.markerColor()); + OverlayUtil.renderPolygon(graphics, poly, color); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPlugin.java index 37d4f1829f..4aa613af7c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPlugin.java @@ -29,11 +29,12 @@ import com.google.common.base.Strings; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import com.google.inject.Provides; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.stream.Collectors; import javax.inject.Inject; import lombok.AccessLevel; @@ -78,11 +79,14 @@ public class GroundMarkerPlugin extends Plugin private boolean hotKeyPressed; @Getter(AccessLevel.PACKAGE) - private final List points = new ArrayList<>(); + private final Set points = new HashSet<>(); @Inject private Client client; + @Inject + private GroundMarkerConfig config; + @Inject private GroundMarkerInputListener inputListener; @@ -98,6 +102,11 @@ public class GroundMarkerPlugin extends Plugin @Inject private KeyManager keyManager; + private void saveColorTileMarkers(int regionId, Collection points) + { + savePoints(regionId, translateFromColorTileMarker(points)); + } + private void savePoints(int regionId, Collection points) { if (points == null || points.isEmpty()) @@ -117,7 +126,25 @@ public class GroundMarkerPlugin extends Plugin { return Collections.emptyList(); } - return GSON.fromJson(json, new GroundMarkerListTypeToken().getType()); + + Collection configPoints = GSON.fromJson(json, new GroundMarkerListTypeToken().getType()); + + if (configPoints.stream().anyMatch(point -> point.getColor() == null)) + { + log.debug("Adding color to old ground marker(s) of region " + regionId); + configPoints = configPoints.stream() + .map(point -> + { + if (point.getColor() != null) + { + return point; + } + return new GroundMarkerPoint(point.getRegionId(), point.getRegionX(), point.getRegionY(), point.getZ(), config.markerColor()); + }) + .collect(Collectors.toSet()); + savePoints(regionId, configPoints); + } + return configPoints; } private static class GroundMarkerListTypeToken extends TypeToken> @@ -145,37 +172,58 @@ public class GroundMarkerPlugin extends Plugin { // load points for region log.debug("Loading points for region {}", regionId); - Collection regionPoints = getPoints(regionId); - Collection worldPoints = translateToWorld(regionPoints); - points.addAll(worldPoints); + final Collection configPoints = getPoints(regionId); + final Collection colorTileMarkers = translateToColorTileMarker(configPoints); + points.addAll(colorTileMarkers); } } /** - * Translate a collection of ground marker points to world points, accounting for instances + * Translate a collection of ground marker points to color tile markers, accounting for instances * - * @param points - * @return + * @param points {@link GroundMarkerPoint}s to be converted to {@link ColorTileMarker}s + * @return A collection of color tile markers, converted from the passed ground marker points, accounting for local + * instance points. See {@link WorldPoint#toLocalInstance(Client, WorldPoint)} */ - private Collection translateToWorld(Collection points) + private Collection translateToColorTileMarker(Collection points) { - if (points.isEmpty()) + if (points == null || points.isEmpty()) { - return Collections.EMPTY_LIST; + return Collections.emptyList(); + } + + return points.stream() + .map(point -> new ColorTileMarker( + WorldPoint.fromRegion(point.getRegionId(), point.getRegionX(), point.getRegionY(), point.getZ()), + point.getColor())) + .flatMap(colorTile -> + { + final Collection localWorldPoints = WorldPoint.toLocalInstance(client, colorTile.getWorldPoint()); + return localWorldPoints.stream().map(wp -> new ColorTileMarker(wp, colorTile.getColor())); + }) + .collect(Collectors.toSet()); + } + + /** + * Translate a collection of color tile markers to a set of ground marker points + * + * @param points {@link ColorTileMarker}s to be converted to {@link GroundMarkerPoint}s + * @return A set of ground marker points, converted from the passed color tile markers + */ + private static Set translateFromColorTileMarker(Collection points) + { + if (points == null || points.isEmpty()) + { + return Collections.emptySet(); } return points.stream() .map(point -> { - int regionId = point.getRegionId(); - int regionX = point.getRegionX(); - int regionY = point.getRegionY(); - int z = point.getZ(); - - return WorldPoint.fromRegion(regionId, regionX, regionY, z); + final WorldPoint worldPoint = point.getWorldPoint(); + return new GroundMarkerPoint(worldPoint.getRegionID(), worldPoint.getRegionX(), worldPoint.getRegionY(), worldPoint.getPlane(), point.getColor()); }) - .flatMap(wp -> WorldPoint.toLocalInstance(client, wp).stream()) - .collect(Collectors.toList()); + .collect(Collectors.toSet()); } @Subscribe @@ -256,23 +304,28 @@ public class GroundMarkerPlugin extends Plugin return; } - WorldPoint worldPoint = WorldPoint.fromLocalInstance(client, localPoint); - - int regionId = worldPoint.getRegionID(); - GroundMarkerPoint point = new GroundMarkerPoint(regionId, worldPoint.getRegionX(), worldPoint.getRegionY(), client.getPlane()); + final WorldPoint worldPoint = WorldPoint.fromLocalInstance(client, localPoint); + final ColorTileMarker point = new ColorTileMarker(worldPoint, config.markerColor()); log.debug("Updating point: {} - {}", point, worldPoint); - List points = new ArrayList<>(getPoints(regionId)); if (points.contains(point)) { points.remove(point); } else { - points.add(point); + // Remove any points on the same tile but are of a different color + points.removeIf(p -> p.sameTile(point)); + + // Add point back only if we are remembering tile colors, otherwise simply remove it + if (config.rememberTileColors()) + { + points.add(point); + } } - savePoints(regionId, points); + final int regionId = worldPoint.getRegionID(); + saveColorTileMarkers(regionId, points); loadPoints(); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPoint.java b/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPoint.java index 396a2217cb..ca3aaadb6d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPoint.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/groundmarkers/GroundMarkerPoint.java @@ -25,8 +25,12 @@ */ package net.runelite.client.plugins.groundmarkers; +import java.awt.Color; import lombok.Value; +/** + * Used for serialization of ground marker points. + */ @Value class GroundMarkerPoint { @@ -34,4 +38,5 @@ class GroundMarkerPoint private int regionX; private int regionY; private int z; + private Color color; }