From 8df7843eefd0514b981e466cf44941034cd41813 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 9 Mar 2018 14:54:27 -0500 Subject: [PATCH] instance map: fix various races between game and event threads --- .../instancemap/InstanceMapInputListener.java | 10 ++- .../instancemap/InstanceMapOverlay.java | 86 +++++++++++-------- 2 files changed, 57 insertions(+), 39 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/instancemap/InstanceMapInputListener.java b/runelite-client/src/main/java/net/runelite/client/plugins/instancemap/InstanceMapInputListener.java index 5fa74240f8..ad3310f99a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/instancemap/InstanceMapInputListener.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/instancemap/InstanceMapInputListener.java @@ -24,6 +24,7 @@ */ package net.runelite.client.plugins.instancemap; +import java.awt.Dimension; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.awt.event.MouseWheelEvent; @@ -114,7 +115,12 @@ public class InstanceMapInputListener extends MouseListener implements KeyListen private boolean isWithinOverlay(int x, int y) { - return (x >= OVERLAY_POSITION.getX() && x <= OVERLAY_POSITION.getX() + plugin.getOverlaySize().width && - y >= OVERLAY_POSITION.getY() && y <= OVERLAY_POSITION.getY() + plugin.getOverlaySize().height); + Dimension dimm = plugin.getOverlaySize(); + if (dimm == null) + { + return false; + } + return (x >= OVERLAY_POSITION.getX() && x <= OVERLAY_POSITION.getX() + dimm.width && + y >= OVERLAY_POSITION.getY() && y <= OVERLAY_POSITION.getY() + dimm.height); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/instancemap/InstanceMapOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/instancemap/InstanceMapOverlay.java index d6ed124f20..3635c9ba5e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/instancemap/InstanceMapOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/instancemap/InstanceMapOverlay.java @@ -24,6 +24,26 @@ */ package net.runelite.client.plugins.instancemap; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.GameObject; +import net.runelite.api.GroundObject; +import net.runelite.api.IndexedSprite; +import net.runelite.api.ObjectComposition; +import net.runelite.api.Player; +import net.runelite.api.Point; +import net.runelite.api.Region; +import net.runelite.api.SceneTileModel; +import net.runelite.api.SceneTilePaint; +import net.runelite.api.SpritePixels; +import net.runelite.api.Tile; +import net.runelite.api.WallObject; +import net.runelite.api.events.GameStateChanged; +import net.runelite.api.events.MapRegionChanged; import static net.runelite.client.plugins.instancemap.PixelMaps.ALL; import static net.runelite.client.plugins.instancemap.PixelMaps.BOTTOM; import static net.runelite.client.plugins.instancemap.PixelMaps.BOTTOM_LEFT_CORNER; @@ -44,27 +64,6 @@ import static net.runelite.client.plugins.instancemap.WallOffset.BOTTOM_RIGHT; import static net.runelite.client.plugins.instancemap.WallOffset.NONE; import static net.runelite.client.plugins.instancemap.WallOffset.TOP_LEFT; import static net.runelite.client.plugins.instancemap.WallOffset.TOP_RIGHT; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.image.BufferedImage; -import javax.annotation.Nullable; -import javax.inject.Inject; -import net.runelite.api.Client; -import net.runelite.api.GameObject; -import net.runelite.api.GroundObject; -import net.runelite.api.IndexedSprite; -import net.runelite.api.ObjectComposition; -import net.runelite.api.Player; -import net.runelite.api.Point; -import net.runelite.api.Region; -import net.runelite.api.SceneTileModel; -import net.runelite.api.SceneTilePaint; -import net.runelite.api.SpritePixels; -import net.runelite.api.Tile; -import net.runelite.api.WallObject; -import net.runelite.api.events.GameStateChanged; -import net.runelite.api.events.MapRegionChanged; import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.OverlayLayer; import net.runelite.client.ui.overlay.OverlayPosition; @@ -106,13 +105,13 @@ class InstanceMapOverlay extends Overlay /** * Saved image of the region, no reason to draw the whole thing every - * frame. This is redrawn in the drawToBufferedImage method + * frame. */ - private BufferedImage mapImage; - private boolean showMap = false; + private volatile BufferedImage mapImage; + private volatile boolean showMap = false; @Inject - InstanceMapOverlay(@Nullable Client client) + InstanceMapOverlay(Client client) { setPosition(OverlayPosition.DYNAMIC); setLayer(OverlayLayer.ALWAYS_ON_TOP); @@ -121,12 +120,14 @@ class InstanceMapOverlay extends Overlay public Dimension getInstanceMapDimension() { - if (mapImage == null) + BufferedImage image = mapImage; + + if (image == null) { return null; } - return new Dimension(mapImage.getWidth(), mapImage.getHeight()); + return new Dimension(image.getWidth(), image.getHeight()); } public boolean isMapShown() @@ -140,20 +141,21 @@ class InstanceMapOverlay extends Overlay * * @param show Whether or not the map should be shown. */ - public void setShowMap(boolean show) + public synchronized void setShowMap(boolean show) { showMap = show; if (showMap) { - viewedPlane = client.getPlane();//When we open the map show the current plane - mapImage = drawMapImage(getTiles()); + //When we open the map show the current plane + viewedPlane = client.getPlane(); } + mapImage = null; } /** * Increases the viewed plane. The maximum viewedPlane is 3 */ - public void onAscend() + public synchronized void onAscend() { if (viewedPlane >= MAX_PLANE) { @@ -161,13 +163,13 @@ class InstanceMapOverlay extends Overlay } viewedPlane++;//Increment plane - mapImage = drawMapImage(getTiles()); + mapImage = null; } /** * Decreases the viewed plane. The minimum viewedPlane is 0 */ - public void onDescend() + public synchronized void onDescend() { if (viewedPlane <= MIN_PLANE) { @@ -175,7 +177,7 @@ class InstanceMapOverlay extends Overlay } viewedPlane--; - mapImage = drawMapImage(getTiles()); + mapImage = null; } @Override @@ -186,12 +188,22 @@ class InstanceMapOverlay extends Overlay return null; } - if (mapImage == null) + // avoid locking on fast path by creating a local ref + BufferedImage image = mapImage; + + if (image == null) { - mapImage = drawMapImage(getTiles()); + image = drawMapImage(getTiles()); + synchronized (this) + { + if (showMap) + { + mapImage = image; + } + } } - graphics.drawImage(mapImage, OVERLAY_POSITION.getX(), OVERLAY_POSITION.getY(), null); + graphics.drawImage(image, OVERLAY_POSITION.getX(), OVERLAY_POSITION.getY(), null); if (client.getPlane() == viewedPlane)//If we are not viewing the plane we are on, don't show player's position {