diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangeConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangeConfig.java index 3294f9d6b4..2dc8eed80f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangeConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangeConfig.java @@ -56,15 +56,4 @@ public interface GrandExchangeConfig extends Config { return true; } - - @ConfigItem( - position = 3, - keyName = "notificationDelay", - name = "Notification Delay", - description = "Number of seconds between notifications on offer updates" - ) - default int notificationDelay() - { - return 5; - } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangeNotification.java b/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangeNotification.java deleted file mode 100644 index 48e281959d..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangeNotification.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2018, Ethan - * 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.grandexchange; - -import java.time.Instant; -import lombok.Value; -import net.runelite.api.GrandExchangeOfferState; - -@Value -class GrandExchangeNotification -{ - private final int slot; - private final int quantitySold; - private final int totalQuantity; - private final String itemName; - private final GrandExchangeOfferState state; - private final Instant insertedOn = Instant.now(); - - String getNotificationMessage() - { - // Send complete or X/Y notification - switch (this.state) - { - case BUYING: - return String.format("Grand Exchange: Bought %d / %d x %s", quantitySold, totalQuantity, itemName); - - case SELLING: - return String.format("Grand Exchange: Sold %d / %d x %s", quantitySold, totalQuantity, itemName); - - case BOUGHT: - return String.format("Grand Exchange: Finished buying %d x %s", totalQuantity, itemName); - - case SOLD: - return String.format("Grand Exchange: Finished selling %d x %s", totalQuantity, itemName); - - default: - // Not possible - return null; - } - } -} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangeNotificationHandler.java b/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangeNotificationHandler.java deleted file mode 100644 index e9714ddea4..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangeNotificationHandler.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2018, Ethan - * 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.grandexchange; - -import java.time.Duration; -import java.time.Instant; -import java.util.LinkedList; -import javax.inject.Inject; -import javax.inject.Singleton; -import net.runelite.api.GrandExchangeOffer; -import net.runelite.api.GrandExchangeOfferState; -import net.runelite.api.ItemComposition; - -@Singleton -class GrandExchangeNotificationHandler -{ - @Inject - private GrandExchangeConfig config; - - private final LinkedList notificationQueue = new LinkedList<>(); - - private Instant lastNotificationSent = Instant.now(); - - void queueNotification(int slot, ItemComposition offerItem, GrandExchangeOffer newOffer) - { - // Get offer data - int itemId = offerItem.getId(); - int quantitySold = newOffer.getQuantitySold(); - int totalQuantity = newOffer.getTotalQuantity(); - String itemName = offerItem.getName(); - - // Ignore empty/cancelled offers, or those with invalid data - if (newOffer.getState() == GrandExchangeOfferState.EMPTY || - newOffer.getState() == GrandExchangeOfferState.CANCELLED_BUY || - newOffer.getState() == GrandExchangeOfferState.CANCELLED_SELL || - quantitySold == 0 || itemId == 0 || itemId == -1) - { - return; - } - - // Inspect the queue for an existing notification from the same offer slot - for (GrandExchangeNotification existingNotification : notificationQueue) - { - if (existingNotification.getSlot() == slot) - { - // Don't replace a "finished" notification with a "in-progress" one - if (existingNotification.getState() == GrandExchangeOfferState.BOUGHT || - existingNotification.getState() == GrandExchangeOfferState.SOLD) - { - return; - } - - // Remove the "in-progress" notification so we can replace it with a "finished" one - notificationQueue.remove(existingNotification); - break; - } - } - - // If not, just add a new notification to the queue - notificationQueue.add(new GrandExchangeNotification(slot, quantitySold, totalQuantity, itemName, newOffer.getState())); - } - - boolean canSendNotification() - { - // Can't send a notification if none are in the queue - if (notificationQueue.isEmpty()) - { - return false; - } - - // Make sure we aren't sending notifications too quickly - long timeSinceLastNotification = Duration.between(this.lastNotificationSent, Instant.now()).toMillis(); - boolean canSendNotification = timeSinceLastNotification > (this.config.notificationDelay() * 1000); - - // Make sure the next notification has been given time to update to a complete status if it instantly bought/sold - boolean notificationAvailable = Duration.between(notificationQueue.peek().getInsertedOn(), Instant.now()).toMillis() > 600; - return canSendNotification && notificationAvailable; - } - - String getNextNotification() - { - // Reset the notification timer - this.lastNotificationSent = Instant.now(); - - // Get the next notification, remove it from the queue - GrandExchangeNotification nextNotification = notificationQueue.pop(); - - // Return the notification - return nextNotification.getNotificationMessage(); - } -} 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 42657140e5..8cbf90ad9b 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 @@ -37,15 +37,17 @@ import javax.swing.SwingUtilities; import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.ChatMessageType; import net.runelite.api.Client; import net.runelite.api.GameState; import net.runelite.api.GrandExchangeOffer; import net.runelite.api.ItemComposition; import net.runelite.api.MenuEntry; +import net.runelite.api.events.ChatMessage; import net.runelite.api.events.ConfigChanged; import net.runelite.api.events.FocusChanged; import net.runelite.api.events.GameStateChanged; -import net.runelite.api.events.GameTick; import net.runelite.api.events.GrandExchangeOfferChanged; import net.runelite.api.events.MenuEntryAdded; import net.runelite.api.widgets.WidgetID; @@ -59,10 +61,12 @@ import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.ui.NavigationButton; import net.runelite.client.ui.PluginToolbar; +import net.runelite.client.util.Text; @PluginDescriptor( name = "Grand Exchange" ) +@Slf4j public class GrandExchangePlugin extends Plugin { @Getter(AccessLevel.PACKAGE) @@ -99,9 +103,6 @@ public class GrandExchangePlugin extends Plugin @Inject private Notifier notifier; - @Inject - private GrandExchangeNotificationHandler notificationHandler; - @Provides GrandExchangeConfig provideConfig(ConfigManager configManager) { @@ -172,32 +173,21 @@ public class GrandExchangePlugin extends Plugin boolean shouldStack = offerItem.isStackable() || offer.getTotalQuantity() > 1; BufferedImage itemImage = itemManager.getImage(offer.getItemId(), offer.getTotalQuantity(), shouldStack); SwingUtilities.invokeLater(() -> panel.getOffersPanel().updateOffer(offerItem, itemImage, offerEvent.getOffer(), offerEvent.getSlot())); - this.queueNotification(offerItem, offerEvent.getOffer(), offerEvent.getSlot()); } - private void queueNotification(ItemComposition offerItem, GrandExchangeOffer newOffer, int slot) + @Subscribe + public void onChatMessage(ChatMessage event) { - if (!this.config.enableNotifications()) + if (!this.config.enableNotifications() || event.getType() != ChatMessageType.SERVER) { return; } - // Queue a notification - this.notificationHandler.queueNotification(slot, offerItem, newOffer); - } + String message = Text.removeTags(event.getMessage()); - @Subscribe - public void onTick(GameTick tick) - { - // Send a notification is the handler and a notification are available - if (this.notificationHandler.canSendNotification()) + if (message.startsWith("Grand Exchange:")) { - // Get the next notification and send it - String notification = this.notificationHandler.getNextNotification(); - if (notification != null) - { - this.notifier.notify(notification); - } + this.notifier.notify(message); } }