From 549150a74930146296fd793aaa17270a2163653b Mon Sep 17 00:00:00 2001 From: Michael Goodwin <29030969+TheStonedTurtle@users.noreply.github.com> Date: Sun, 2 Sep 2018 12:43:27 -0700 Subject: [PATCH 1/4] Make same-tick same-tile loot event fire once Make kills done in same tick on same tile count only once to prevent duplicated entries in loot tracker. Closes #4839 --- .../main/java/net/runelite/client/game/LootManager.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/game/LootManager.java b/runelite-client/src/main/java/net/runelite/client/game/LootManager.java index 41aae4e43b..0c2dd55628 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/LootManager.java +++ b/runelite-client/src/main/java/net/runelite/client/game/LootManager.java @@ -31,6 +31,7 @@ import com.google.common.eventbus.EventBus; import com.google.common.eventbus.Subscribe; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.List; import java.util.Map; import javax.inject.Inject; @@ -66,6 +67,7 @@ public class LootManager private final EventBus eventBus; private final Client client; private final ListMultimap itemSpawns = ArrayListMultimap.create(); + private final Map killMap = new HashMap<>(); private WorldPoint playerLocationLastTick; private WorldPoint krakenPlayerLocation; @@ -124,7 +126,7 @@ public class LootManager { final Player player = playerDespawned.getPlayer(); final LocalPoint location = LocalPoint.fromWorld(client, player.getWorldLocation()); - if (location == null) + if (location == null || killMap.get(location)) { return; } @@ -139,6 +141,7 @@ public class LootManager return; } + killMap.put(location, true); eventBus.post(new PlayerLootReceived(player, items)); } @@ -205,12 +208,13 @@ public class LootManager { playerLocationLastTick = client.getLocalPlayer().getWorldLocation(); itemSpawns.clear(); + killMap.clear(); } private void processNpcLoot(NPC npc) { final LocalPoint location = LocalPoint.fromWorld(client, getDropLocation(npc, npc.getWorldLocation())); - if (location == null) + if (location == null || killMap.get(location)) { return; } @@ -236,6 +240,7 @@ public class LootManager return; } + killMap.put(location, true); eventBus.post(new NpcLootReceived(npc, allItems)); } From 0b2c7af6aa58acdc47ad8d2b1f4b5ada14289df1 Mon Sep 17 00:00:00 2001 From: Michael Goodwin <29030969+TheStonedTurtle@users.noreply.github.com> Date: Sun, 2 Sep 2018 12:43:57 -0700 Subject: [PATCH 2/4] Check for player HP being 0 in player loot event Check if player HP is 0 (e.g player being really dead) when sending PlayerLootReceived event. Fixes #4653 --- .../src/main/java/net/runelite/client/game/LootManager.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/runelite-client/src/main/java/net/runelite/client/game/LootManager.java b/runelite-client/src/main/java/net/runelite/client/game/LootManager.java index 0c2dd55628..a9754eaa74 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/LootManager.java +++ b/runelite-client/src/main/java/net/runelite/client/game/LootManager.java @@ -125,6 +125,12 @@ public class LootManager public void onPlayerDespawned(PlayerDespawned playerDespawned) { final Player player = playerDespawned.getPlayer(); + // Only care about dead Players + if (player.getHealthRatio() != 0) + { + return; + } + final LocalPoint location = LocalPoint.fromWorld(client, player.getWorldLocation()); if (location == null || killMap.get(location)) { From 98ec2cd5c804cf0176b5449a32b9b272e44805c5 Mon Sep 17 00:00:00 2001 From: Michael Goodwin <29030969+TheStonedTurtle@users.noreply.github.com> Date: Sun, 2 Sep 2018 22:01:36 +0200 Subject: [PATCH 3/4] Add common method for converting local to world point - Add commom method for converting local to world point accounting for instances - Make both discord and ground marker plugin use this method Signed-off-by: Tomas Slusny --- .../net/runelite/api/coords/WorldPoint.java | 67 +++++++++++++++++++ .../client/plugins/discord/DiscordPlugin.java | 26 +------ .../groundmarkers/GroundMarkerPlugin.java | 34 +--------- 3 files changed, 69 insertions(+), 58 deletions(-) diff --git a/runelite-api/src/main/java/net/runelite/api/coords/WorldPoint.java b/runelite-api/src/main/java/net/runelite/api/coords/WorldPoint.java index 45b96ee22b..9defe5fd89 100644 --- a/runelite-api/src/main/java/net/runelite/api/coords/WorldPoint.java +++ b/runelite-api/src/main/java/net/runelite/api/coords/WorldPoint.java @@ -27,6 +27,7 @@ package net.runelite.api.coords; import lombok.Value; import net.runelite.api.Client; +import static net.runelite.api.Constants.CHUNK_SIZE; import net.runelite.api.Perspective; import net.runelite.api.Point; @@ -149,6 +150,72 @@ public class WorldPoint ); } + /** + * Gets the coordinate of the tile that contains the passed local point. + * + * @param client the client + * @param localPoint the local coordinate + * @return the tile coordinate containing the local point + */ + public static WorldPoint fromLocalInstance(Client client, LocalPoint localPoint) + { + if (client.isInInstancedRegion()) + { + // get position in the scene + int sceneX = localPoint.getSceneX(); + int sceneY = localPoint.getSceneY(); + + // get chunk from scene + int chunkX = sceneX / CHUNK_SIZE; + int chunkY = sceneY / CHUNK_SIZE; + + // get the template chunk for the chunk + int[][][] instanceTemplateChunks = client.getInstanceTemplateChunks(); + int templateChunk = instanceTemplateChunks[client.getPlane()][chunkX][chunkY]; + + int rotation = templateChunk >> 1 & 0x3; + int templateChunkY = (templateChunk >> 3 & 0x7FF) * CHUNK_SIZE; + int templateChunkX = (templateChunk >> 14 & 0x3FF) * CHUNK_SIZE; + int plane = templateChunk >> 24 & 0x3; + + // calculate world point of the template + int x = templateChunkX + (sceneX & (CHUNK_SIZE - 1)); + int y = templateChunkY + (sceneY & (CHUNK_SIZE - 1)); + + // create and rotate point back to 0, to match with template + return rotate(new WorldPoint(x, y, plane), 4 - rotation); + } + else + { + return fromLocal(client, localPoint); + } + } + + /** + * Rotate the coordinates in the chunk according to chunk rotation + * + * @param point point + * @param rotation rotation + * @return world point + */ + private static WorldPoint rotate(WorldPoint point, int rotation) + { + int chunkX = point.getX() & ~(CHUNK_SIZE - 1); + int chunkY = point.getY() & ~(CHUNK_SIZE - 1); + int x = point.getX() & (CHUNK_SIZE - 1); + int y = point.getY() & (CHUNK_SIZE - 1); + switch (rotation) + { + case 1: + return new WorldPoint(chunkX + y, chunkY + (CHUNK_SIZE - 1 - x), point.getPlane()); + case 2: + return new WorldPoint(chunkX + (CHUNK_SIZE - 1 - x), chunkY + (CHUNK_SIZE - 1 - y), point.getPlane()); + case 3: + return new WorldPoint(chunkX + (CHUNK_SIZE - 1 - y), chunkY + x, point.getPlane()); + } + return point; + } + /** * Gets the shortest distance from this point to a WorldArea. * diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordPlugin.java index c2605d5186..f5e382ea95 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordPlugin.java @@ -34,11 +34,9 @@ import java.util.EnumSet; import java.util.HashMap; import java.util.Map; import net.runelite.api.Client; -import static net.runelite.api.Constants.CHUNK_SIZE; import net.runelite.api.GameState; import net.runelite.api.Skill; import net.runelite.api.WorldType; -import net.runelite.api.coords.LocalPoint; import net.runelite.api.coords.WorldPoint; import net.runelite.api.events.ConfigChanged; import net.runelite.api.events.ExperienceChanged; @@ -186,7 +184,7 @@ public class DiscordPlugin extends Plugin return; } - final int playerRegionID = getCurrentRegion(); + final int playerRegionID = WorldPoint.fromLocalInstance(client, client.getLocalPlayer().getLocalLocation()).getRegionID(); if (playerRegionID == 0) { @@ -238,26 +236,4 @@ public class DiscordPlugin extends Plugin return false; } - - private int getCurrentRegion() - { - if (!client.isInInstancedRegion()) - { - return client.getLocalPlayer().getWorldLocation().getRegionID(); - } - - // get chunk data of current chunk - final LocalPoint localPoint = client.getLocalPlayer().getLocalLocation(); - final int[][][] instanceTemplateChunks = client.getInstanceTemplateChunks(); - final int z = client.getPlane(); - final int chunkData = instanceTemplateChunks[z][localPoint.getSceneX() / CHUNK_SIZE][localPoint.getSceneY() / CHUNK_SIZE]; - - // extract world point from chunk data - final int chunkY = (chunkData >> 3 & 0x7FF) * CHUNK_SIZE; - final int chunkX = (chunkData >> 14 & 0x3FF) * CHUNK_SIZE; - - final WorldPoint worldPoint = new WorldPoint(chunkX, chunkY, z); - return worldPoint.getRegionID(); - } - } 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 ffbea44f19..199683301f 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 @@ -311,39 +311,7 @@ public class GroundMarkerPlugin extends Plugin return; } - WorldPoint worldPoint; - - if (client.isInInstancedRegion()) - { - // get position in the scene - int sceneX = localPoint.getSceneX(); - int sceneY = localPoint.getSceneY(); - - // get chunk from scene - int chunkX = sceneX / CHUNK_SIZE; - int chunkY = sceneY / CHUNK_SIZE; - - // get the template chunk for the chunk - int[][][] instanceTemplateChunks = client.getInstanceTemplateChunks(); - int templateChunk = instanceTemplateChunks[client.getPlane()][chunkX][chunkY]; - - int rotation = templateChunk >> 1 & 0x3; - int templateChunkY = (templateChunk >> 3 & 0x7FF) * CHUNK_SIZE; - int templateChunkX = (templateChunk >> 14 & 0x3FF) * CHUNK_SIZE; - int plane = templateChunk >> 24 & 0x3; - - // calculate world point of the template - int x = templateChunkX + (sceneX & (CHUNK_SIZE - 1)); - int y = templateChunkY + (sceneY & (CHUNK_SIZE - 1)); - - worldPoint = new WorldPoint(x, y, plane); - // rotate point back to 0, to match with template - worldPoint = rotateInverse(worldPoint, rotation); - } - else - { - worldPoint = WorldPoint.fromLocal(client, localPoint); - } + WorldPoint worldPoint = WorldPoint.fromLocalInstance(client, client.getLocalPlayer().getLocalLocation()); int regionId = worldPoint.getRegionID(); GroundMarkerPoint point = new GroundMarkerPoint(regionId, worldPoint.getX() & 0x3f, worldPoint.getY() & 0x3f, client.getPlane()); From 369fd90d1d565bbe73d2eaaa255e5b4f62be2a54 Mon Sep 17 00:00:00 2001 From: Michael Goodwin <29030969+TheStonedTurtle@users.noreply.github.com> Date: Sun, 2 Sep 2018 22:03:00 +0200 Subject: [PATCH 4/4] Check for correct ToB region when receiving loot Check for ToB region being end region when receiving ToB loot to avoid falsely trigered loot (e.g for onions). Foxes #4695 Signed-off-by: Tomas Slusny --- .../client/plugins/loottracker/LootTrackerPlugin.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java index df4929329b..9c359bad1d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java @@ -45,6 +45,7 @@ import net.runelite.api.ItemContainer; import net.runelite.api.NPC; import net.runelite.api.Player; import net.runelite.api.SpriteID; +import net.runelite.api.coords.WorldPoint; import net.runelite.api.events.ChatMessage; import net.runelite.api.events.WidgetLoaded; import net.runelite.api.widgets.WidgetID; @@ -71,6 +72,7 @@ public class LootTrackerPlugin extends Plugin { // Activity/Event loot handling private static final Pattern CLUE_SCROLL_PATTERN = Pattern.compile("You have completed [0-9]+ ([a-z]+) Treasure Trails."); + private static final int THEATRE_OF_BLOOD_REGION = 12867; @Inject private ClientToolbar clientToolbar; @@ -178,6 +180,11 @@ public class LootTrackerPlugin extends Plugin container = client.getItemContainer(InventoryID.CHAMBERS_OF_XERIC_CHEST); break; case (WidgetID.THEATRE_OF_BLOOD_GROUP_ID): + int region = WorldPoint.fromLocalInstance(client, client.getLocalPlayer().getLocalLocation()).getRegionID(); + if (region != THEATRE_OF_BLOOD_REGION) + { + return; + } eventType = "Theatre of Blood"; container = client.getItemContainer(InventoryID.THEATRE_OF_BLOOD_CHEST); break;