Advertisement
Guest User

Untitled

a guest
Jul 19th, 2019
97
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 18.97 KB | None | 0 0
  1. /*
  2. * Copyright (c) 2019, Adam <Adam@sigterm.info>
  3. * Copyright (c) 2017, Robbie <https://github.com/rbbi>
  4. * Copyright (c) 2018, SomeoneWithAnInternetConnection
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright notice, this
  11. * list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright notice,
  13. * this list of conditions and the following disclaimer in the documentation
  14. * and/or other materials provided with the distribution.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  17. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
  20. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27.  
  28. package net.runelite.client.plugins.grandexchange;
  29.  
  30. import com.google.common.reflect.TypeToken;
  31. import com.google.gson.Gson;
  32. import com.google.inject.Provides;
  33. import io.reactivex.schedulers.Schedulers;
  34. import java.awt.image.BufferedImage;
  35. import java.io.InputStream;
  36. import java.io.InputStreamReader;
  37. import java.util.Map;
  38. import java.util.concurrent.ScheduledExecutorService;
  39. import javax.inject.Inject;
  40. import javax.inject.Singleton;
  41. import javax.swing.SwingUtilities;
  42. import lombok.AccessLevel;
  43. import lombok.Getter;
  44. import lombok.Setter;
  45. import lombok.extern.slf4j.Slf4j;
  46. import net.runelite.api.ChatMessageType;
  47. import net.runelite.api.Client;
  48. import net.runelite.api.GameState;
  49. import net.runelite.api.GrandExchangeOffer;
  50. import net.runelite.api.GrandExchangeOfferState;
  51. import net.runelite.api.InventoryID;
  52. import net.runelite.api.Item;
  53. import net.runelite.api.ItemContainer;
  54. import net.runelite.api.ItemDefinition;
  55. import static net.runelite.api.ItemID.COINS_995;
  56. import net.runelite.api.MenuAction;
  57. import net.runelite.api.MenuEntry;
  58. import net.runelite.api.Varbits;
  59. import net.runelite.api.events.ChatMessage;
  60. import net.runelite.api.events.ConfigChanged;
  61. import net.runelite.api.events.FocusChanged;
  62. import net.runelite.api.events.GameStateChanged;
  63. import net.runelite.api.events.GameTick;
  64. import net.runelite.api.events.GrandExchangeOfferChanged;
  65. import net.runelite.api.events.MenuEntryAdded;
  66. import net.runelite.api.events.ScriptCallbackEvent;
  67. import net.runelite.api.events.WidgetLoaded;
  68. import net.runelite.api.widgets.Widget;
  69. import net.runelite.api.widgets.WidgetID;
  70. import net.runelite.api.widgets.WidgetInfo;
  71. import net.runelite.client.Notifier;
  72. import net.runelite.client.account.AccountSession;
  73. import net.runelite.client.account.SessionManager;
  74. import net.runelite.client.callback.ClientThread;
  75. import net.runelite.client.config.ConfigManager;
  76. import net.runelite.client.eventbus.EventBus;
  77. import net.runelite.client.events.SessionClose;
  78. import net.runelite.client.events.SessionOpen;
  79. import net.runelite.client.game.ItemManager;
  80. import net.runelite.client.input.KeyManager;
  81. import net.runelite.client.input.MouseManager;
  82. import net.runelite.client.plugins.Plugin;
  83. import net.runelite.client.plugins.PluginDescriptor;
  84. import net.runelite.client.ui.ClientToolbar;
  85. import net.runelite.client.ui.NavigationButton;
  86. import net.runelite.client.util.ImageUtil;
  87. import net.runelite.client.util.StackFormatter;
  88. import net.runelite.client.util.Text;
  89. import net.runelite.http.api.ge.GrandExchangeClient;
  90. import net.runelite.http.api.ge.GrandExchangeTrade;
  91. import net.runelite.http.api.osbuddy.OSBGrandExchangeClient;
  92. import net.runelite.http.api.osbuddy.OSBGrandExchangeResult;
  93.  
  94. @PluginDescriptor(
  95. name = "Grand Exchange",
  96. description = "Provide additional and/or easier access to Grand Exchange information",
  97. tags = {"external", "integration", "notifications", "panel", "prices", "trade"}
  98. )
  99. @Slf4j
  100. @Singleton
  101. public class GrandExchangePlugin extends Plugin
  102. {
  103. private static final int OFFER_CONTAINER_ITEM = 21;
  104. private static final int OFFER_DEFAULT_ITEM_ID = 6512;
  105. private static final OSBGrandExchangeClient CLIENT = new OSBGrandExchangeClient();
  106. private static final String OSB_GE_TEXT = "<br>OSBuddy Actively traded price: ";
  107.  
  108. private static final String BUY_LIMIT_GE_TEXT = "Buy limit: ";
  109. private static final String AFFORD_GE_TEXT = "<br>Afford: ";
  110. private static final Gson GSON = new Gson();
  111. private static final TypeToken<Map<Integer, Integer>> BUY_LIMIT_TOKEN = new TypeToken<Map<Integer, Integer>>()
  112. {
  113. };
  114.  
  115. static final String SEARCH_GRAND_EXCHANGE = "Search Grand Exchange";
  116.  
  117. @Getter(AccessLevel.PACKAGE)
  118. private NavigationButton button;
  119.  
  120. @Getter(AccessLevel.PACKAGE)
  121. private GrandExchangePanel panel;
  122.  
  123. @Getter(AccessLevel.PACKAGE)
  124. @Setter(AccessLevel.PACKAGE)
  125. private boolean hotKeyPressed;
  126.  
  127. @Inject
  128. private GrandExchangeInputListener inputListener;
  129.  
  130. @Inject
  131. private ItemManager itemManager;
  132.  
  133. @Inject
  134. private MouseManager mouseManager;
  135.  
  136. @Inject
  137. private KeyManager keyManager;
  138.  
  139. @Inject
  140. private Client client;
  141.  
  142. @Inject
  143. private ClientThread clientThread;
  144.  
  145. @Inject
  146. private ClientToolbar clientToolbar;
  147.  
  148. @Inject
  149. private GrandExchangeConfig config;
  150.  
  151. @Inject
  152. private Notifier notifier;
  153.  
  154. @Inject
  155. private ScheduledExecutorService executorService;
  156.  
  157. @Inject
  158. private SessionManager sessionManager;
  159.  
  160. @Inject
  161. private ConfigManager configManager;
  162.  
  163. @Inject
  164. private EventBus eventBus;
  165.  
  166. private Widget grandExchangeText;
  167. private Widget grandExchangeItem;
  168. private Map<Integer, Integer> itemGELimits;
  169.  
  170. private GrandExchangeClient grandExchangeClient;
  171.  
  172. private int coins = 0;
  173. private int lastAmount = -1;
  174. private int lastItem = -1;
  175.  
  176. private int osbItem = -1;
  177. private String osbText = "";
  178.  
  179. private SavedOffer getOffer(int slot)
  180. {
  181. String offer = configManager.getConfiguration("geoffer." + client.getUsername().toLowerCase(), Integer.toString(slot));
  182. if (offer == null)
  183. {
  184. return null;
  185. }
  186. return GSON.fromJson(offer, SavedOffer.class);
  187. }
  188.  
  189. private void setOffer(int slot, SavedOffer offer)
  190. {
  191. configManager.setConfiguration("geoffer." + client.getUsername().toLowerCase(), Integer.toString(slot), GSON.toJson(offer));
  192. }
  193.  
  194. private void deleteOffer(int slot)
  195. {
  196. configManager.unsetConfiguration("geoffer." + client.getUsername().toLowerCase(), Integer.toString(slot));
  197. }
  198.  
  199. private boolean quickLookup;
  200. private boolean enableNotifications;
  201. private boolean enableOsbPrices;
  202. private boolean enableGELimits;
  203. private boolean enableAfford;
  204.  
  205. @Provides
  206. GrandExchangeConfig provideConfig(ConfigManager configManager)
  207. {
  208. return configManager.getConfig(GrandExchangeConfig.class);
  209. }
  210.  
  211. @Override
  212. protected void startUp()
  213. {
  214. updateConfig();
  215. addSubscriptions();
  216.  
  217. itemGELimits = loadGELimits();
  218. panel = injector.getInstance(GrandExchangePanel.class);
  219. panel.setGELimits(itemGELimits);
  220.  
  221. final BufferedImage icon = ImageUtil.getResourceStreamFromClass(getClass(), "ge_icon.png");
  222.  
  223. button = NavigationButton.builder()
  224. .tooltip("Grand Exchange")
  225. .icon(icon)
  226. .priority(3)
  227. .panel(panel)
  228. .build();
  229.  
  230. clientToolbar.addNavigation(button);
  231.  
  232. if (this.quickLookup)
  233. {
  234. mouseManager.registerMouseListener(inputListener);
  235. keyManager.registerKeyListener(inputListener);
  236. }
  237.  
  238. AccountSession accountSession = sessionManager.getAccountSession();
  239. if (accountSession != null)
  240. {
  241. grandExchangeClient = new GrandExchangeClient(accountSession.getUuid());
  242. }
  243. }
  244.  
  245. @Override
  246. protected void shutDown()
  247. {
  248. eventBus.unregister(this);
  249.  
  250. clientToolbar.removeNavigation(button);
  251. mouseManager.unregisterMouseListener(inputListener);
  252. keyManager.unregisterKeyListener(inputListener);
  253. grandExchangeText = null;
  254. grandExchangeItem = null;
  255. itemGELimits = null;
  256. grandExchangeClient = null;
  257. }
  258.  
  259. private void addSubscriptions()
  260. {
  261. eventBus.subscribe(ConfigChanged.class, this, this::onConfigChanged);
  262. eventBus.subscribe(GameTick.class, this, this::onGameTick);
  263. eventBus.subscribe(ChatMessage.class, this, this::onChatMessage);
  264. eventBus.subscribe(SessionOpen.class, this, this::onSessionOpen);
  265. eventBus.subscribe(SessionClose.class, this, this::onSessionClose);
  266. eventBus.subscribe(GrandExchangeOfferChanged.class, this, this::onGrandExchangeOfferChanged);
  267. eventBus.subscribe(GameStateChanged.class, this, this::onGameStateChanged);
  268. eventBus.subscribe(MenuEntryAdded.class, this, this::onMenuEntryAdded);
  269. eventBus.subscribe(FocusChanged.class, this, this::onFocusChanged);
  270. eventBus.subscribe(WidgetLoaded.class, this, this::onWidgetLoaded);
  271. eventBus.subscribe(ScriptCallbackEvent.class, this, this::onScriptCallbackEvent);
  272. eventBus.subscribe(GameTick.class, this, this::onGameTick);
  273. }
  274.  
  275. private void onSessionOpen(SessionOpen sessionOpen)
  276. {
  277. AccountSession accountSession = sessionManager.getAccountSession();
  278. if (accountSession.getUuid() != null)
  279. {
  280. grandExchangeClient = new GrandExchangeClient(accountSession.getUuid());
  281. }
  282. else
  283. {
  284. grandExchangeClient = null;
  285. }
  286. }
  287.  
  288. private void updateConfig()
  289. {
  290. this.quickLookup = config.quickLookup();
  291. this.enableNotifications = config.enableNotifications();
  292. this.enableOsbPrices = config.enableOsbPrices();
  293. this.enableGELimits = config.enableGELimits();
  294. this.enableAfford = config.enableAfford();
  295. }
  296.  
  297. private void onSessionClose(SessionClose sessionClose)
  298. {
  299. grandExchangeClient = null;
  300. }
  301.  
  302. private void onConfigChanged(ConfigChanged event)
  303. {
  304. if (event.getGroup().equals("grandexchange"))
  305. {
  306. updateConfig();
  307. if (event.getKey().equals("quickLookup"))
  308. {
  309. if (this.quickLookup)
  310. {
  311. mouseManager.registerMouseListener(inputListener);
  312. keyManager.registerKeyListener(inputListener);
  313. }
  314. else
  315. {
  316. mouseManager.unregisterMouseListener(inputListener);
  317. keyManager.unregisterKeyListener(inputListener);
  318. }
  319. }
  320. }
  321. }
  322.  
  323. private void onGrandExchangeOfferChanged(GrandExchangeOfferChanged offerEvent)
  324. {
  325. final int slot = offerEvent.getSlot();
  326. final GrandExchangeOffer offer = offerEvent.getOffer();
  327.  
  328. ItemDefinition offerItem = itemManager.getItemDefinition(offer.getItemId());
  329. boolean shouldStack = offerItem.isStackable() || offer.getTotalQuantity() > 1;
  330. BufferedImage itemImage = itemManager.getImage(offer.getItemId(), offer.getTotalQuantity(), shouldStack);
  331. SwingUtilities.invokeLater(() -> panel.getOffersPanel().updateOffer(offerItem, itemImage, offer, slot));
  332.  
  333. submitTrades(slot, offer);
  334.  
  335. updateConfig(slot, offer);
  336. }
  337.  
  338. private void submitTrades(int slot, GrandExchangeOffer offer)
  339. {
  340. if (grandExchangeClient == null)
  341. {
  342. return;
  343. }
  344.  
  345. // Only interested in offers which are fully bought/sold
  346. if (offer.getState() != GrandExchangeOfferState.BOUGHT && offer.getState() != GrandExchangeOfferState.SOLD)
  347. {
  348. return;
  349. }
  350.  
  351. SavedOffer savedOffer = getOffer(slot);
  352. if (!shouldUpdate(savedOffer, offer))
  353. {
  354. return;
  355. }
  356.  
  357. // getPrice() is the price of the offer, not necessarily what the item bought at
  358. int priceEach = offer.getSpent() / offer.getTotalQuantity();
  359.  
  360. GrandExchangeTrade grandExchangeTrade = new GrandExchangeTrade();
  361. grandExchangeTrade.setBuy(offer.getState() == GrandExchangeOfferState.BOUGHT);
  362. grandExchangeTrade.setItemId(offer.getItemId());
  363. grandExchangeTrade.setQuantity(offer.getTotalQuantity());
  364. grandExchangeTrade.setPrice(priceEach);
  365.  
  366. log.debug("Submitting trade: {}", grandExchangeTrade);
  367. grandExchangeClient.submit(grandExchangeTrade);
  368. }
  369.  
  370. private void updateConfig(int slot, GrandExchangeOffer offer)
  371. {
  372. if (offer.getState() == GrandExchangeOfferState.EMPTY)
  373. {
  374. deleteOffer(slot);
  375. }
  376. else
  377. {
  378. SavedOffer savedOffer = new SavedOffer();
  379. savedOffer.setItemId(offer.getItemId());
  380. savedOffer.setQuantitySold(offer.getQuantitySold());
  381. savedOffer.setTotalQuantity(offer.getTotalQuantity());
  382. savedOffer.setPrice(offer.getPrice());
  383. savedOffer.setSpent(offer.getSpent());
  384. savedOffer.setState(offer.getState());
  385. setOffer(slot, savedOffer);
  386. }
  387. }
  388.  
  389. private boolean shouldUpdate(SavedOffer savedOffer, GrandExchangeOffer grandExchangeOffer)
  390. {
  391. if (savedOffer == null)
  392. {
  393. return false;
  394. }
  395.  
  396. // Only update offer if state has changed
  397. return savedOffer.getState() != grandExchangeOffer.getState();
  398. }
  399.  
  400. private void onChatMessage(ChatMessage event)
  401. {
  402. if (!this.enableNotifications || event.getType() != ChatMessageType.GAMEMESSAGE)
  403. {
  404. return;
  405. }
  406.  
  407. String message = Text.removeTags(event.getMessage());
  408.  
  409. if (message.startsWith("Grand Exchange:"))
  410. {
  411. this.notifier.notify(message);
  412. }
  413. }
  414.  
  415. private void onGameStateChanged(GameStateChanged gameStateChanged)
  416. {
  417. if (gameStateChanged.getGameState() == GameState.LOGIN_SCREEN)
  418. {
  419. panel.getOffersPanel().resetOffers();
  420. }
  421. }
  422.  
  423. private void onMenuEntryAdded(MenuEntryAdded event)
  424. {
  425. // At the moment, if the user disables quick lookup, the input listener gets disabled. Thus, isHotKeyPressed()
  426. // should always return false when quick lookup is disabled.
  427. // Replace the default option with "Search ..." when holding alt
  428. if (client.getGameState() != GameState.LOGGED_IN || !hotKeyPressed)
  429. {
  430. return;
  431. }
  432.  
  433. final MenuEntry[] entries = client.getMenuEntries();
  434. final MenuEntry menuEntry = entries[entries.length - 1];
  435. final int widgetId = menuEntry.getParam1();
  436. final int groupId = WidgetInfo.TO_GROUP(widgetId);
  437.  
  438. switch (groupId)
  439. {
  440. case WidgetID.BANK_GROUP_ID:
  441. // Don't show for view tabs and such
  442. if (WidgetInfo.TO_CHILD(widgetId) != WidgetInfo.BANK_ITEM_CONTAINER.getChildId())
  443. {
  444. break;
  445. }
  446. case WidgetID.INVENTORY_GROUP_ID:
  447. case WidgetID.BANK_INVENTORY_GROUP_ID:
  448. case WidgetID.GRAND_EXCHANGE_INVENTORY_GROUP_ID:
  449. case WidgetID.SHOP_INVENTORY_GROUP_ID:
  450. menuEntry.setOption(SEARCH_GRAND_EXCHANGE);
  451. menuEntry.setType(MenuAction.RUNELITE.getId());
  452. client.setMenuEntries(entries);
  453. }
  454. }
  455.  
  456. private void onFocusChanged(FocusChanged focusChanged)
  457. {
  458. if (!focusChanged.isFocused())
  459. {
  460. setHotKeyPressed(false);
  461. }
  462. }
  463.  
  464. private void onWidgetLoaded(WidgetLoaded event)
  465. {
  466. switch (event.getGroupId())
  467. {
  468. // Grand exchange was opened.
  469. case WidgetID.GRAND_EXCHANGE_GROUP_ID:
  470. Widget grandExchangeOffer = client.getWidget(WidgetInfo.GRAND_EXCHANGE_OFFER_CONTAINER);
  471. grandExchangeText = client.getWidget(WidgetInfo.GRAND_EXCHANGE_OFFER_TEXT);
  472. grandExchangeItem = grandExchangeOffer.getDynamicChildren()[OFFER_CONTAINER_ITEM];
  473. break;
  474. // Grand exchange was closed (if it was open before).
  475. case WidgetID.INVENTORY_GROUP_ID:
  476. grandExchangeText = null;
  477. grandExchangeItem = null;
  478. break;
  479. }
  480. }
  481.  
  482. private void onScriptCallbackEvent(ScriptCallbackEvent event)
  483. {
  484. if (!event.getEventName().equals("setGETitle") || !config.showTotal())
  485. {
  486. return;
  487. }
  488.  
  489. long total = 0;
  490. GrandExchangeOffer[] offers = client.getGrandExchangeOffers();
  491. for (GrandExchangeOffer offer : offers)
  492. {
  493. if (offer != null)
  494. {
  495. total += offer.getPrice() * offer.getTotalQuantity();
  496. }
  497. }
  498.  
  499. if (total == 0L)
  500. {
  501. return;
  502. }
  503.  
  504. StringBuilder titleBuilder = new StringBuilder(" (");
  505.  
  506. if (config.showExact())
  507. {
  508. titleBuilder.append(StackFormatter.formatNumber(total));
  509. }
  510. else
  511. {
  512. titleBuilder.append(StackFormatter.quantityToStackSize(total));
  513. }
  514.  
  515. titleBuilder.append(')');
  516.  
  517. // Append to title
  518. String[] stringStack = client.getStringStack();
  519. int stringStackSize = client.getStringStackSize();
  520.  
  521. stringStack[stringStackSize - 1] += titleBuilder.toString();
  522. }
  523.  
  524. private void onGameTick(GameTick event)
  525. {
  526. if (grandExchangeText == null || grandExchangeItem == null || grandExchangeItem.isHidden())
  527. {
  528. return;
  529. }
  530.  
  531. final Widget geText = grandExchangeText;
  532. final String geTextString = geText.getText();
  533. final int itemId = grandExchangeItem.getItemId();
  534. final String osbstr = text;
  535.  
  536. if (itemId == OFFER_DEFAULT_ITEM_ID || itemId == -1)
  537. {
  538. lastAmount = osbItem = lastItem = -1;
  539. // This item is invalid/nothing has been searched for
  540. return;
  541. }
  542.  
  543. final int currentItemPrice = client.getVar(Varbits.GRAND_EXCHANGE_PRICE_PER_ITEM);
  544.  
  545. if (lastItem == itemId && lastAmount == currentItemPrice )
  546. {
  547. return;
  548. }
  549.  
  550. lastItem = itemId;
  551. lastAmount = currentItemPrice;
  552.  
  553. String[] texts = geText.getText().split("<br>");
  554. String text = texts[0];
  555.  
  556. if (this.enableAfford)
  557. {
  558. final ItemContainer itemContainer = client.getItemContainer(InventoryID.INVENTORY);
  559. final Item[] items = itemContainer.getItems();
  560. for (Item item : items)
  561. {
  562. if (item.getId() == COINS_995)
  563. {
  564. coins = item.getQuantity();
  565. break;
  566. }
  567. }
  568.  
  569. final String text = geText.getText() + AFFORD_GE_TEXT + StackFormatter.formatNumber(coins / currentItemPrice) + " ";
  570. geText.setText(text);
  571. }
  572.  
  573. if (this.enableGELimits && itemGELimits != null && !geTextString.contains(BUY_LIMIT_GE_TEXT))
  574. {
  575. final Integer itemLimit = itemGELimits.get(itemId);
  576.  
  577. // If we have item buy limit, append it
  578. if (itemLimit != null)
  579. {
  580. final String text = geText.getText() + BUY_LIMIT_GE_TEXT + StackFormatter.formatNumber(itemLimit);
  581. geText.setText(text);
  582. }
  583. }
  584.  
  585. if (!this.enableOsbPrices || geTextString.contains(OSB_GE_TEXT))
  586.  
  587. {
  588. // OSB prices are disabled or price was already looked up, so no need to set it again
  589. return;
  590. }
  591.  
  592. log.debug("Looking up OSB item price {}", itemId);
  593. if (osbItem == lastItem)
  594. {
  595. // OSB Item was already looked up
  596. return;
  597. }
  598.  
  599. osbItem = lastItem;
  600.  
  601. executorService.submit(() ->
  602. {
  603. if (geText.getText().contains(OSB_GE_TEXT))
  604. {
  605. // If there are multiple tasks queued and one of them have already added the price
  606. return;
  607. }
  608.  
  609. try
  610. {
  611. final OSBGrandExchangeResult result = CLIENT.lookupItem(itemId);
  612. final String text = geText.getText() + OSB_GE_TEXT + StackFormatter.formatNumber(result.getOverall_average());
  613. geText.setText(text);
  614. }
  615. catch (IOException e)
  616. {
  617. log.debug("Error getting price of item {}", itemId, e);
  618. }
  619. });
  620. }
  621.  
  622. private static Map<Integer, Integer> loadGELimits()
  623. {
  624. final InputStream geLimitData = GrandExchangePlugin.class.getResourceAsStream("ge_limits.json");
  625. final Map<Integer, Integer> itemGELimits = GSON.fromJson(new InputStreamReader(geLimitData), BUY_LIMIT_TOKEN.getType());
  626. log.debug("Loaded {} limits", itemGELimits.size());
  627. return itemGELimits;
  628. }
  629. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement