diff --git a/http-api/src/main/java/net/runelite/http/api/loottracker/LootRecord.java b/http-api/src/main/java/net/runelite/http/api/loottracker/LootRecord.java index 01e180c55b..a8e04aefd3 100644 --- a/http-api/src/main/java/net/runelite/http/api/loottracker/LootRecord.java +++ b/http-api/src/main/java/net/runelite/http/api/loottracker/LootRecord.java @@ -40,4 +40,5 @@ public class LootRecord private Object metadata; private Collection drops; private Instant time; + private Integer world; } diff --git a/http-api/src/main/java/net/runelite/http/api/worlds/WorldType.java b/http-api/src/main/java/net/runelite/http/api/worlds/WorldType.java index 9e6ae694e3..20639b5f3c 100644 --- a/http-api/src/main/java/net/runelite/http/api/worlds/WorldType.java +++ b/http-api/src/main/java/net/runelite/http/api/worlds/WorldType.java @@ -32,8 +32,8 @@ public enum WorldType SKILL_TOTAL, HIGH_RISK, LAST_MAN_STANDING, - TOURNAMENT, + NOSAVE_MODE, DEADMAN, - DEADMAN_TOURNAMENT, - LEAGUE; + TOURNAMENT, + SEASONAL; } diff --git a/runelite-api/src/main/java/net/runelite/api/Actor.java b/runelite-api/src/main/java/net/runelite/api/Actor.java index 5c93f47b78..fc70625f2f 100644 --- a/runelite-api/src/main/java/net/runelite/api/Actor.java +++ b/runelite-api/src/main/java/net/runelite/api/Actor.java @@ -295,7 +295,7 @@ public interface Actor extends Renderable, Locatable void setSpotAnimFrame(int spotAnimFrame); /** - * Gets the canvas area of the current tile the actor is standing on. + * Gets the canvas area of the current tiles the actor is standing on. * * @return the current tile canvas area */ diff --git a/runelite-api/src/main/java/net/runelite/api/Model.java b/runelite-api/src/main/java/net/runelite/api/Model.java index dd3c8eb3b0..6830a97b69 100644 --- a/runelite-api/src/main/java/net/runelite/api/Model.java +++ b/runelite-api/src/main/java/net/runelite/api/Model.java @@ -90,8 +90,7 @@ public interface Model extends Renderable short[] getFaceTextures(); - float[][] getFaceTextureUCoordinates(); - float[][] getFaceTextureVCoordinates(); + float[] getFaceTextureUVCoordinates(); void calculateExtreme(int orientation); diff --git a/runelite-api/src/main/java/net/runelite/api/WorldType.java b/runelite-api/src/main/java/net/runelite/api/WorldType.java index 74caa635b6..be922de20d 100644 --- a/runelite-api/src/main/java/net/runelite/api/WorldType.java +++ b/runelite-api/src/main/java/net/runelite/api/WorldType.java @@ -26,10 +26,12 @@ package net.runelite.api; import java.util.Collection; import java.util.EnumSet; +import lombok.AllArgsConstructor; /** * An enumeration of possible world types. */ +@AllArgsConstructor public enum WorldType { /** @@ -57,29 +59,24 @@ public enum WorldType */ LAST_MAN_STANDING(1 << 14), /** - * Tournament world type. + * Beta worlds without profiles that are saved. */ - TOURNAMENT(1 << 25), + NOSAVE_MODE(1 << 25), /** - * Deadman Tournament world type. + * Tournament world type */ - DEADMAN_TOURNAMENT(1 << 26), + TOURNAMENT_WORLD(1 << 26), /** * Deadman world type. */ DEADMAN(1 << 29), /** - * League world type + * Seasonal world type for leagues and seasonal deadman. */ - LEAGUE(1 << 30); + SEASONAL(1 << 30); private final int mask; - WorldType(int mask) - { - this.mask = mask; - } - private static final EnumSet PVP_WORLD_TYPES = EnumSet.of( DEADMAN, // dmmt worlds are also flaged as DEADMAN PVP diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java index bc261ad235..9219be40ce 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java @@ -430,6 +430,7 @@ public class WidgetID static final int SPEC_ORB = 29; static final int SPEC_CLICKBOX = 31; static final int WORLDMAP_ORB = 43; + static final int WIKI_BANNER_PARENT = 44; static final int WIKI_BANNER = 45; static final int WORLDMAP_OPTIONS = 48; } diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java index 616da55b1f..c30aa6a517 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java @@ -182,6 +182,7 @@ public enum WidgetInfo MINIMAP_SPEC_ORB(WidgetID.MINIMAP_GROUP_ID, WidgetID.Minimap.SPEC_ORB), MINIMAP_SPEC_CLICKBOX(WidgetID.MINIMAP_GROUP_ID, WidgetID.Minimap.SPEC_CLICKBOX), MINIMAP_WORLDMAP_ORB(WidgetID.MINIMAP_GROUP_ID, WidgetID.Minimap.WORLDMAP_ORB), + MINIMAP_WIKI_BANNER_PARENT(WidgetID.MINIMAP_GROUP_ID, WidgetID.Minimap.WIKI_BANNER_PARENT), MINIMAP_WIKI_BANNER(WidgetID.MINIMAP_GROUP_ID, WidgetID.Minimap.WIKI_BANNER), MINIMAP_WORLDMAP_OPTIONS(WidgetID.MINIMAP_GROUP_ID, WidgetID.Minimap.WORLDMAP_OPTIONS), diff --git a/runelite-client/src/main/java/net/runelite/client/account/SessionManager.java b/runelite-client/src/main/java/net/runelite/client/account/SessionManager.java index aa2571a957..90c4c0c32d 100644 --- a/runelite-client/src/main/java/net/runelite/client/account/SessionManager.java +++ b/runelite-client/src/main/java/net/runelite/client/account/SessionManager.java @@ -188,7 +188,7 @@ public class SessionManager } catch (IOException ex) { - log.warn("Unable to logout of session", ex); + log.warn("Unable to sign out of session", ex); } accountSession = null; // No more account @@ -227,7 +227,7 @@ public class SessionManager @Subscribe public void onLoginResponse(LoginResponse loginResponse) { - log.debug("Now logged in as {}", loginResponse.getUsername()); + log.debug("Now signed in as {}", loginResponse.getUsername()); AccountSession session = getAccountSession(); session.setUsername(loginResponse.getUsername()); diff --git a/runelite-client/src/main/java/net/runelite/client/config/RuneScapeProfileType.java b/runelite-client/src/main/java/net/runelite/client/config/RuneScapeProfileType.java index d82fc13f69..8eba74cd4d 100644 --- a/runelite-client/src/main/java/net/runelite/client/config/RuneScapeProfileType.java +++ b/runelite-client/src/main/java/net/runelite/client/config/RuneScapeProfileType.java @@ -35,10 +35,10 @@ import net.runelite.api.WorldType; public enum RuneScapeProfileType { STANDARD(client -> true), - BETA(client -> client.getWorldType().contains(WorldType.TOURNAMENT)), + BETA(client -> client.getWorldType().contains(WorldType.NOSAVE_MODE)), DEADMAN(client -> client.getWorldType().contains(WorldType.DEADMAN)), TRAILBLAZER_LEAGUE, - DEADMAN_REBORN(client -> client.getWorldType().contains(WorldType.DEADMAN_TOURNAMENT)) + DEADMAN_REBORN(client -> client.getWorldType().contains(WorldType.SEASONAL)) ; private final Predicate test; diff --git a/runelite-client/src/main/java/net/runelite/client/eventbus/EventBus.java b/runelite-client/src/main/java/net/runelite/client/eventbus/EventBus.java index 4e0ca89965..f2b1a1f21b 100644 --- a/runelite-client/src/main/java/net/runelite/client/eventbus/EventBus.java +++ b/runelite-client/src/main/java/net/runelite/client/eventbus/EventBus.java @@ -44,12 +44,16 @@ import lombok.RequiredArgsConstructor; import lombok.Value; import lombok.extern.slf4j.Slf4j; import net.runelite.client.util.ReflectUtil; +import org.slf4j.Marker; +import org.slf4j.MarkerFactory; @Slf4j @RequiredArgsConstructor @ThreadSafe public class EventBus { + private static final Marker DEDUPLICATE = MarkerFactory.getMarker("DEDUPLICATE"); + @Value public static class Subscriber { @@ -82,7 +86,7 @@ public class EventBus */ public EventBus() { - this((e) -> log.warn("Uncaught exception in event subscriber", e)); + this((e) -> log.warn(DEDUPLICATE, "Uncaught exception in event subscriber", e)); } /** diff --git a/runelite-client/src/main/java/net/runelite/client/game/ItemMapping.java b/runelite-client/src/main/java/net/runelite/client/game/ItemMapping.java index e638eef3af..a194854faa 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/ItemMapping.java +++ b/runelite-client/src/main/java/net/runelite/client/game/ItemMapping.java @@ -196,6 +196,7 @@ public enum ItemMapping ITEM_SANGUINESTI_STAFF(SANGUINESTI_STAFF_UNCHARGED, SANGUINESTI_STAFF, HOLY_SANGUINESTI_STAFF_UNCHARGED, HOLY_SANGUINESTI_STAFF), ITEM_SCYTHE_OF_VITUR(SCYTHE_OF_VITUR_UNCHARGED, SCYTHE_OF_VITUR, HOLY_SCYTHE_OF_VITUR_UNCHARGED, HOLY_SCYTHE_OF_VITUR, SANGUINE_SCYTHE_OF_VITUR_UNCHARGED, SANGUINE_SCYTHE_OF_VITUR), ITEM_TOME_OF_FIRE(TOME_OF_FIRE_EMPTY, TOME_OF_FIRE), + ITEM_TOME_OF_WATER(TOME_OF_WATER_EMPTY, TOME_OF_WATER), ITEM_CRAWS_BOW(CRAWS_BOW_U, CRAWS_BOW), ITEM_VIGGORAS_CHAINMACE(VIGGORAS_CHAINMACE_U, VIGGORAS_CHAINMACE), ITEM_THAMMARONS_SCEPTRE(THAMMARONS_SCEPTRE_U, THAMMARONS_SCEPTRE), @@ -255,6 +256,7 @@ public enum ItemMapping ITEM_VOLATILE_ORB(VOLATILE_ORB, VOLATILE_NIGHTMARE_STAFF), ITEM_NIGHTMARE_STAFF(NIGHTMARE_STAFF, ELDRITCH_NIGHTMARE_STAFF, HARMONISED_NIGHTMARE_STAFF, VOLATILE_NIGHTMARE_STAFF), ITEM_GHARZI_RAPIER(GHRAZI_RAPIER, HOLY_GHRAZI_RAPIER), + ITEM_MASTER_SCROLL_BOOK(MASTER_SCROLL_BOOK_EMPTY, MASTER_SCROLL_BOOK), // Trouver Parchment ITEM_TROUVER_PARCHMENT( diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/account/AccountPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/account/AccountPlugin.java index 501537654e..2cb1c66ded 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/account/AccountPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/account/AccountPlugin.java @@ -75,14 +75,14 @@ public class AccountPlugin extends Plugin loginButton = NavigationButton.builder() .tab(false) .icon(LOGIN_IMAGE) - .tooltip("Log in to RuneLite") + .tooltip("Sign in to RuneLite") .onClick(this::loginClick) .build(); logoutButton = NavigationButton.builder() .tab(false) .icon(LOGOUT_IMAGE) - .tooltip("Log out of RuneLite") + .tooltip("Sign out of RuneLite") .onClick(this::logoutClick) .build(); @@ -113,7 +113,7 @@ public class AccountPlugin extends Plugin private void logoutClick() { if (JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(null, - "Are you sure you want to log out from RuneLite?", "Logout Confirmation", + "Are you sure you want to sign out of RuneLite?", "Sign Out Confirmation", JOptionPane.YES_NO_OPTION)) { executor.execute(sessionManager::logout); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityOverlay.java index d44863d2a1..78c9bec540 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityOverlay.java @@ -35,7 +35,6 @@ import java.util.Set; import javax.inject.Inject; 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.Tile; @@ -157,11 +156,7 @@ class AgilityOverlay extends Overlay Color color = config.sepulchreHighlightColor(); for (NPC npc : npcs) { - NPCComposition npcComposition = npc.getComposition(); - int size = npcComposition.getSize(); - LocalPoint lp = npc.getLocalLocation(); - - Polygon tilePoly = Perspective.getCanvasTileAreaPoly(client, lp, size); + Polygon tilePoly = npc.getCanvasTilePoly(); if (tilePoly != null) { OverlayUtil.renderPolygon(graphics, tilePoly, color); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java index 01b29fe814..9168c8f150 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java @@ -1738,12 +1738,12 @@ public class ChatCommandsPlugin extends Plugin return new HiscoreLookup(localPlayer.getName(), hiscoreEndpoint); } - // Public chat on a leagues world is always league hiscores, regardless of icon if (chatMessage.getType() == ChatMessageType.PUBLICCHAT || chatMessage.getType() == ChatMessageType.MODCHAT) { - if (client.getWorldType().contains(WorldType.LEAGUE)) + // Public chat on a seasonal world is always seasonal or tournament hiscores, regardless of icon + if (client.getWorldType().contains(WorldType.SEASONAL)) { - return new HiscoreLookup(player, HiscoreEndpoint.LEAGUE); + return new HiscoreLookup(player, HiscoreEndpoint.TOURNAMENT); } } @@ -1789,9 +1789,9 @@ public class ChatCommandsPlugin extends Plugin private HiscoreEndpoint getLocalHiscoreEndpointType() { EnumSet worldType = client.getWorldType(); - if (worldType.contains(WorldType.LEAGUE)) + if (worldType.contains(WorldType.SEASONAL)) { - return HiscoreEndpoint.LEAGUE; + return HiscoreEndpoint.TOURNAMENT; } return toEndPoint(client.getAccountType()); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/SceneUploader.java b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/SceneUploader.java index 548eca7589..675381053d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/SceneUploader.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/SceneUploader.java @@ -389,8 +389,7 @@ class SceneUploader final short[] faceTextures = model.getFaceTextures(); final byte[] facePriorities = model.getFaceRenderPriorities(); - float[][] u = model.getFaceTextureUCoordinates(); - float[][] v = model.getFaceTextureVCoordinates(); + float[] uv = model.getFaceTextureUVCoordinates(); int len = 0; for (int face = 0; face < triangleCount; ++face) @@ -432,7 +431,7 @@ class SceneUploader if (faceTextures != null) { - pushUvForFace(faceTextures, u, v, face, uvBuffer); + pushUvForFace(faceTextures, uv, face, uvBuffer); } len += 3; @@ -559,11 +558,9 @@ class SceneUploader vertexBuffer.put(a, b, c, packedAlphaPriority | color3); - float[][] u = model.getFaceTextureUCoordinates(); - float[][] v = model.getFaceTextureVCoordinates(); if (padUvs || faceTextures != null) { - pushUvForFace(faceTextures, u, v, face, uvBuffer); + pushUvForFace(faceTextures, model.getFaceTextureUVCoordinates(), face, uvBuffer); } return 3; @@ -584,15 +581,15 @@ class SceneUploader return alpha | priority; } - private static void pushUvForFace(short[] faceTextures, float[][] u, float[][] v, int face, GpuFloatBuffer uvBuffer) + private static void pushUvForFace(short[] faceTextures, float[] uv, int face, GpuFloatBuffer uvBuffer) { - float[] uf, vf; - if (faceTextures != null && u != null && v != null && (uf = u[face]) != null && (vf = v[face]) != null) + if (faceTextures != null && faceTextures[face] != -1 && uv != null) { + int idx = face * 6; float texture = faceTextures[face] + 1f; - uvBuffer.put(texture, uf[0], vf[0], 0f); - uvBuffer.put(texture, uf[1], vf[1], 0f); - uvBuffer.put(texture, uf[2], vf[2], 0f); + uvBuffer.put(texture, uv[idx], uv[idx + 1], 0f); + uvBuffer.put(texture, uv[idx + 2], uv[idx + 3], 0f); + uvBuffer.put(texture, uv[idx + 4], uv[idx + 5], 0f); } else { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangePlugin.java index 53f3276b12..a8dd17da60 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangePlugin.java @@ -479,9 +479,9 @@ public class GrandExchangePlugin extends Plugin private WorldType getGeWorldType() { EnumSet worldTypes = client.getWorldType(); - if (worldTypes.contains(net.runelite.api.WorldType.DEADMAN_TOURNAMENT)) + if (worldTypes.contains(net.runelite.api.WorldType.SEASONAL)) { - return WorldType.DEADMAN_TOURNAMENT; + return WorldType.SEASONAL; } else if (worldTypes.contains(net.runelite.api.WorldType.DEADMAN)) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/HiscorePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/HiscorePlugin.java index ac905ca4c5..4071b8eed7 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/HiscorePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/HiscorePlugin.java @@ -265,7 +265,7 @@ public class HiscorePlugin extends Plugin { EnumSet wTypes = client.getWorldType(); - if (wTypes.contains(WorldType.DEADMAN_TOURNAMENT)) + if (wTypes.contains(WorldType.SEASONAL)) { return HiscoreEndpoint.TOURNAMENT; } @@ -273,10 +273,6 @@ public class HiscorePlugin extends Plugin { return HiscoreEndpoint.DEADMAN; } - else if (wTypes.contains(WorldType.LEAGUE)) - { - return HiscoreEndpoint.LEAGUE; - } } return HiscoreEndpoint.NORMAL; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/info/InfoPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/info/InfoPanel.java index 246fd0aef8..cd0b7c8fa9 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/info/InfoPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/info/InfoPanel.java @@ -189,7 +189,7 @@ public class InfoPanel extends PluginPanel syncPanel = buildLinkPanel(IMPORT_ICON, "Import signed-out", "settings", () -> { final int result = JOptionPane.showOptionDialog(syncPanel, - "This will overwrite your settings with settings from your local profile, which
is the profile used when not logged into RuneLite with a RuneLite account.", + "This will overwrite your settings with settings from your local profile, which
is the profile used when not signed into RuneLite with a RuneLite account.", "Are you sure?", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null, new String[]{"Yes", "No"}, "No"); @@ -303,14 +303,14 @@ public class InfoPanel extends PluginPanel { emailLabel.setContentType("text/plain"); emailLabel.setText(name); - loggedLabel.setText("Logged in as"); + loggedLabel.setText("Signed in as"); actionsContainer.add(syncPanel, 0); } else { emailLabel.setContentType("text/html"); - emailLabel.setText("Login to sync settings to the cloud."); - loggedLabel.setText("Not logged in"); + emailLabel.setText("Sign in to sync settings to the cloud."); + loggedLabel.setText("Not signed in"); actionsContainer.remove(syncPanel); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerBox.java b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerBox.java index f0248b19be..16da3c9460 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerBox.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerBox.java @@ -50,6 +50,7 @@ import javax.swing.SwingConstants; import javax.swing.border.EmptyBorder; import lombok.AccessLevel; import lombok.Getter; +import net.runelite.api.ItemID; import net.runelite.client.game.ItemManager; import net.runelite.client.ui.ColorScheme; import net.runelite.client.ui.FontManager; @@ -375,8 +376,32 @@ class LootTrackerBox extends JPanel final long gePrice = item.getTotalGePrice(); final long haPrice = item.getTotalHaPrice(); final String ignoredLabel = item.isIgnored() ? " - Ignored" : ""; - return "" + name + " x " + quantity + ignoredLabel - + "
GE: " + QuantityFormatter.quantityToStackSize(gePrice) - + "
HA: " + QuantityFormatter.quantityToStackSize(haPrice) + ""; + final StringBuilder sb = new StringBuilder(""); + sb.append(name).append(" x ").append(QuantityFormatter.formatNumber(quantity)).append(ignoredLabel); + if (item.getId() == ItemID.COINS_995) + { + sb.append(""); + return sb.toString(); + } + + sb.append("
GE: ").append(QuantityFormatter.quantityToStackSize(gePrice)); + if (quantity > 1) + { + sb.append(" (").append(QuantityFormatter.quantityToStackSize(item.getGePrice())).append(" ea)"); + } + + if (item.getId() == ItemID.PLATINUM_TOKEN) + { + sb.append(""); + return sb.toString(); + } + + sb.append("
HA: ").append(QuantityFormatter.quantityToStackSize(haPrice)); + if (quantity > 1) + { + sb.append(" (").append(QuantityFormatter.quantityToStackSize(item.getHaPrice())).append(" ea)"); + } + sb.append(""); + return sb.toString(); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerConfig.java index abf9234a5e..983cfb45a9 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerConfig.java @@ -92,7 +92,7 @@ public interface LootTrackerConfig extends Config @ConfigItem( keyName = "syncPanel", name = "Synchronize panel contents", - description = "Synchronize your local loot tracker with your server data (requires being logged in).
" + + description = "Synchronize your local loot tracker with your server data (requires being signed in).
" + " This means the panel is filled with portions of your remote data on startup
" + " and deleting data in the panel also deletes it on the server." ) 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 634a1fcc77..5519be978a 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 @@ -74,6 +74,7 @@ import net.runelite.api.ObjectID; import net.runelite.api.Player; import net.runelite.api.Skill; import net.runelite.api.SpriteID; +import net.runelite.api.WorldType; import net.runelite.api.coords.WorldPoint; import net.runelite.api.events.ChatMessage; import net.runelite.api.events.GameStateChanged; @@ -479,7 +480,7 @@ public class LootTrackerPlugin extends Plugin if (config.saveLoot()) { - LootRecord lootRecord = new LootRecord(name, type, metadata, toGameItems(items), Instant.now()); + LootRecord lootRecord = new LootRecord(name, type, metadata, toGameItems(items), Instant.now(), getLootWorldId()); synchronized (queuedLoots) { queuedLoots.add(lootRecord); @@ -489,6 +490,12 @@ public class LootTrackerPlugin extends Plugin eventBus.post(new LootReceived(name, combatLevel, type, items)); } + private Integer getLootWorldId() + { + // For the wiki to determine drop rates based on dmm brackets + return client.getWorldType().contains(WorldType.SEASONAL) ? client.getWorld() : null; + } + @Subscribe public void onNpcLootReceived(final NpcLootReceived npcLootReceived) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/mining/MiningPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/mining/MiningPlugin.java index 6cc0e90ae4..67edf4a1e5 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/mining/MiningPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/mining/MiningPlugin.java @@ -50,6 +50,10 @@ import static net.runelite.api.ObjectID.ORE_VEIN_26661; import static net.runelite.api.ObjectID.ORE_VEIN_26662; import static net.runelite.api.ObjectID.ORE_VEIN_26663; import static net.runelite.api.ObjectID.ORE_VEIN_26664; +import static net.runelite.api.ObjectID.ROCKS_41547; +import static net.runelite.api.ObjectID.ROCKS_41548; +import static net.runelite.api.ObjectID.ROCKS_41549; +import static net.runelite.api.ObjectID.ROCKS_41550; import net.runelite.api.Player; import net.runelite.api.WallObject; import net.runelite.api.coords.WorldPoint; @@ -79,12 +83,12 @@ import net.runelite.client.ui.overlay.OverlayMenuEntry; @PluginDependency(XpTrackerPlugin.class) public class MiningPlugin extends Plugin { - private static final Pattern MINING_PATERN = Pattern.compile( + private static final Pattern MINING_PATTERN = Pattern.compile( "You " + "(?:manage to|just)" + " (?:mined?|quarry) " + "(?:some|an?) " + - "(?:copper|tin|clay|iron|silver|coal|gold|mithril|adamantite|runeite|amethyst|sandstone|granite|Opal|piece of Jade|Red Topaz|Emerald|Sapphire|Ruby|Diamond)" + + "(?:copper|tin|clay|iron|silver|coal|gold|mithril|adamantite|runeite|amethyst|sandstone|granite|barronite shards|barronite deposit|Opal|piece of Jade|Red Topaz|Emerald|Sapphire|Ruby|Diamond)" + "(?:\\.|!)"); @Inject @@ -343,10 +347,20 @@ public class MiningPlugin extends Plugin respawns.add(rockRespawn); break; } + case ROCKS_41549: // Depleted barronite vein + case ROCKS_41550: // Depleted barronite vein + { + Rock rock = Rock.BARRONITE; + RockRespawn rockRespawn = new RockRespawn(rock, object.getWorldLocation(), Instant.now(), (int) rock.getRespawnTime(region).toMillis(), rock.getZOffset()); + respawns.add(rockRespawn); + break; + } case ORE_VEIN_26661: // Motherlode vein case ORE_VEIN_26662: // Motherlode vein case ORE_VEIN_26663: // Motherlode vein case ORE_VEIN_26664: // Motherlode vein + case ROCKS_41547: // Barronite vein + case ROCKS_41548: // Barronite vein { // If the vein respawns before the timer is up, remove it final WorldPoint point = object.getWorldLocation(); @@ -361,7 +375,7 @@ public class MiningPlugin extends Plugin { if (event.getType() == ChatMessageType.SPAM || event.getType() == ChatMessageType.GAMEMESSAGE) { - if (MINING_PATERN.matcher(event.getMessage()).matches()) + if (MINING_PATTERN.matcher(event.getMessage()).matches()) { if (session == null) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/mining/Rock.java b/runelite-client/src/main/java/net/runelite/client/plugins/mining/Rock.java index 4f8cf9b32f..ac28366b8b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/mining/Rock.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/mining/Rock.java @@ -97,7 +97,8 @@ enum Rock EFH_SALT(Duration.of(9, GAME_TICKS), 0, ROCKS_33255), TE_SALT(Duration.of(9, GAME_TICKS), 0, ROCKS_33256), BASALT(Duration.of(9, GAME_TICKS), 0, ROCKS_33257), - DAEYALT_ESSENCE(Duration.of(MiningRocksOverlay.DAEYALT_MAX_RESPAWN_TIME, GAME_TICKS), 0, DAEYALT_ESSENCE_39095); + DAEYALT_ESSENCE(Duration.of(MiningRocksOverlay.DAEYALT_MAX_RESPAWN_TIME, GAME_TICKS), 0, DAEYALT_ESSENCE_39095), + BARRONITE(Duration.of(89, GAME_TICKS), 140); private static final int WILDERNESS_RESOURCE_AREA = 12605; private static final int MISCELLANIA = 10044; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcSceneOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcSceneOverlay.java index 84e428918c..a13ef58ade 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcSceneOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcSceneOverlay.java @@ -162,10 +162,7 @@ public class NpcSceneOverlay extends Overlay if (highlightedNpc.isTile()) { - int size = npcComposition.getSize(); - LocalPoint lp = actor.getLocalLocation(); - Polygon tilePoly = Perspective.getCanvasTileAreaPoly(client, lp, size); - + Polygon tilePoly = actor.getCanvasTilePoly(); renderPoly(graphics, borderColor, fillColor, tilePoly); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoPlugin.java index 65fcf0af05..4d58b924d1 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoPlugin.java @@ -116,7 +116,7 @@ public class OpponentInfoPlugin extends Plugin } final EnumSet worldType = client.getWorldType(); - if (worldType.contains(WorldType.DEADMAN_TOURNAMENT)) + if (worldType.contains(WorldType.SEASONAL)) { hiscoreEndpoint = HiscoreEndpoint.TOURNAMENT; } @@ -124,10 +124,6 @@ public class OpponentInfoPlugin extends Plugin { hiscoreEndpoint = HiscoreEndpoint.DEADMAN; } - else if (worldType.contains(WorldType.LEAGUE)) - { - hiscoreEndpoint = HiscoreEndpoint.LEAGUE; - } else { hiscoreEndpoint = HiscoreEndpoint.NORMAL; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/roofremoval/RoofRemovalPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/roofremoval/RoofRemovalPlugin.java index a9e92f4420..9f86d9a47e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/roofremoval/RoofRemovalPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/roofremoval/RoofRemovalPlugin.java @@ -46,6 +46,7 @@ import static net.runelite.api.Constants.ROOF_FLAG_HOVERED; import static net.runelite.api.Constants.ROOF_FLAG_POSITION; import net.runelite.api.GameState; import net.runelite.api.Tile; +import net.runelite.api.coords.WorldPoint; import net.runelite.api.events.GameStateChanged; import net.runelite.client.callback.ClientThread; import net.runelite.client.config.ConfigManager; @@ -246,14 +247,17 @@ public class RoofRemovalPlugin extends Plugin continue; } - int regionID = tile.getWorldLocation().getRegionID() << 2 | z; + // Properly account for instances shifting worldpoints around + final WorldPoint wp = WorldPoint.fromLocalInstance(client, tile.getLocalLocation(), tile.getPlane()); + + int regionID = wp.getRegionID() << 2 | z; if (!overrides.containsKey(regionID)) { continue; } - int rx = tile.getWorldLocation().getRegionX(); - int ry = tile.getWorldLocation().getRegionY(); + int rx = wp.getRegionX(); + int ry = wp.getRegionY(); long[] region = overrides.get(regionID); if ((region[ry] & (1L << rx)) != 0) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeablePanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeablePanel.java index 1a8b23a8fa..8903a0b715 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeablePanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/TimeablePanel.java @@ -46,6 +46,9 @@ import net.runelite.client.util.SwingUtil; @Getter public class TimeablePanel extends JPanel { + private static final ImageIcon NOTIFY_ICON = new ImageIcon(ImageUtil.loadImageResource(TimeTrackingPlugin.class, "notify_icon.png")); + private static final ImageIcon NOTIFY_SELECTED_ICON = new ImageIcon(ImageUtil.loadImageResource(TimeTrackingPlugin.class, "notify_selected_icon.png")); + private final T timeable; private final JLabel icon = new JLabel(); private final JLabel farmingContractIcon = new JLabel(); @@ -84,13 +87,10 @@ public class TimeablePanel extends JPanel infoPanel.add(text); infoPanel.add(estimate); - ImageIcon notifyIcon = new ImageIcon(ImageUtil.loadImageResource(TimeTrackingPlugin.class, "notify_icon.png")); - ImageIcon notifySelectedIcon = new ImageIcon(ImageUtil.loadImageResource(TimeTrackingPlugin.class, "notify_selected_icon.png")); - notifyButton.setPreferredSize(new Dimension(30, 16)); notifyButton.setBorder(new EmptyBorder(0, 0, 0, 10)); - notifyButton.setIcon(notifyIcon); - notifyButton.setSelectedIcon(notifySelectedIcon); + notifyButton.setIcon(NOTIFY_ICON); + notifyButton.setSelectedIcon(NOTIFY_SELECTED_ICON); SwingUtil.removeButtonDecorations(notifyButton); SwingUtil.addModalTooltip(notifyButton, "Disable notifications", "Enable notifications"); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiPlugin.java index 7354a5a7f0..589ebc9240 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiPlugin.java @@ -118,13 +118,12 @@ public class WikiPlugin extends Plugin private void removeWidgets() { - - Widget minimapOrbs = client.getWidget(WidgetInfo.MINIMAP_ORBS); - if (minimapOrbs == null) + Widget wikiBannerParent = client.getWidget(WidgetInfo.MINIMAP_WIKI_BANNER_PARENT); + if (wikiBannerParent == null) { return; } - Widget[] children = minimapOrbs.getChildren(); + Widget[] children = wikiBannerParent.getChildren(); if (children == null || children.length < 1) { return; @@ -152,8 +151,8 @@ public class WikiPlugin extends Plugin private void addWidgets() { - Widget minimapOrbs = client.getWidget(WidgetInfo.MINIMAP_ORBS); - if (minimapOrbs == null) + Widget wikiBannerParent = client.getWidget(WidgetInfo.MINIMAP_WIKI_BANNER_PARENT); + if (wikiBannerParent == null) { return; } @@ -164,12 +163,12 @@ public class WikiPlugin extends Plugin vanilla.setHidden(true); } - icon = minimapOrbs.createChild(0, WidgetType.GRAPHIC); + icon = wikiBannerParent.createChild(0, WidgetType.GRAPHIC); icon.setSpriteId(SpriteID.WIKI_DESELECTED); icon.setOriginalX(0); icon.setOriginalY(0); - icon.setXPositionMode(WidgetPositionMode.ABSOLUTE_RIGHT); - icon.setYPositionMode(WidgetPositionMode.ABSOLUTE_BOTTOM); + icon.setXPositionMode(WidgetPositionMode.ABSOLUTE_CENTER); + icon.setYPositionMode(WidgetPositionMode.ABSOLUTE_CENTER); icon.setOriginalWidth(40); icon.setOriginalHeight(14); icon.setTargetVerb("Lookup"); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldTableRow.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldTableRow.java index 11f9c8b261..29ba121129 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldTableRow.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldTableRow.java @@ -1,364 +1,402 @@ -/* - * Copyright (c) 2018, Psikoi - * 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.worldhopper; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.event.ActionListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.function.BiConsumer; -import java.util.function.Consumer; -import javax.swing.ImageIcon; -import javax.swing.JLabel; -import javax.swing.JMenuItem; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.border.EmptyBorder; -import lombok.AccessLevel; -import lombok.Getter; -import net.runelite.client.ui.FontManager; -import net.runelite.client.util.ImageUtil; -import net.runelite.http.api.worlds.World; -import net.runelite.http.api.worlds.WorldRegion; -import net.runelite.http.api.worlds.WorldType; - -class WorldTableRow extends JPanel -{ - private static final ImageIcon FLAG_AUS; - private static final ImageIcon FLAG_UK; - private static final ImageIcon FLAG_US; - private static final ImageIcon FLAG_GER; - - private static final int WORLD_COLUMN_WIDTH = 60; - private static final int PLAYERS_COLUMN_WIDTH = 40; - private static final int PING_COLUMN_WIDTH = 35; - - private static final Color CURRENT_WORLD = new Color(66, 227, 17); - private static final Color DANGEROUS_WORLD = new Color(251, 62, 62); - private static final Color TOURNAMENT_WORLD = new Color(79, 145, 255); - private static final Color MEMBERS_WORLD = new Color(210, 193, 53); - private static final Color FREE_WORLD = new Color(200, 200, 200); - private static final Color LEAGUE_WORLD = new Color(133, 177, 178); - - static - { - FLAG_AUS = new ImageIcon(ImageUtil.loadImageResource(WorldHopperPlugin.class, "flag_aus.png")); - FLAG_UK = new ImageIcon(ImageUtil.loadImageResource(WorldHopperPlugin.class, "flag_uk.png")); - FLAG_US = new ImageIcon(ImageUtil.loadImageResource(WorldHopperPlugin.class, "flag_us.png")); - FLAG_GER = new ImageIcon(ImageUtil.loadImageResource(WorldHopperPlugin.class, "flag_ger.png")); - } - - private final JMenuItem favoriteMenuOption = new JMenuItem(); - - private JLabel worldField; - private JLabel playerCountField; - private JLabel activityField; - private JLabel pingField; - private final BiConsumer onFavorite; - - @Getter - private final World world; - - @Getter(AccessLevel.PACKAGE) - private int updatedPlayerCount; - - private int ping; - - private Color lastBackground; - - WorldTableRow(World world, boolean current, boolean favorite, Integer ping, Consumer onSelect, BiConsumer onFavorite) - { - this.world = world; - this.onFavorite = onFavorite; - this.updatedPlayerCount = world.getPlayers(); - - setLayout(new BorderLayout()); - setBorder(new EmptyBorder(2, 0, 2, 0)); - - addMouseListener(new MouseAdapter() - { - @Override - public void mouseClicked(MouseEvent mouseEvent) - { - if (mouseEvent.getClickCount() == 2) - { - if (onSelect != null) - { - onSelect.accept(world); - } - } - } - - @Override - public void mousePressed(MouseEvent mouseEvent) - { - if (mouseEvent.getClickCount() == 2) - { - setBackground(getBackground().brighter()); - } - } - - @Override - public void mouseReleased(MouseEvent mouseEvent) - { - if (mouseEvent.getClickCount() == 2) - { - setBackground(getBackground().darker()); - } - } - - @Override - public void mouseEntered(MouseEvent mouseEvent) - { - WorldTableRow.this.lastBackground = getBackground(); - setBackground(getBackground().brighter()); - } - - @Override - public void mouseExited(MouseEvent mouseEvent) - { - setBackground(lastBackground); - } - }); - - setFavoriteMenu(favorite); - - final JPopupMenu popupMenu = new JPopupMenu(); - popupMenu.setBorder(new EmptyBorder(5, 5, 5, 5)); - popupMenu.add(favoriteMenuOption); - - setComponentPopupMenu(popupMenu); - - JPanel leftSide = new JPanel(new BorderLayout()); - JPanel rightSide = new JPanel(new BorderLayout()); - leftSide.setOpaque(false); - rightSide.setOpaque(false); - - JPanel worldField = buildWorldField(); - worldField.setPreferredSize(new Dimension(WORLD_COLUMN_WIDTH, 0)); - worldField.setOpaque(false); - - JPanel pingField = buildPingField(ping); - pingField.setPreferredSize(new Dimension(PING_COLUMN_WIDTH, 0)); - pingField.setOpaque(false); - - JPanel playersField = buildPlayersField(); - playersField.setPreferredSize(new Dimension(PLAYERS_COLUMN_WIDTH, 0)); - playersField.setOpaque(false); - - JPanel activityField = buildActivityField(); - activityField.setBorder(new EmptyBorder(5, 5, 5, 5)); - activityField.setOpaque(false); - - recolour(current); - - leftSide.add(worldField, BorderLayout.WEST); - leftSide.add(playersField, BorderLayout.CENTER); - rightSide.add(activityField, BorderLayout.CENTER); - rightSide.add(pingField, BorderLayout.EAST); - - add(leftSide, BorderLayout.WEST); - add(rightSide, BorderLayout.CENTER); - } - - void setFavoriteMenu(boolean favorite) - { - String favoriteAction = favorite ? - "Remove " + world.getId() + " from favorites" : - "Add " + world.getId() + " to favorites"; - - favoriteMenuOption.setText(favoriteAction); - - for (ActionListener listener : favoriteMenuOption.getActionListeners()) - { - favoriteMenuOption.removeActionListener(listener); - } - - favoriteMenuOption.addActionListener(e -> - { - onFavorite.accept(world, !favorite); - }); - } - - void updatePlayerCount(int playerCount) - { - this.updatedPlayerCount = playerCount; - playerCountField.setText(playerCountString(playerCount)); - } - - private static String playerCountString(int playerCount) - { - return playerCount < 0 ? "OFF" : Integer.toString(playerCount); - } - - void setPing(int ping) - { - this.ping = ping; - pingField.setText(ping <= 0 ? "-" : Integer.toString(ping)); - } - - void hidePing() - { - pingField.setText("-"); - } - - void showPing() - { - setPing(ping); // to update pingField - } - - int getPing() - { - return ping; - } - - public void recolour(boolean current) - { - playerCountField.setForeground(current ? CURRENT_WORLD : Color.WHITE); - pingField.setForeground(current ? CURRENT_WORLD : Color.WHITE); - - if (current) - { - activityField.setForeground(CURRENT_WORLD); - worldField.setForeground(CURRENT_WORLD); - return; - } - else if (world.getTypes().contains(WorldType.PVP) - || world.getTypes().contains(WorldType.HIGH_RISK) - || world.getTypes().contains(WorldType.DEADMAN)) - { - activityField.setForeground(DANGEROUS_WORLD); - } - else if (world.getTypes().contains(WorldType.LEAGUE)) - { - activityField.setForeground(LEAGUE_WORLD); - } - else if (world.getTypes().contains(WorldType.TOURNAMENT)) - { - activityField.setForeground(TOURNAMENT_WORLD); - } - else - { - activityField.setForeground(Color.WHITE); - } - - worldField.setForeground(world.getTypes().contains(WorldType.MEMBERS) ? MEMBERS_WORLD : FREE_WORLD); - } - - /** - * Builds the players list field (containing the amount of players logged in that world). - */ - private JPanel buildPlayersField() - { - JPanel column = new JPanel(new BorderLayout()); - column.setBorder(new EmptyBorder(0, 5, 0, 5)); - - playerCountField = new JLabel(playerCountString(world.getPlayers())); - playerCountField.setFont(FontManager.getRunescapeSmallFont()); - - column.add(playerCountField, BorderLayout.WEST); - - return column; - } - - private JPanel buildPingField(Integer ping) - { - JPanel column = new JPanel(new BorderLayout()); - column.setBorder(new EmptyBorder(0, 5, 0, 5)); - - pingField = new JLabel("-"); - pingField.setFont(FontManager.getRunescapeSmallFont()); - - column.add(pingField, BorderLayout.EAST); - - if (ping != null) - { - setPing(ping); - } - - return column; - } - - /** - * Builds the activity list field (containing that world's activity/theme). - */ - private JPanel buildActivityField() - { - JPanel column = new JPanel(new BorderLayout()); - column.setBorder(new EmptyBorder(0, 5, 0, 5)); - - activityField = new JLabel(world.getActivity()); - activityField.setFont(FontManager.getRunescapeSmallFont()); - - column.add(activityField, BorderLayout.WEST); - - return column; - } - - /** - * Builds the world list field (containing the country's flag and the world index). - */ - private JPanel buildWorldField() - { - JPanel column = new JPanel(new BorderLayout(7, 0)); - column.setBorder(new EmptyBorder(0, 5, 0, 5)); - - worldField = new JLabel(world.getId() + ""); - - ImageIcon flagIcon = getFlag(world.getRegion()); - if (flagIcon != null) - { - JLabel flag = new JLabel(flagIcon); - column.add(flag, BorderLayout.WEST); - } - column.add(worldField, BorderLayout.CENTER); - - return column; - } - - private static ImageIcon getFlag(WorldRegion region) - { - if (region == null) - { - return null; - } - - switch (region) - { - case UNITED_STATES_OF_AMERICA: - return FLAG_US; - case UNITED_KINGDOM: - return FLAG_UK; - case AUSTRALIA: - return FLAG_AUS; - case GERMANY: - return FLAG_GER; - default: - return null; - } - } -} +/* + * Copyright (c) 2018, Psikoi + * 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.worldhopper; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import javax.swing.ImageIcon; +import javax.swing.JLabel; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.border.EmptyBorder; +import lombok.AccessLevel; +import lombok.Getter; +import net.runelite.client.ui.FontManager; +import net.runelite.client.util.ImageUtil; +import net.runelite.http.api.worlds.World; +import net.runelite.http.api.worlds.WorldRegion; +import net.runelite.http.api.worlds.WorldType; + +class WorldTableRow extends JPanel +{ + private static final ImageIcon FLAG_AUS; + private static final ImageIcon FLAG_UK; + private static final ImageIcon FLAG_US; + private static final ImageIcon FLAG_GER; + + private static final int WORLD_COLUMN_WIDTH = 60; + private static final int PLAYERS_COLUMN_WIDTH = 40; + private static final int PING_COLUMN_WIDTH = 35; + + private static final Color CURRENT_WORLD = new Color(66, 227, 17); + private static final Color DANGEROUS_WORLD = new Color(251, 62, 62); + private static final Color TOURNAMENT_WORLD = new Color(79, 145, 255); + private static final Color MEMBERS_WORLD = new Color(210, 193, 53); + private static final Color FREE_WORLD = new Color(200, 200, 200); + private static final Color SEASONAL_WORLD = new Color(133, 177, 178); + + static + { + FLAG_AUS = new ImageIcon(ImageUtil.loadImageResource(WorldHopperPlugin.class, "flag_aus.png")); + FLAG_UK = new ImageIcon(ImageUtil.loadImageResource(WorldHopperPlugin.class, "flag_uk.png")); + FLAG_US = new ImageIcon(ImageUtil.loadImageResource(WorldHopperPlugin.class, "flag_us.png")); + FLAG_GER = new ImageIcon(ImageUtil.loadImageResource(WorldHopperPlugin.class, "flag_ger.png")); + } + + private final JMenuItem favoriteMenuOption = new JMenuItem(); + + private JLabel worldField; + private JLabel playerCountField; + private JLabel activityField; + private JLabel pingField; + private final BiConsumer onFavorite; + + @Getter + private final World world; + + @Getter(AccessLevel.PACKAGE) + private int updatedPlayerCount; + + private int ping; + + private Color lastBackground; + + WorldTableRow(World world, boolean current, boolean favorite, Integer ping, Consumer onSelect, BiConsumer onFavorite) + { + this.world = world; + this.onFavorite = onFavorite; + this.updatedPlayerCount = world.getPlayers(); + + setLayout(new BorderLayout()); + setBorder(new EmptyBorder(2, 0, 2, 0)); + + addMouseListener(new MouseAdapter() + { + @Override + public void mouseClicked(MouseEvent mouseEvent) + { + if (mouseEvent.getClickCount() == 2) + { + if (onSelect != null) + { + onSelect.accept(world); + } + } + } + + @Override + public void mousePressed(MouseEvent mouseEvent) + { + if (mouseEvent.getClickCount() == 2) + { + setBackground(getBackground().brighter()); + } + } + + @Override + public void mouseReleased(MouseEvent mouseEvent) + { + if (mouseEvent.getClickCount() == 2) + { + setBackground(getBackground().darker()); + } + } + + @Override + public void mouseEntered(MouseEvent mouseEvent) + { + WorldTableRow.this.lastBackground = getBackground(); + setBackground(getBackground().brighter()); + } + + @Override + public void mouseExited(MouseEvent mouseEvent) + { + setBackground(lastBackground); + } + }); + + setFavoriteMenu(favorite); + + final JPopupMenu popupMenu = new JPopupMenu(); + popupMenu.setBorder(new EmptyBorder(5, 5, 5, 5)); + popupMenu.add(favoriteMenuOption); + + setComponentPopupMenu(popupMenu); + + JPanel leftSide = new JPanel(new BorderLayout()); + JPanel rightSide = new JPanel(new BorderLayout()); + leftSide.setOpaque(false); + rightSide.setOpaque(false); + + JPanel worldField = buildWorldField(); + worldField.setPreferredSize(new Dimension(WORLD_COLUMN_WIDTH, 0)); + worldField.setOpaque(false); + + JPanel pingField = buildPingField(ping); + pingField.setPreferredSize(new Dimension(PING_COLUMN_WIDTH, 0)); + pingField.setOpaque(false); + + JPanel playersField = buildPlayersField(); + playersField.setPreferredSize(new Dimension(PLAYERS_COLUMN_WIDTH, 0)); + playersField.setOpaque(false); + + JPanel activityField = buildActivityField(); + activityField.setBorder(new EmptyBorder(5, 5, 5, 5)); + activityField.setOpaque(false); + + recolour(current); + + leftSide.add(worldField, BorderLayout.WEST); + leftSide.add(playersField, BorderLayout.CENTER); + rightSide.add(activityField, BorderLayout.CENTER); + rightSide.add(pingField, BorderLayout.EAST); + + add(leftSide, BorderLayout.WEST); + add(rightSide, BorderLayout.CENTER); + } + + void setFavoriteMenu(boolean favorite) + { + String favoriteAction = favorite ? + "Remove " + world.getId() + " from favorites" : + "Add " + world.getId() + " to favorites"; + + favoriteMenuOption.setText(favoriteAction); + + for (ActionListener listener : favoriteMenuOption.getActionListeners()) + { + favoriteMenuOption.removeActionListener(listener); + } + + favoriteMenuOption.addActionListener(e -> + { + onFavorite.accept(world, !favorite); + }); + } + + void updatePlayerCount(int playerCount) + { + this.updatedPlayerCount = playerCount; + playerCountField.setText(playerCountString(playerCount)); + } + + private static String playerCountString(int playerCount) + { + return playerCount < 0 ? "OFF" : Integer.toString(playerCount); + } + + void setPing(int ping) + { + this.ping = ping; + pingField.setText(ping <= 0 ? "-" : Integer.toString(ping)); + } + + void hidePing() + { + pingField.setText("-"); + } + + void showPing() + { + setPing(ping); // to update pingField + } + + int getPing() + { + return ping; + } + + public void recolour(boolean current) + { + playerCountField.setForeground(current ? CURRENT_WORLD : Color.WHITE); + pingField.setForeground(current ? CURRENT_WORLD : Color.WHITE); + + if (current) + { + activityField.setForeground(CURRENT_WORLD); + worldField.setForeground(CURRENT_WORLD); + return; + } + else if (world.getTypes().contains(WorldType.PVP) + || world.getTypes().contains(WorldType.HIGH_RISK) + || world.getTypes().contains(WorldType.DEADMAN)) + { + activityField.setForeground(DANGEROUS_WORLD); + } + else if (world.getTypes().contains(WorldType.SEASONAL)) + { + activityField.setForeground(SEASONAL_WORLD); + } + else if (world.getTypes().contains(WorldType.NOSAVE_MODE)) + { + activityField.setForeground(TOURNAMENT_WORLD); + } + else + { + activityField.setForeground(Color.WHITE); + } + + worldField.setForeground(world.getTypes().contains(WorldType.MEMBERS) ? MEMBERS_WORLD : FREE_WORLD); + } + + /** + * Builds the players list field (containing the amount of players logged in that world). + */ + private JPanel buildPlayersField() + { + JPanel column = new JPanel(new BorderLayout()); + column.setBorder(new EmptyBorder(0, 5, 0, 5)); + + playerCountField = new JLabel(playerCountString(world.getPlayers())); + playerCountField.setFont(FontManager.getRunescapeSmallFont()); + + column.add(playerCountField, BorderLayout.WEST); + + return column; + } + + private JPanel buildPingField(Integer ping) + { + JPanel column = new JPanel(new BorderLayout()); + column.setBorder(new EmptyBorder(0, 5, 0, 5)); + + pingField = new JLabel("-"); + pingField.setFont(FontManager.getRunescapeSmallFont()); + + column.add(pingField, BorderLayout.EAST); + + if (ping != null) + { + setPing(ping); + } + + return column; + } + + /** + * Builds the activity list field (containing that world's activity/theme). + */ + private JPanel buildActivityField() + { + JPanel column = new JPanel(new BorderLayout()); + column.setBorder(new EmptyBorder(0, 5, 0, 5)); + + String activity = world.getActivity(); + activityField = new JLabel(activity); + activityField.setFont(FontManager.getRunescapeSmallFont()); + if (activity != null && activity.length() > 16) + { + activityField.setToolTipText(activity); + // Pass up events - https://stackoverflow.com/a/14932443 + activityField.addMouseListener(new MouseAdapter() + { + @Override + public void mouseClicked(MouseEvent e) + { + dispatchEvent(e); + } + + @Override + public void mousePressed(MouseEvent e) + { + dispatchEvent(e); + } + + @Override + public void mouseReleased(MouseEvent e) + { + dispatchEvent(e); + } + + @Override + public void mouseEntered(MouseEvent e) + { + dispatchEvent(e); + } + + @Override + public void mouseExited(MouseEvent e) + { + dispatchEvent(e); + } + }); + } + + column.add(activityField, BorderLayout.WEST); + + return column; + } + + /** + * Builds the world list field (containing the country's flag and the world index). + */ + private JPanel buildWorldField() + { + JPanel column = new JPanel(new BorderLayout(7, 0)); + column.setBorder(new EmptyBorder(0, 5, 0, 5)); + + worldField = new JLabel(world.getId() + ""); + + ImageIcon flagIcon = getFlag(world.getRegion()); + if (flagIcon != null) + { + JLabel flag = new JLabel(flagIcon); + column.add(flag, BorderLayout.WEST); + } + column.add(worldField, BorderLayout.CENTER); + + return column; + } + + private static ImageIcon getFlag(WorldRegion region) + { + if (region == null) + { + return null; + } + + switch (region) + { + case UNITED_STATES_OF_AMERICA: + return FLAG_US; + case UNITED_KINGDOM: + return FLAG_UK; + case AUSTRALIA: + return FLAG_AUS; + case GERMANY: + return FLAG_GER; + default: + return null; + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/MiningSiteLocation.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/MiningSiteLocation.java index b683414722..85fef484b9 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/MiningSiteLocation.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/MiningSiteLocation.java @@ -61,6 +61,8 @@ enum MiningSiteLocation BLAST_MINE_WEST(new WorldPoint(1471, 3865, 0), new Rock(22, Ore.HARD_ROCK)), BRIMHAVEN_NORTH(new WorldPoint(2732, 3225, 0), new Rock(10, Ore.GOLD)), BRIMHAVEN_SOUTH_(new WorldPoint(2743, 3150, 0), new Rock(6, Ore.GOLD)), + CAMDOZAAL_MINES_EAST(new WorldPoint(2934, 5811, 0), new Rock(8, Ore.BARRONITE), new Rock(1, Ore.CLAY), new Rock(2, Ore.TIN), new Rock(1, Ore.COPPER)), + CAMDOZAAL_MINES_WEST(new WorldPoint(2914, 5811, 0), new Rock(10, Ore.BARRONITE), new Rock(2, Ore.COPPER), new Rock(2, Ore.CLAY), new Rock(1, Ore.TIN)), CENTRAL_FREMENIK_ISLES(new WorldPoint(2374, 3850, 0), new Rock(7, Ore.COAL), new Rock(1, Ore.RUNITE)), CITHAREDE_ABBEY(new WorldPoint(3400, 3170, 0), new Rock(3, Ore.IRON), new Rock (3, Ore.COAL)), COAL_TRUCKS(new WorldPoint(2580, 3484, 0), new Rock(18, Ore.COAL)), @@ -238,6 +240,7 @@ enum MiningSiteLocation TIN("Tin"), LIMESTONE("Limestone"), BLURITE("Blurite"), + BARRONITE("Barronite"), IRON("Iron"), ELEMENTAL("Elemental"), SILVER("Silver"), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xpglobes/XpGlobesOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/xpglobes/XpGlobesOverlay.java index 526d3aacbc..1243c76712 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xpglobes/XpGlobesOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xpglobes/XpGlobesOverlay.java @@ -63,6 +63,7 @@ public class XpGlobesOverlay extends Overlay private static final int MINIMUM_STEP = 10; private static final int PROGRESS_RADIUS_START = 90; private static final int PROGRESS_RADIUS_REMAINDER = 0; + private static final int PROGRESS_BACKGROUND_SIZE = 5; private static final int TOOLTIP_RECT_SIZE_X = 150; private static final Color DARK_OVERLAY_COLOR = new Color(0, 0, 0, 180); static final String FLIP_ACTION = "Flip"; @@ -108,31 +109,34 @@ public class XpGlobesOverlay extends Overlay return null; } - int curDrawPosition = 0; + // The progress arc is drawn either side of the perimeter of the background. This value accounts for that + // when calculating draw positions and overall size of the overlay + final int progressArcOffset = (int) Math.ceil(Math.max(PROGRESS_BACKGROUND_SIZE, config.progressArcStrokeWidth()) / 2.0); + int curDrawPosition = progressArcOffset; for (final XpGlobe xpGlobe : xpGlobes) { int startXp = xpTrackerService.getStartGoalXp(xpGlobe.getSkill()); int goalXp = xpTrackerService.getEndGoalXp(xpGlobe.getSkill()); if (config.alignOrbsVertically()) { - renderProgressCircle(graphics, xpGlobe, startXp, goalXp, 0, curDrawPosition, getBounds()); + renderProgressCircle(graphics, xpGlobe, startXp, goalXp, progressArcOffset, curDrawPosition, getBounds()); } else { - renderProgressCircle(graphics, xpGlobe, startXp, goalXp, curDrawPosition, 0, getBounds()); + renderProgressCircle(graphics, xpGlobe, startXp, goalXp, curDrawPosition, progressArcOffset, getBounds()); } curDrawPosition += MINIMUM_STEP + config.xpOrbSize(); } // Get length of markers - final int markersLength = (queueSize * (config.xpOrbSize())) + ((MINIMUM_STEP) * (queueSize - 1)); + final int markersLength = (queueSize * (config.xpOrbSize() + progressArcOffset)) + ((MINIMUM_STEP) * (queueSize - 1)); if (config.alignOrbsVertically()) { - return new Dimension(config.xpOrbSize(), markersLength); + return new Dimension(config.xpOrbSize() + progressArcOffset * 2, markersLength); } else { - return new Dimension(markersLength, config.xpOrbSize()); + return new Dimension(markersLength, config.xpOrbSize() + progressArcOffset * 2); } } @@ -184,7 +188,7 @@ public class XpGlobesOverlay extends Overlay x, y, config.xpOrbSize(), config.xpOrbSize(), PROGRESS_RADIUS_REMAINDER, radiusToGoalXp, - 5, + PROGRESS_BACKGROUND_SIZE, config.progressOrbOutLineColor() ); drawProgressArc( diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBox.java b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBox.java index 5d41b055c6..dbcfd6ddbd 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBox.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBox.java @@ -50,7 +50,6 @@ import lombok.Getter; import net.runelite.api.Client; import net.runelite.api.Experience; import net.runelite.api.Skill; -import net.runelite.api.WorldType; import net.runelite.client.game.SkillIconManager; import net.runelite.client.ui.ColorScheme; import net.runelite.client.ui.DynamicGridLayout; @@ -125,7 +124,7 @@ class XpInfoBox extends JPanel // Create open xp tracker menu final JMenuItem openXpTracker = new JMenuItem("Open Wise Old Man"); openXpTracker.addActionListener(e -> LinkBrowser.browse(XpPanel.buildXpTrackerUrl( - client.getLocalPlayer(), skill, client.getWorldType().contains(WorldType.LEAGUE)))); + client.getLocalPlayer(), skill))); // Create reset menu final JMenuItem reset = new JMenuItem("Reset"); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpPanel.java index b346f2733d..ed72128ef4 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpPanel.java @@ -41,7 +41,6 @@ import javax.swing.border.EmptyBorder; import net.runelite.api.Actor; import net.runelite.api.Client; import net.runelite.api.Skill; -import net.runelite.api.WorldType; import net.runelite.client.game.SkillIconManager; import net.runelite.client.ui.ColorScheme; import net.runelite.client.ui.FontManager; @@ -84,7 +83,7 @@ class XpPanel extends PluginPanel // Create open xp tracker menu final JMenuItem openXpTracker = new JMenuItem("Open Wise Old Man"); openXpTracker.addActionListener(e -> LinkBrowser.browse(XpPanel.buildXpTrackerUrl( - client.getLocalPlayer(), Skill.OVERALL, client.getWorldType().contains(WorldType.LEAGUE)))); + client.getLocalPlayer(), Skill.OVERALL))); // Create reset all menu final JMenuItem reset = new JMenuItem("Reset All"); @@ -147,18 +146,16 @@ class XpPanel extends PluginPanel add(errorPanel); } - static String buildXpTrackerUrl(final Actor player, final Skill skill, boolean leagueWorld) + static String buildXpTrackerUrl(final Actor player, final Skill skill) { if (player == null) { return ""; } - final String host = leagueWorld ? "trailblazer.wiseoldman.net" : "wiseoldman.net"; - return new HttpUrl.Builder() .scheme("https") - .host(host) + .host("wiseoldman.net") .addPathSegment("players") .addPathSegment(player.getName()) .addPathSegment("gained") diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpWorldType.java b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpWorldType.java index 245057e209..909a7de841 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpWorldType.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpWorldType.java @@ -70,12 +70,10 @@ enum XpWorldType { switch (type) { - case TOURNAMENT: + case NOSAVE_MODE: return TOURNEY; case DEADMAN: return DMM; - case LEAGUE: - return LEAGUE; default: return NORMAL; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xpupdater/XpUpdaterPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/xpupdater/XpUpdaterPlugin.java index 73f295ccaa..4595a9f722 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xpupdater/XpUpdaterPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xpupdater/XpUpdaterPlugin.java @@ -143,9 +143,9 @@ public class XpUpdaterPlugin extends Plugin private void updateCml(String username, EnumSet worldTypes) { if (config.cml() - && !worldTypes.contains(WorldType.LEAGUE) + && !worldTypes.contains(WorldType.SEASONAL) && !worldTypes.contains(WorldType.DEADMAN) - && !worldTypes.contains(WorldType.TOURNAMENT)) + && !worldTypes.contains(WorldType.NOSAVE_MODE)) { HttpUrl url = new HttpUrl.Builder() .scheme("https") @@ -168,9 +168,9 @@ public class XpUpdaterPlugin extends Plugin private void updateTempleosrs(String username, EnumSet worldTypes) { if (config.templeosrs() - && !worldTypes.contains(WorldType.LEAGUE) + && !worldTypes.contains(WorldType.SEASONAL) && !worldTypes.contains(WorldType.DEADMAN) - && !worldTypes.contains(WorldType.TOURNAMENT)) + && !worldTypes.contains(WorldType.NOSAVE_MODE)) { HttpUrl url = new HttpUrl.Builder() .scheme("https") @@ -192,9 +192,9 @@ public class XpUpdaterPlugin extends Plugin private void updateWom(String username, EnumSet worldTypes) { if (config.wiseoldman() - && !worldTypes.contains(WorldType.LEAGUE) + && !worldTypes.contains(WorldType.SEASONAL) && !worldTypes.contains(WorldType.DEADMAN) - && !worldTypes.contains(WorldType.TOURNAMENT)) + && !worldTypes.contains(WorldType.NOSAVE_MODE)) { HttpUrl url = new HttpUrl.Builder() .scheme("https") diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/Overlay.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/Overlay.java index 7bf9672c87..3886855a53 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/Overlay.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/Overlay.java @@ -129,10 +129,7 @@ public abstract class Overlay implements LayoutableRenderableEntity return null; } - public void reset() + public void revalidate() { - setPreferredPosition(null); - setPreferredSize(null); - setPreferredLocation(null); } } diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayManager.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayManager.java index 21cb834ca1..bea3f9d280 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayManager.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayManager.java @@ -289,8 +289,11 @@ public class OverlayManager */ public synchronized void resetOverlay(final Overlay overlay) { - overlay.reset(); + overlay.setPreferredPosition(null); + overlay.setPreferredSize(null); + overlay.setPreferredLocation(null); saveOverlay(overlay); + overlay.revalidate(); } synchronized void rebuildOverlayLayers() diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java index 3ed548a91f..c658c6944a 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java @@ -69,11 +69,14 @@ import net.runelite.client.ui.JagexColors; import net.runelite.client.ui.overlay.tooltip.Tooltip; import net.runelite.client.ui.overlay.tooltip.TooltipManager; import net.runelite.client.util.ColorUtil; +import org.slf4j.Marker; +import org.slf4j.MarkerFactory; @Singleton @Slf4j public class OverlayRenderer extends MouseAdapter implements KeyListener { + private static final Marker DEDUPLICATE = MarkerFactory.getMarker("DEDUPLICATE"); private static final int BORDER = 5; private static final int BORDER_TOP = BORDER + 15; private static final int PADDING = 2; @@ -289,25 +292,18 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener final Dimension dimension = bounds.getSize(); final Point preferredLocation = overlay.getPreferredLocation(); Point location; + Rectangle snapCorner = null; // If the final position is not modified, layout it if (overlayPosition != OverlayPosition.DETACHED && (preferredLocation == null || overlay.getPreferredPosition() != null)) { - final Rectangle snapCorner = snapCorners.forPosition(overlayPosition); + snapCorner = snapCorners.forPosition(overlayPosition); final Point translation = OverlayUtil.transformPosition(overlayPosition, dimension); // offset from corner // Target x/y to draw the overlay - int destX = (int) snapCorner.getX() + translation.x; - int destY = (int) snapCorner.getY() + translation.y; + int destX = snapCorner.x + translation.x; + int destY = snapCorner.y + translation.y; // Clamp the target position to ensure it is on screen or within parent bounds location = clampOverlayLocation(destX, destY, dimension.width, dimension.height, overlay); - // Diff final position to target position in order to add it to the snap corner padding. The - // overlay effectively takes up the difference of (clamped location - target location) in - // addition to its normal dimensions. - int dX = location.x - destX; - int dY = location.y - destY; - final Point padding = OverlayUtil.padPosition(overlayPosition, dimension, PADDING); // overlay size + fixed padding - // translate corner for padding and any difference due to the position clamping - snapCorner.translate(padding.x + dX, padding.y + dY); } else { @@ -324,6 +320,12 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener safeRender(client, overlay, layer, graphics, location); + // Adjust snap corner based on where the overlay was drawn + if (snapCorner != null && bounds.width + bounds.height > 0) + { + OverlayUtil.shiftSnapCorner(overlayPosition, snapCorner, bounds, PADDING); + } + // Restore graphics2d properties prior to drawing bounds graphics.setTransform(transform); graphics.setStroke(stroke); @@ -703,7 +705,7 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener { OverlayPosition position = snapCorners.fromBounds(snapCorner); - if (position == currentManagedOverlay.getPosition()) + if (position == getCorrectedOverlayPosition(currentManagedOverlay)) { // overlay moves back to default position position = null; @@ -711,6 +713,7 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener currentManagedOverlay.setPreferredPosition(position); currentManagedOverlay.setPreferredLocation(null); // from dragging + currentManagedOverlay.revalidate(); break; } } @@ -786,7 +789,7 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener } catch (Exception ex) { - log.warn("Error during overlay rendering", ex); + log.warn(DEDUPLICATE, "Error during overlay rendering", ex); return; } diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayUtil.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayUtil.java index 1caa3a7c01..26497ab43d 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayUtil.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayUtil.java @@ -30,6 +30,7 @@ import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Polygon; +import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.Shape; import java.awt.Stroke; @@ -201,33 +202,32 @@ public class OverlayUtil graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); } - public static java.awt.Point padPosition(OverlayPosition position, Dimension dimension, final int padding) + static void shiftSnapCorner(OverlayPosition overlayPosition, Rectangle snapCorner, Rectangle bounds, int padding) { - final java.awt.Point result = new java.awt.Point(); - - switch (position) + // translate corner for padding and also based on where the overlay bounds are now + int sX = snapCorner.x, sY = snapCorner.y; + switch (overlayPosition) { - case DYNAMIC: - case TOOLTIP: - break; case BOTTOM_LEFT: - result.x += dimension.width + (dimension.width == 0 ? 0 : padding); + sX = bounds.x + bounds.width + padding; break; case BOTTOM_RIGHT: - result.x -= dimension.width + (dimension.width == 0 ? 0 : padding); + sX = bounds.x - padding; break; case TOP_LEFT: case TOP_CENTER: case CANVAS_TOP_RIGHT: case TOP_RIGHT: - result.y += dimension.height + (dimension.height == 0 ? 0 : padding); + sY = bounds.y + bounds.height + padding; break; case ABOVE_CHATBOX_RIGHT: - result.y -= dimension.height + (dimension.height == 0 ? 0 : padding); + sY = bounds.y - padding; break; + default: + throw new IllegalArgumentException(); } - - return result; + snapCorner.x = sX; + snapCorner.y = sY; } public static java.awt.Point transformPosition(OverlayPosition position, Dimension dimension) diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/WidgetOverlay.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/WidgetOverlay.java index 67d20cf8bd..43a1faf32e 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/WidgetOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/WidgetOverlay.java @@ -121,9 +121,9 @@ public class WidgetOverlay extends Overlay assert widget != null; final Rectangle bounds = getBounds(); - // OverlayRenderer sets the overlay bounds to the preferred location if one is set prior to calling render() - // for detached overlays. - if (getPosition() != OverlayPosition.DETACHED || getPreferredLocation() != null) + // OverlayRenderer sets the overlay bounds to where it would like the overlay to render at prior to calling + // render(). If the overlay has a preferred location or position set we update the widget position to that. + if (getPreferredLocation() != null || getPreferredPosition() != null) { // The widget relative pos is relative to the parent widget.setRelativeX(bounds.x - parent.x); @@ -188,9 +188,8 @@ public class WidgetOverlay extends Overlay } @Override - public void reset() + public void revalidate() { - super.reset(); // Revalidate must be called on the client thread, so defer til next frame revalidate = true; } diff --git a/runelite-client/src/main/java/net/runelite/client/util/DeduplicationFilter.java b/runelite-client/src/main/java/net/runelite/client/util/DeduplicationFilter.java new file mode 100644 index 0000000000..2b99a27e97 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/util/DeduplicationFilter.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2021, Adam + * 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.util; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.turbo.TurboFilter; +import ch.qos.logback.core.spi.FilterReply; +import java.util.Deque; +import java.util.concurrent.ConcurrentLinkedDeque; +import lombok.EqualsAndHashCode; +import lombok.RequiredArgsConstructor; +import org.slf4j.Marker; +import org.slf4j.MarkerFactory; + +public class DeduplicationFilter extends TurboFilter +{ + private static final Marker deduplicateMarker = MarkerFactory.getMarker("DEDUPLICATE"); + private static final int CACHE_SIZE = 8; + private static final int DUPLICATE_LOG_COUNT = 1000; + + @RequiredArgsConstructor + @EqualsAndHashCode(exclude = {"count"}) + private static class LogException + { + private final String message; + private final StackTraceElement[] stackTraceElements; + private volatile int count; + } + + private final Deque cache = new ConcurrentLinkedDeque<>(); + + @Override + public void stop() + { + cache.clear(); + super.stop(); + } + + @Override + public FilterReply decide(Marker marker, Logger logger, Level level, String s, Object[] objects, Throwable throwable) + { + if (marker != deduplicateMarker || logger.isDebugEnabled() || throwable == null) + { + return FilterReply.NEUTRAL; + } + + LogException logException = new LogException(s, throwable.getStackTrace()); + for (LogException e : cache) + { + if (logException.equals(e)) + { + // this iinc is not atomic, but doesn't matter in practice + if (++e.count % DUPLICATE_LOG_COUNT == 0) + { + logger.warn("following log message logged " + DUPLICATE_LOG_COUNT + " times!"); + return FilterReply.NEUTRAL; + } + return FilterReply.DENY; + } + } + + synchronized (cache) + { + if (cache.size() >= CACHE_SIZE) + { + cache.pop(); + } + cache.push(logException); + } + + return FilterReply.NEUTRAL; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/util/MacOSPopupFactory.java b/runelite-client/src/main/java/net/runelite/client/util/MacOSPopupFactory.java new file mode 100644 index 0000000000..8e9f14551a --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/util/MacOSPopupFactory.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021, Adam + * 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.util; + +import javax.swing.PopupFactory; + +/** + * Dummy popup factory for Java 8 + */ +class MacOSPopupFactory extends PopupFactory +{ +} diff --git a/runelite-client/src/main/java/net/runelite/client/util/SwingUtil.java b/runelite-client/src/main/java/net/runelite/client/util/SwingUtil.java index d5b5ebd65e..22e46213e2 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/SwingUtil.java +++ b/runelite-client/src/main/java/net/runelite/client/util/SwingUtil.java @@ -51,6 +51,7 @@ import javax.swing.JButton; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; import javax.swing.LookAndFeel; +import javax.swing.PopupFactory; import javax.swing.SwingUtilities; import javax.swing.ToolTipManager; import javax.swing.UIManager; @@ -112,6 +113,14 @@ public class SwingUtil try { UIManager.setLookAndFeel(laf); + + if (OSType.getOSType() == OSType.MacOS) + { + // On MacOS Substance doesn't install its own popup factory, and the default one uses lightweight + // components unless the Aqua LAF is used. Lightweight components do not render correctly over AWT + // canvases on MacOS - so replace the popup factory one with that forces heavy components. + PopupFactory.setSharedInstance(new MacOSPopupFactory()); + } } catch (UnsupportedLookAndFeelException ex) { diff --git a/runelite-client/src/main/java11/net/runelite/client/util/MacOSPopupFactory.java b/runelite-client/src/main/java11/net/runelite/client/util/MacOSPopupFactory.java new file mode 100644 index 0000000000..62a91abed8 --- /dev/null +++ b/runelite-client/src/main/java11/net/runelite/client/util/MacOSPopupFactory.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021, Adam + * 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.util; + +import java.awt.Component; +import javax.swing.Popup; +import javax.swing.PopupFactory; + +/** + * Popup factory for Java 11 which forces heavyweight popups. Lightweight popups do not render correctly + * over AWT canvases on OSX. + */ +class MacOSPopupFactory extends PopupFactory +{ + @Override + protected Popup getPopup(Component owner, Component contents, int x, int y, boolean isHeavyWeightPopup) throws IllegalArgumentException + { + return super.getPopup(owner, contents, x, y, true); + } +} \ No newline at end of file diff --git a/runelite-client/src/main/resources/logback.xml b/runelite-client/src/main/resources/logback.xml index b92f056e96..db2cb318e4 100644 --- a/runelite-client/src/main/resources/logback.xml +++ b/runelite-client/src/main/resources/logback.xml @@ -24,6 +24,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --> + + %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/roofremoval/overrides.jsonc b/runelite-client/src/main/resources/net/runelite/client/plugins/roofremoval/overrides.jsonc index b831d41f43..656c4ae4dc 100644 --- a/runelite-client/src/main/resources/net/runelite/client/plugins/roofremoval/overrides.jsonc +++ b/runelite-client/src/main/resources/net/runelite/client/plugins/roofremoval/overrides.jsonc @@ -3260,5 +3260,15 @@ "z1": 1, "z2": 2 } + ], + "10290": [ // Ardougne Monastery + { + "rx1": 43, + "ry1": 17, + "rx2": 49, + "ry2": 17, + "z1": 0, + "z2": 0 + } ] } diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_cooking.json b/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_cooking.json index 6ddb07cbaf..8e86a25a65 100644 --- a/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_cooking.json +++ b/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_cooking.json @@ -78,6 +78,12 @@ "name": "Baked Potato", "xp": 15 }, + { + "level": 7, + "icon": 25654, + "name": "Guppy", + "xp": 12 + }, { "level": 8, "icon": 2048, @@ -228,6 +234,12 @@ "name": "Cup of tea", "xp": 52 }, + { + "level": 20, + "icon": 25660, + "name": "Cavefish", + "xp": 23 + }, { "level": 21, "icon": 9988, @@ -378,6 +390,12 @@ "name": "Choc Saturday", "xp": 170 }, + { + "level": 33, + "icon": 25666, + "name": "Tetra", + "xp": 31 + }, { "level": 34, "icon": 7178, @@ -516,6 +534,12 @@ "name": "Fried Mushrooms", "xp": 60 }, + { + "level": 46, + "icon": 25672, + "name": "Catfish", + "xp": 43 + }, { "level": 47, "icon": 7188, diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_fishing.json b/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_fishing.json index f55759fece..730be09d00 100644 --- a/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_fishing.json +++ b/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_fishing.json @@ -24,6 +24,12 @@ "name": "Raw Karambwanji", "xp": 5 }, + { + "level": 7, + "icon": 25652, + "name": "Raw Guppy", + "xp": 8 + }, { "level": 10, "icon": 345, @@ -48,6 +54,12 @@ "name": "Raw Trout", "xp": 50 }, + { + "level": 20, + "icon": 25658, + "name": "Raw Cavefish", + "xp": 16 + }, { "level": 23, "icon": 341, @@ -72,6 +84,12 @@ "name": "Raw Salmon", "xp": 70 }, + { + "level": 33, + "icon": 25664, + "name": "Raw Tetra", + "xp": 24 + }, { "level": 35, "icon": 359, @@ -102,6 +120,12 @@ "name": "Raw Bass", "xp": 100 }, + { + "level": 46, + "icon": 25670, + "name": "Raw Catfish", + "xp": 33 + }, { "level": 48, "icon": 11328, diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_mining.json b/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_mining.json index 728f204861..a944c4782f 100644 --- a/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_mining.json +++ b/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_mining.json @@ -36,6 +36,18 @@ "name": "Limestone", "xp": 26.5 }, + { + "level": 14, + "icon": 25683, + "name": "Barronite shards", + "xp": 16 + }, + { + "level": 14, + "icon": 25684, + "name": "Barronite deposit", + "xp": 32 + }, { "level": 15, "icon": 440, diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_prayer.json b/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_prayer.json index 2e74c93d0c..9ebde37563 100644 --- a/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_prayer.json +++ b/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_prayer.json @@ -11,6 +11,10 @@ { "name": "Chaos Altar (700%)", "value": 6 + }, + { + "name": "Morytania Diary 3 Shades(150%)", + "value": 0.5 } ], "actions": [ @@ -219,8 +223,7 @@ "level": 1, "icon": 3396, "name": "Loar Remains", - "xp": 33, - "ignoreBonus": true + "xp": 33 }, { "level": 1, @@ -274,8 +277,7 @@ "level": 1, "icon": 3398, "name": "Phrin Remains", - "xp": 46.5, - "ignoreBonus": true + "xp": 46.5 }, { "level": 1, @@ -287,8 +289,7 @@ "level": 1, "icon": 3400, "name": "Riyl Remains", - "xp": 59.5, - "ignoreBonus": true + "xp": 59.5 }, { "level": 1, @@ -312,8 +313,7 @@ "level": 1, "icon": 3402, "name": "Asyn Remains", - "xp": 82.5, - "ignoreBonus": true + "xp": 82.5 }, { "level": 1, @@ -325,8 +325,7 @@ "level": 1, "icon": 3404, "name": "Fiyr Remains", - "xp": 84, - "ignoreBonus": true + "xp": 84 }, { "level": 1, @@ -363,6 +362,36 @@ "icon": 22124, "name": "Superior Dragon Bones", "xp": 150 + }, + { + "level": 1, + "icon": 25419, + "name": "Urium Remains", + "xp": 120 + }, + { + "level": 1, + "icon": 25654, + "name": "Guppy", + "xp": 4 + }, + { + "level": 1, + "icon": 25660, + "name": "Cavefish", + "xp": 7 + }, + { + "level": 1, + "icon": 25666, + "name": "Tetra", + "xp": 10 + }, + { + "level": 1, + "icon": 25672, + "name": "Cavefish", + "xp": 16 } ] } diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_runecraft.json b/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_runecraft.json index 3e62d892f4..901196750e 100644 --- a/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_runecraft.json +++ b/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_runecraft.json @@ -102,6 +102,12 @@ "name": "Mind Rune", "xp": 5.5 }, + { + "level": 2, + "icon": 25696, + "name": "Mind core", + "xp": 55 + }, { "level": 5, "icon": 555, @@ -156,6 +162,12 @@ "name": "Body Rune", "xp": 7.5 }, + { + "level": 20, + "icon": 25698, + "name": "Body core", + "xp": 75 + }, { "level": 23, "icon": 4699, @@ -174,6 +186,12 @@ "name": "Chaos Rune", "xp": 8.5 }, + { + "level": 35, + "icon": 25700, + "name": "Chaos core", + "xp": 85 + }, { "level": 40, "icon": 9075, diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_smithing.json b/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_smithing.json index adce0a7faf..bf829f53b6 100644 --- a/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_smithing.json +++ b/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_smithing.json @@ -156,6 +156,12 @@ "name": "Bronze 2h Sword", "xp": 37.5 }, + { + "level": 14, + "icon": 25684, + "name": "Barronite deposits", + "xp": 30 + }, { "level": 15, "icon": 2351, diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java index 1162e83edb..ceeaa0d32e 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java @@ -1451,11 +1451,11 @@ public abstract class RSClientMixin implements RSClient "|MenuAction|: MenuOption={} MenuTarget={} Id={} Opcode={}/{} Param0={} Param1={} CanvasX={} CanvasY={}", menuOptionClicked.getMenuOption(), menuOptionClicked.getMenuTarget(), menuOptionClicked.getId(), menuOptionClicked.getMenuAction(), opcode + (decremented ? 2000 : 0), - menuOptionClicked.getActionParam(), menuOptionClicked.getWidgetId(), canvasX, canvasY + menuOptionClicked.getParam0(), menuOptionClicked.getParam1(), canvasX, canvasY ); } - copy$menuAction(menuOptionClicked.getActionParam(), menuOptionClicked.getWidgetId(), + copy$menuAction(menuOptionClicked.getParam0(), menuOptionClicked.getParam1(), menuOptionClicked.getMenuAction() == UNKNOWN ? opcode : menuOptionClicked.getMenuAction().getId(), menuOptionClicked.getId(), menuOptionClicked.getMenuOption(), menuOptionClicked.getMenuTarget(), canvasX, canvasY); diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSModelDataMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSModelDataMixin.java index 36a55fcdd4..40ade7bb30 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSModelDataMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSModelDataMixin.java @@ -41,10 +41,7 @@ public abstract class RSModelDataMixin implements RSModelData private static RSClient client; @Inject - private float[][] faceTextureUCoordinates; - - @Inject - private float[][] faceTextureVCoordinates; + private float[] faceTextureUVCoordinates; @Copy("toModel") @Replace("toModel") @@ -59,14 +56,13 @@ public abstract class RSModelDataMixin implements RSModelData return null; } - if (faceTextureUCoordinates == null) + if (faceTextureUVCoordinates == null) { computeTextureUVCoordinates(); } RSModel rsModel = (RSModel) model; - rsModel.setFaceTextureUCoordinates(faceTextureUCoordinates); - rsModel.setFaceTextureVCoordinates(faceTextureVCoordinates); + rsModel.setFaceTextureUVCoordinates(faceTextureUVCoordinates); return model; } @@ -94,40 +90,35 @@ public abstract class RSModelDataMixin implements RSModelData final byte[] textureCoords = getTextureCoords(); int faceCount = getTriangleFaceCount(); - this.faceTextureUCoordinates = new float[faceCount][]; - this.faceTextureVCoordinates = new float[faceCount][]; + float[] faceTextureUCoordinates = new float[faceCount * 6]; for (int i = 0; i < faceCount; i++) { int trianglePointX = trianglePointsX[i]; int trianglePointY = trianglePointsY[i]; int trianglePointZ = trianglePointsZ[i]; - int textureCoordinate = textureCoords != null && textureCoords[i] != -1 ? textureCoords[i] & 255 : -1; - short textureIdx; - textureIdx = faceTextures[i]; + short textureIdx = faceTextures[i]; if (textureIdx != -1) { - float[] u = new float[3]; - float[] v = new float[3]; - int triangleVertexIdx1; int triangleVertexIdx2; int triangleVertexIdx3; - if (textureCoordinate == -1) + if (textureCoords != null && textureCoords[i] != -1) + { + int textureCoordinate = textureCoords[i] & 255; + triangleVertexIdx1 = texTriangleX[textureCoordinate]; + triangleVertexIdx2 = texTriangleY[textureCoordinate]; + triangleVertexIdx3 = texTriangleZ[textureCoordinate]; + } + else { triangleVertexIdx1 = trianglePointX; triangleVertexIdx2 = trianglePointY; triangleVertexIdx3 = trianglePointZ; } - else - { - triangleVertexIdx1 = texTriangleX[textureCoordinate]; - triangleVertexIdx2 = texTriangleY[textureCoordinate]; - triangleVertexIdx3 = texTriangleZ[textureCoordinate]; - } float triangleX = (float) vertexPositionsX[triangleVertexIdx1]; float triangleY = (float) vertexPositionsY[triangleVertexIdx1]; @@ -157,22 +148,29 @@ public abstract class RSModelDataMixin implements RSModelData float f_902_ = f_885_ * f_898_ - f_886_ * f_897_; float f_903_ = 1.0F / (f_900_ * f_882_ + f_901_ * f_883_ + f_902_ * f_884_); - u[0] = (f_900_ * f_888_ + f_901_ * f_889_ + f_902_ * f_890_) * f_903_; - u[1] = (f_900_ * f_891_ + f_901_ * f_892_ + f_902_ * f_893_) * f_903_; - u[2] = (f_900_ * f_894_ + f_901_ * f_895_ + f_902_ * f_896_) * f_903_; + float u0 = (f_900_ * f_888_ + f_901_ * f_889_ + f_902_ * f_890_) * f_903_; + float u1 = (f_900_ * f_891_ + f_901_ * f_892_ + f_902_ * f_893_) * f_903_; + float u2 = (f_900_ * f_894_ + f_901_ * f_895_ + f_902_ * f_896_) * f_903_; f_900_ = f_883_ * f_899_ - f_884_ * f_898_; f_901_ = f_884_ * f_897_ - f_882_ * f_899_; f_902_ = f_882_ * f_898_ - f_883_ * f_897_; f_903_ = 1.0F / (f_900_ * f_885_ + f_901_ * f_886_ + f_902_ * f_887_); - v[0] = (f_900_ * f_888_ + f_901_ * f_889_ + f_902_ * f_890_) * f_903_; - v[1] = (f_900_ * f_891_ + f_901_ * f_892_ + f_902_ * f_893_) * f_903_; - v[2] = (f_900_ * f_894_ + f_901_ * f_895_ + f_902_ * f_896_) * f_903_; + float v0 = (f_900_ * f_888_ + f_901_ * f_889_ + f_902_ * f_890_) * f_903_; + float v1 = (f_900_ * f_891_ + f_901_ * f_892_ + f_902_ * f_893_) * f_903_; + float v2 = (f_900_ * f_894_ + f_901_ * f_895_ + f_902_ * f_896_) * f_903_; - this.faceTextureUCoordinates[i] = u; - this.faceTextureVCoordinates[i] = v; + int idx = i * 6; + faceTextureUCoordinates[idx] = u0; + faceTextureUCoordinates[idx + 1] = v0; + faceTextureUCoordinates[idx + 2] = u1; + faceTextureUCoordinates[idx + 3] = v1; + faceTextureUCoordinates[idx + 4] = u2; + faceTextureUCoordinates[idx + 5] = v2; } } + + this.faceTextureUVCoordinates = faceTextureUCoordinates; } } \ No newline at end of file diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSModelMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSModelMixin.java index a81e8c6092..e3e41629e0 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSModelMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSModelMixin.java @@ -61,51 +61,36 @@ public abstract class RSModelMixin implements RSModel private int rl$uvBufferOffset; @Inject - private float[][] rl$faceTextureUCoordinates; - - @Inject - private float[][] rl$faceTextureVCoordinates; + private float[] rl$faceTextureUVCoordinates; @MethodHook(value = "", end = true) @Inject public void rl$init(RSModel[] models, int length) { - int count = 0; - for (int i = 0; i < length; ++i) + if (this.getFaceTextures() != null) { - RSModel model = models[i]; - if (model != null) + int count = this.getTrianglesCount(); + float[] uv = new float[count * 6]; + int idx = 0; + + for (int i = 0; i < length; ++i) { - count += model.getTrianglesCount(); - } - } - - float[][] u = new float[count][]; - float[][] v = new float[count][]; - int idx = 0; - - for (int i = 0; i < length; ++i) - { - RSModel model = models[i]; - if (model != null) - { - float[][] modelU = model.getFaceTextureUCoordinates(); - float[][] modelV = model.getFaceTextureVCoordinates(); - - for (int j = 0; j < model.getTrianglesCount(); ++j) + RSModel model = models[i]; + if (model != null) { - if (modelU != null && modelV != null) + float[] modelUV = model.getFaceTextureUVCoordinates(); + + if (modelUV != null) { - u[idx] = modelU[j]; - v[idx] = modelV[j]; + System.arraycopy(modelUV, 0, uv, idx, model.getTrianglesCount() * 6); } - ++idx; + + idx += model.getTrianglesCount() * 6; } } - } - setFaceTextureUCoordinates(u); - setFaceTextureVCoordinates(v); + setFaceTextureUVCoordinates(uv); + } } @Override @@ -169,8 +154,7 @@ public abstract class RSModelMixin implements RSModel if (model != null && model != this) { RSModel rsModel = (RSModel) model; - rsModel.setFaceTextureUCoordinates(rl$faceTextureUCoordinates); - rsModel.setFaceTextureVCoordinates(rl$faceTextureVCoordinates); + rsModel.setFaceTextureUVCoordinates(rl$faceTextureUVCoordinates); } return model; } @@ -192,8 +176,7 @@ public abstract class RSModelMixin implements RSModel { // Animated models are usually a shared Model instance that is global RSModel rsModel = (RSModel) sharedModel; - rsModel.setFaceTextureUCoordinates(rl$faceTextureUCoordinates); - rsModel.setFaceTextureVCoordinates(rl$faceTextureVCoordinates); + rsModel.setFaceTextureUVCoordinates(rl$faceTextureUVCoordinates); } @Inject @@ -385,29 +368,15 @@ public abstract class RSModelMixin implements RSModel @Inject @Override - public float[][] getFaceTextureUCoordinates() + public float[] getFaceTextureUVCoordinates() { - return rl$faceTextureUCoordinates; + return rl$faceTextureUVCoordinates; } @Inject @Override - public void setFaceTextureUCoordinates(float[][] faceTextureUCoordinates) + public void setFaceTextureUVCoordinates(float[] faceTextureUVCoordinates) { - this.rl$faceTextureUCoordinates = faceTextureUCoordinates; - } - - @Inject - @Override - public float[][] getFaceTextureVCoordinates() - { - return rl$faceTextureVCoordinates; - } - - @Inject - @Override - public void setFaceTextureVCoordinates(float[][] faceTextureVCoordinates) - { - this.rl$faceTextureVCoordinates = faceTextureVCoordinates; + this.rl$faceTextureUVCoordinates = faceTextureUVCoordinates; } } \ No newline at end of file diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSNPCMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSNPCMixin.java index 0c47ce539a..aca1512718 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSNPCMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSNPCMixin.java @@ -24,6 +24,7 @@ */ package net.runelite.mixins; +import java.awt.Polygon; import java.awt.Shape; import net.runelite.api.AnimationID; import net.runelite.api.NPCComposition; @@ -169,6 +170,22 @@ public abstract class RSNPCMixin implements RSNPC return composition; } + @Inject + @Override + public Polygon getCanvasTilePoly() + { + NPCComposition transformedComposition = this.getTransformedComposition(); + if (transformedComposition == null) + { + return null; + } + else + { + int size = transformedComposition.getSize(); + return Perspective.getCanvasTileAreaPoly(client, this.getLocalLocation(), size); + } + } + @Inject @Override public Shape getConvexHull() diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSModel.java b/runescape-api/src/main/java/net/runelite/rs/api/RSModel.java index bb17d2c718..8a3751d858 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSModel.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSModel.java @@ -169,9 +169,6 @@ public interface RSModel extends RSRenderable, Model */ Shape getConvexHull(int localX, int localY, int orientation, int tileHeight); - float[][] getFaceTextureUCoordinates(); - void setFaceTextureUCoordinates(float[][] rl$faceTextureUCoordinates); - - float[][] getFaceTextureVCoordinates(); - void setFaceTextureVCoordinates(float[][] rl$faceTextureVCoordinates); + float[] getFaceTextureUVCoordinates(); + void setFaceTextureUVCoordinates(float[] rl$faceTextureUVCoordinates); }