ge plugin: add OSB actively traded price

This commit is contained in:
AeonLucid
2018-06-15 23:33:30 +02:00
committed by Adam
parent b85fb80fe8
commit abcc733c9e
11 changed files with 551 additions and 1 deletions

View File

@@ -0,0 +1,69 @@
/*
* Copyright (c) 2018, AeonLucid <https://github.com/AeonLucid>
* 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.http.api.osbuddy;
import com.google.gson.JsonParseException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import lombok.extern.slf4j.Slf4j;
import net.runelite.http.api.RuneLiteAPI;
import okhttp3.HttpUrl;
import okhttp3.Request;
import okhttp3.Response;
@Slf4j
public class GrandExchangeClient
{
public GrandExchangeResult lookupItem(int itemId) throws IOException
{
final HttpUrl url = RuneLiteAPI.getApiBase().newBuilder()
.addPathSegment("osb")
.addPathSegment("ge")
.addQueryParameter("itemId", Integer.toString(itemId))
.build();
log.debug("Built URI: {}", url);
final Request request = new Request.Builder()
.url(url)
.build();
try (final Response response = RuneLiteAPI.CLIENT.newCall(request).execute())
{
if (!response.isSuccessful())
{
throw new IOException("Error looking up item id: " + response.message());
}
final InputStream in = response.body().byteStream();
return RuneLiteAPI.GSON.fromJson(new InputStreamReader(in), GrandExchangeResult.class);
}
catch (JsonParseException ex)
{
throw new IOException(ex);
}
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) 2018, AeonLucid <https://github.com/AeonLucid>
* 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.http.api.osbuddy;
import java.time.Instant;
import lombok.Data;
@Data
public class GrandExchangeResult
{
private int item_id;
private int buy_average;
private int sell_average;
private int overall_average;
private Instant last_update;
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright (c) 2018, AeonLucid <https://github.com/AeonLucid>
* 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.http.service.osbuddy;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.CacheControl;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/osb/ge")
public class GrandExchangeController
{
private final GrandExchangeService grandExchangeService;
@Autowired
public GrandExchangeController(GrandExchangeService grandExchangeService)
{
this.grandExchangeService = grandExchangeService;
}
@RequestMapping
public ResponseEntity<GrandExchangeEntry> get(@RequestParam("itemId") int itemId) throws ExecutionException
{
GrandExchangeEntry grandExchangeEntry = grandExchangeService.get(itemId);
return ResponseEntity.ok()
.cacheControl(CacheControl.maxAge(30, TimeUnit.MINUTES).cachePublic())
.body(grandExchangeEntry);
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) 2018, AeonLucid <https://github.com/AeonLucid>
* 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.http.service.osbuddy;
import java.time.Instant;
import lombok.Data;
@Data
class GrandExchangeEntry
{
private int item_id;
private int buy_average;
private int sell_average;
private int overall_average;
private Instant last_update;
}

View File

@@ -0,0 +1,119 @@
/*
* Copyright (c) 2018, AeonLucid <https://github.com/AeonLucid>
* 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.http.service.osbuddy;
import java.io.IOException;
import java.sql.Timestamp;
import java.time.Instant;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import net.runelite.http.service.osbuddy.beans.OsbuddySummaryItem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.sql2o.Connection;
import org.sql2o.Query;
import org.sql2o.Sql2o;
@Service
@Slf4j
public class GrandExchangeService
{
private static final String CREATE_GRAND_EXCHANGE_PRICES = "CREATE TABLE IF NOT EXISTS `osb_ge` (\n"
+ " `item_id` int(11) NOT NULL,\n"
+ " `buy_average` int(11) NOT NULL,\n"
+ " `sell_average` int(11) NOT NULL,\n"
+ " `overall_average` int(11) NOT NULL,\n"
+ " `last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n"
+ " PRIMARY KEY (`item_id`)\n"
+ ") ENGINE=InnoDB";
private static final OsbuddyClient CLIENT = new OsbuddyClient();
private final Sql2o sql2o;
@Autowired
public GrandExchangeService(@Qualifier("Runelite SQL2O") Sql2o sql2o)
{
this.sql2o = sql2o;
try (Connection con = sql2o.open())
{
con.createQuery(CREATE_GRAND_EXCHANGE_PRICES).executeUpdate();
}
}
public GrandExchangeEntry get(int itemId)
{
try (Connection con = sql2o.open())
{
return con.createQuery("SELECT item_id, buy_average, sell_average, overall_average, last_update"
+ " FROM osb_ge WHERE item_id = :itemId")
.addParameter("itemId", itemId)
.executeAndFetchFirst(GrandExchangeEntry.class);
}
}
@Scheduled(initialDelay = 1000 * 5, fixedDelay = 1000 * 60 * 30)
private void updateDatabase()
{
try
{
Map<Integer, OsbuddySummaryItem> summary = CLIENT.getSummary();
try (Connection con = sql2o.beginTransaction())
{
Instant updateTime = Instant.now();
Query query = con.createQuery("INSERT INTO osb_ge (item_id, buy_average, sell_average, overall_average,"
+ " last_update) VALUES (:itemId, :buyAverage, :sellAverage, :overallAverage, :lastUpdate)"
+ " ON DUPLICATE KEY UPDATE buy_average = VALUES(buy_average), sell_average = VALUES(sell_average),"
+ " overall_average = VALUES(overall_average), last_update = VALUES(last_update)");
for (Map.Entry<Integer, OsbuddySummaryItem> entry : summary.entrySet())
{
Integer itemId = entry.getKey();
OsbuddySummaryItem item = entry.getValue();
query
.addParameter("itemId", itemId)
.addParameter("buyAverage", item.getBuy_average())
.addParameter("sellAverage", item.getSell_average())
.addParameter("overallAverage", item.getOverall_average())
.addParameter("lastUpdate", Timestamp.from(updateTime))
.addToBatch();
}
query.executeBatch();
con.commit(false);
}
}
catch (IOException e)
{
log.warn("Error while updating the osb grand exchange table", e);
}
}
}

View File

@@ -0,0 +1,74 @@
/*
* Copyright (c) 2018, AeonLucid <https://github.com/AeonLucid>
* 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.http.service.osbuddy;
import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.Map;
import net.runelite.http.api.RuneLiteAPI;
import net.runelite.http.service.osbuddy.beans.OsbuddySummaryItem;
import okhttp3.HttpUrl;
import okhttp3.Request;
import okhttp3.Response;
public class OsbuddyClient
{
private static final String USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36";
public Map<Integer, OsbuddySummaryItem> getSummary() throws IOException
{
HttpUrl httpUrl = new HttpUrl.Builder()
.scheme("https")
.host("rsbuddy.com")
.addPathSegment("exchange")
.addPathSegment("summary.json")
.build();
Request request = new Request.Builder()
.url(httpUrl)
.header("User-Agent", USER_AGENT)
.build();
try (Response responseOk = RuneLiteAPI.CLIENT.newCall(request).execute())
{
if (!responseOk.isSuccessful())
{
throw new IOException("Error retrieving summary from OSBuddy: " + responseOk.message());
}
Type type = new TypeToken<Map<Integer, OsbuddySummaryItem>>()
{
}.getType();
return RuneLiteAPI.GSON.fromJson(responseOk.body().string(), type);
}
catch (JsonSyntaxException ex)
{
throw new IOException(ex);
}
}
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright (c) 2018, AeonLucid <https://github.com/AeonLucid>
* 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.http.service.osbuddy.beans;
import lombok.Data;
@Data
public class OsbuddySummaryItem
{
private int id;
private String name;
private boolean members;
private int sp;
private int buy_average;
private int sell_average;
private int overall_average;
}

View File

@@ -42,6 +42,7 @@ public class WidgetID
public static final int BANK_GROUP_ID = 12;
public static final int BANK_INVENTORY_GROUP_ID = 15;
public static final int GRAND_EXCHANGE_INVENTORY_GROUP_ID = 467;
public static final int GRAND_EXCHANGE_GROUP_ID = 465;
public static final int DEPOSIT_BOX_GROUP_ID = 192;
public static final int INVENTORY_GROUP_ID = 149;
public static final int FRIENDS_LIST_GROUP_ID = 429;
@@ -158,6 +159,18 @@ public class WidgetID
}
static class GrandExchange
{
static final int WINDOW_CONTAINER = 0;
static final int WINDOW_BORDERS = 2;
static final int HISTORY_BUTTON = 3;
static final int BACK_BUTTON = 4;
static final int OFFER_CONTAINER = 24;
static final int OFFER_DESCRIPTION = 25;
static final int OFFER_PRICE = 26;
static final int OFFER_CONFIRM_BUTTON = 27;
}
static class GrandExchangeInventory
{
static final int INVENTORY_ITEM_CONTAINER = 0;
}

View File

@@ -114,7 +114,12 @@ public enum WidgetInfo
BANK_TITLE_BAR(WidgetID.BANK_GROUP_ID, WidgetID.Bank.BANK_TITLE_BAR),
BANK_ITEM_COUNT(WidgetID.BANK_GROUP_ID, WidgetID.Bank.BANK_ITEM_COUNT),
GRAND_EXCHANGE_INVENTORY_ITEMS_CONTAINER(WidgetID.GRAND_EXCHANGE_INVENTORY_GROUP_ID, WidgetID.GrandExchange.INVENTORY_ITEM_CONTAINER),
GRAND_EXCHANGE_WINDOW_CONTAINER(WidgetID.GRAND_EXCHANGE_GROUP_ID, WidgetID.GrandExchange.WINDOW_CONTAINER),
GRAND_EXCHANGE_OFFER_CONTAINER(WidgetID.GRAND_EXCHANGE_GROUP_ID, WidgetID.GrandExchange.OFFER_CONTAINER),
GRAND_EXCHANGE_OFFER_TEXT(WidgetID.GRAND_EXCHANGE_GROUP_ID, WidgetID.GrandExchange.OFFER_DESCRIPTION),
GRAND_EXCHANGE_OFFER_PRICE(WidgetID.GRAND_EXCHANGE_GROUP_ID, WidgetID.GrandExchange.OFFER_PRICE),
GRAND_EXCHANGE_INVENTORY_ITEMS_CONTAINER(WidgetID.GRAND_EXCHANGE_INVENTORY_GROUP_ID, WidgetID.GrandExchangeInventory.INVENTORY_ITEM_CONTAINER),
DEPOSIT_BOX_INVENTORY_ITEMS_CONTAINER(WidgetID.DEPOSIT_BOX_GROUP_ID, WidgetID.DepositBox.INVENTORY_ITEM_CONTAINER),

View File

@@ -56,4 +56,15 @@ public interface GrandExchangeConfig extends Config
{
return true;
}
@ConfigItem(
position = 3,
keyName = "enableOsbPrices",
name = "Enable OSB actively traded prices",
description = "Shows the OSBuddy actively traded price at the GE"
)
default boolean enableOsbPrices()
{
return true;
}
}

View File

@@ -31,6 +31,7 @@ import com.google.common.eventbus.Subscribe;
import com.google.inject.Provides;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.concurrent.ScheduledExecutorService;
import javax.imageio.ImageIO;
import javax.inject.Inject;
import javax.swing.SwingUtilities;
@@ -48,8 +49,11 @@ 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.events.WidgetLoaded;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetID;
import net.runelite.api.widgets.WidgetInfo;
import net.runelite.client.Notifier;
@@ -61,7 +65,10 @@ 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.StackFormatter;
import net.runelite.client.util.Text;
import net.runelite.http.api.osbuddy.GrandExchangeClient;
import net.runelite.http.api.osbuddy.GrandExchangeResult;
@PluginDescriptor(
name = "Grand Exchange"
@@ -69,6 +76,10 @@ import net.runelite.client.util.Text;
@Slf4j
public class GrandExchangePlugin extends Plugin
{
private static final int OFFER_CONTAINER_ITEM = 21;
private static final int OFFER_DEFAULT_ITEM_ID = 6512;
private static final GrandExchangeClient CLIENT = new GrandExchangeClient();
@Getter(AccessLevel.PACKAGE)
private NavigationButton button;
@@ -103,6 +114,14 @@ public class GrandExchangePlugin extends Plugin
@Inject
private Notifier notifier;
@Inject
private ScheduledExecutorService executorService;
private Widget grandExchangeText;
private Widget grandExchangeItem;
private int lastItem = -1;
@Provides
GrandExchangeConfig provideConfig(ConfigManager configManager)
{
@@ -239,4 +258,72 @@ public class GrandExchangePlugin extends Plugin
setHotKeyPressed(false);
}
}
@Subscribe
public void onWidgetLoaded(WidgetLoaded event)
{
switch (event.getGroupId())
{
// Grand exchange was opened.
case WidgetID.GRAND_EXCHANGE_GROUP_ID:
if (!config.enableOsbPrices())
{
return;
}
Widget grandExchangeOffer = client.getWidget(WidgetInfo.GRAND_EXCHANGE_OFFER_CONTAINER);
grandExchangeText = client.getWidget(WidgetInfo.GRAND_EXCHANGE_OFFER_TEXT);
grandExchangeItem = grandExchangeOffer.getDynamicChildren()[OFFER_CONTAINER_ITEM];
lastItem = -1;
break;
// Grand exchange was closed (if it was open before).
case WidgetID.INVENTORY_GROUP_ID:
grandExchangeText = null;
grandExchangeItem = null;
lastItem = -1;
break;
}
}
@Subscribe
public void onGameTick(GameTick event)
{
if (grandExchangeText == null || grandExchangeItem == null)
{
return;
}
int itemId = grandExchangeItem.getItemId();
if (itemId == OFFER_DEFAULT_ITEM_ID
|| itemId == -1
|| lastItem == itemId)
{
return;
}
lastItem = itemId;
final Widget geText = grandExchangeText;
executorService.submit(() ->
{
try
{
final GrandExchangeResult result = CLIENT.lookupItem(itemId);
if (result.getItem_id() != lastItem)
{
// something else has since been looked up?
return;
}
final String text = geText.getText() + "<br>OSBuddy Actively traded price: " + StackFormatter.formatNumber(result.getOverall_average());
geText.setText(text);
}
catch (IOException e)
{
log.debug("Error getting price of item {}", itemId, e);
}
});
}
}