From eefee493b7eec9a731df381fd4394c9770898193 Mon Sep 17 00:00:00 2001 From: RuneLite Cache-Code Autoupdater Date: Thu, 28 May 2020 10:32:23 +0000 Subject: [PATCH 01/12] Update Item IDs to 2020-05-28-rev182 --- .../src/main/java/net/runelite/api/ItemID.java | 10 ++++++++++ .../src/main/java/net/runelite/api/NullItemID.java | 6 ++++++ 2 files changed, 16 insertions(+) diff --git a/runelite-api/src/main/java/net/runelite/api/ItemID.java b/runelite-api/src/main/java/net/runelite/api/ItemID.java index f5eb3c41d1..92094cf0fd 100644 --- a/runelite-api/src/main/java/net/runelite/api/ItemID.java +++ b/runelite-api/src/main/java/net/runelite/api/ItemID.java @@ -11470,5 +11470,15 @@ public final class ItemID public static final int LOGS_24650 = 24650; public static final int RAW_SHRIMPS_24652 = 24652; public static final int BONES_24655 = 24655; + public static final int ENRAGED_TEKTINY = 24656; + public static final int FLYING_VESPINA = 24658; + public static final int MASSIVE_STORAGE_UNIT = 24660; + public static final int MASSIVE_STORAGE_UNIT_24661 = 24661; + public static final int MASSIVE_STORAGE_UNIT_24662 = 24662; + public static final int MASSIVE_STORAGE_UNIT_24663 = 24663; + public static final int TWISTED_ANCESTRAL_HAT = 24664; + public static final int TWISTED_ANCESTRAL_ROBE_TOP = 24666; + public static final int TWISTED_ANCESTRAL_ROBE_BOTTOM = 24668; + public static final int TWISTED_ANCESTRAL_COLOUR_KIT = 24670; /* This file is automatically generated. Do not edit. */ } diff --git a/runelite-api/src/main/java/net/runelite/api/NullItemID.java b/runelite-api/src/main/java/net/runelite/api/NullItemID.java index b57c30a4ad..4272c68378 100644 --- a/runelite-api/src/main/java/net/runelite/api/NullItemID.java +++ b/runelite-api/src/main/java/net/runelite/api/NullItemID.java @@ -12975,5 +12975,11 @@ public final class NullItemID public static final int NULL_24651 = 24651; public static final int NULL_24653 = 24653; public static final int NULL_24654 = 24654; + public static final int NULL_24657 = 24657; + public static final int NULL_24659 = 24659; + public static final int NULL_24665 = 24665; + public static final int NULL_24667 = 24667; + public static final int NULL_24669 = 24669; + public static final int NULL_24671 = 24671; /* This file is automatically generated. Do not edit. */ } From c8d187500dd00a138c81409bbb475ef408a21405 Mon Sep 17 00:00:00 2001 From: RuneLite Cache-Code Autoupdater Date: Thu, 28 May 2020 10:32:23 +0000 Subject: [PATCH 02/12] Update Item variations to 2020-05-28-rev182 --- runelite-client/src/main/resources/item_variations.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/runelite-client/src/main/resources/item_variations.json b/runelite-client/src/main/resources/item_variations.json index 6985b3678d..ce423e6ca7 100644 --- a/runelite-client/src/main/resources/item_variations.json +++ b/runelite-client/src/main/resources/item_variations.json @@ -9764,5 +9764,11 @@ 24638, 24641, 24644 + ], + "massive storage unit": [ + 24660, + 24661, + 24662, + 24663 ] } \ No newline at end of file From 5d39c499ef22b9197d057ad309c10fc3a29bffa9 Mon Sep 17 00:00:00 2001 From: RuneLite Cache-Code Autoupdater Date: Thu, 28 May 2020 10:32:24 +0000 Subject: [PATCH 03/12] Update Object IDs to 2020-05-28-rev182 --- runelite-api/src/main/java/net/runelite/api/NullObjectID.java | 2 ++ runelite-api/src/main/java/net/runelite/api/ObjectID.java | 1 + 2 files changed, 3 insertions(+) diff --git a/runelite-api/src/main/java/net/runelite/api/NullObjectID.java b/runelite-api/src/main/java/net/runelite/api/NullObjectID.java index a11256b413..12e20de7a5 100644 --- a/runelite-api/src/main/java/net/runelite/api/NullObjectID.java +++ b/runelite-api/src/main/java/net/runelite/api/NullObjectID.java @@ -18335,5 +18335,7 @@ public final class NullObjectID public static final int NULL_37958 = 37958; public static final int NULL_37960 = 37960; public static final int NULL_37962 = 37962; + public static final int NULL_37976 = 37976; + public static final int NULL_37977 = 37977; /* This file is automatically generated. Do not edit. */ } diff --git a/runelite-api/src/main/java/net/runelite/api/ObjectID.java b/runelite-api/src/main/java/net/runelite/api/ObjectID.java index e280976757..a1861aaed0 100644 --- a/runelite-api/src/main/java/net/runelite/api/ObjectID.java +++ b/runelite-api/src/main/java/net/runelite/api/ObjectID.java @@ -19628,5 +19628,6 @@ public final class ObjectID public static final int TREE_37973 = 37973; public static final int TREE_37974 = 37974; public static final int TREE_37975 = 37975; + public static final int MASSIVE_STORAGE_UNIT = 37978; /* This file is automatically generated. Do not edit. */ } From bb31babba25c117e6493063e094d29ef9f7b5285 Mon Sep 17 00:00:00 2001 From: RuneLite Cache-Code Autoupdater Date: Thu, 28 May 2020 10:32:24 +0000 Subject: [PATCH 04/12] Update NPC IDs to 2020-05-28-rev182 --- runelite-api/src/main/java/net/runelite/api/NpcID.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/runelite-api/src/main/java/net/runelite/api/NpcID.java b/runelite-api/src/main/java/net/runelite/api/NpcID.java index d2b8833f58..d516dec046 100644 --- a/runelite-api/src/main/java/net/runelite/api/NpcID.java +++ b/runelite-api/src/main/java/net/runelite/api/NpcID.java @@ -8512,5 +8512,9 @@ public final class NpcID public static final int ACCOUNT_SECURITY_TUTOR = 9504; public static final int HAMELN_THE_JESTER_9505 = 9505; public static final int HANCHEN_THE_HOUND_9506 = 9506; + public static final int ENRAGED_TEKTINY = 9511; + public static final int FLYING_VESPINA = 9512; + public static final int ENRAGED_TEKTINY_9513 = 9513; + public static final int FLYING_VESPINA_9514 = 9514; /* This file is automatically generated. Do not edit. */ } From 27173d90b5cf9736ddb4f1071e1d6b2f508930ac Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 27 May 2020 14:47:10 -0400 Subject: [PATCH 05/12] hooks: remove remaining static callbacks --- .../net/runelite/api/hooks/Callbacks.java | 2 + .../net/runelite/client/callback/Hooks.java | 62 ++++--------------- 2 files changed, 13 insertions(+), 51 deletions(-) diff --git a/runelite-api/src/main/java/net/runelite/api/hooks/Callbacks.java b/runelite-api/src/main/java/net/runelite/api/hooks/Callbacks.java index b6960d761f..07d00487bc 100644 --- a/runelite-api/src/main/java/net/runelite/api/hooks/Callbacks.java +++ b/runelite-api/src/main/java/net/runelite/api/hooks/Callbacks.java @@ -70,6 +70,8 @@ public interface Callbacks */ void drawAboveOverheads(); + void drawAfterWidgets(); + /** * Client top-most draw method, rendering over top of most of game interfaces. * diff --git a/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java b/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java index f4a963035a..d7e353df4c 100644 --- a/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java +++ b/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java @@ -24,7 +24,6 @@ */ package net.runelite.client.callback; -import com.google.inject.Injector; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; @@ -40,27 +39,22 @@ import java.awt.image.VolatileImage; import javax.inject.Inject; import javax.inject.Singleton; import lombok.extern.slf4j.Slf4j; -import net.runelite.api.BufferProvider; import net.runelite.api.Client; import net.runelite.api.MainBufferProvider; import net.runelite.api.NullItemID; import net.runelite.api.RenderOverview; -import net.runelite.api.Renderable; import net.runelite.api.Skill; import net.runelite.api.WorldMapManager; -import net.runelite.api.events.BeforeMenuRender; import net.runelite.api.events.BeforeRender; import net.runelite.api.events.FakeXpDrop; import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.GameTick; import net.runelite.api.events.ScriptCallbackEvent; import net.runelite.api.hooks.Callbacks; -import net.runelite.api.hooks.DrawCallbacks; import net.runelite.api.widgets.Widget; import static net.runelite.api.widgets.WidgetInfo.WORLD_MAP_VIEW; import net.runelite.api.widgets.WidgetItem; import net.runelite.client.Notifier; -import net.runelite.client.RuneLite; import net.runelite.client.chat.ChatMessageManager; import net.runelite.client.eventbus.EventBus; import net.runelite.client.eventbus.Subscribe; @@ -87,14 +81,18 @@ public class Hooks implements Callbacks { private static final long CHECK = RSTimeUnit.GAME_TICKS.getDuration().toNanos(); // ns - how often to run checks - private static final Injector injector = RuneLite.getInjector(); - private static final Client client = injector.getInstance(Client.class); - private static final OverlayRenderer renderer = injector.getInstance(OverlayRenderer.class); - private static final OverlayManager overlayManager = injector.getInstance(OverlayManager.class); - private static final GameTick GAME_TICK = new GameTick(); private static final BeforeRender BEFORE_RENDER = new BeforeRender(); + @Inject + private Client client; + + @Inject + private OverlayRenderer renderer; + + @Inject + private OverlayManager overlayManager; + @Inject private EventBus eventBus; @@ -449,7 +447,8 @@ public class Hooks implements Callbacks } } - public static void drawAfterWidgets() + @Override + public void drawAfterWidgets() { MainBufferProvider bufferProvider = (MainBufferProvider) client.getBufferProvider(); Graphics2D graphics2d = getGraphics(bufferProvider); @@ -505,38 +504,6 @@ public class Hooks implements Callbacks deferredEventBus.replay(); } - public static void renderDraw(Renderable renderable, int orientation, int pitchSin, int pitchCos, int yawSin, int yawCos, int x, int y, int z, long hash) - { - DrawCallbacks drawCallbacks = client.getDrawCallbacks(); - if (drawCallbacks != null) - { - drawCallbacks.draw(renderable, orientation, pitchSin, pitchCos, yawSin, yawCos, x, y, z, hash); - } - else - { - renderable.draw(orientation, pitchSin, pitchCos, yawSin, yawCos, x, y, z, hash); - } - } - - public static void clearColorBuffer(int x, int y, int width, int height, int color) - { - BufferProvider bp = client.getBufferProvider(); - int canvasWidth = bp.getWidth(); - int[] pixels = bp.getPixels(); - - int pixelPos = y * canvasWidth + x; - int pixelJump = canvasWidth - width; - - for (int cy = y; cy < y + height; cy++) - { - for (int cx = x; cx < x + width; cx++) - { - pixels[pixelPos++] = 0; - } - pixelPos += pixelJump; - } - } - @Override public void drawItem(int itemId, WidgetItem widgetItem) { @@ -547,13 +514,6 @@ public class Hooks implements Callbacks } } - public static boolean drawMenu() - { - BeforeMenuRender event = new BeforeMenuRender(); - client.getCallbacks().post(event); - return event.isConsumed(); - } - @Subscribe public void onScriptCallbackEvent(ScriptCallbackEvent scriptCallbackEvent) { From 869b1ba1d9c3c1f67e0bf9471750b1fd3082d82e Mon Sep 17 00:00:00 2001 From: Jesse Serrao Date: Sat, 30 May 2020 16:52:59 +0100 Subject: [PATCH 06/12] npc indicators: add option to not highlight dead npcs --- .../plugins/npchighlight/NpcIndicatorsConfig.java | 11 +++++++++++ .../plugins/npchighlight/NpcIndicatorsPlugin.java | 2 +- .../plugins/npchighlight/NpcMinimapOverlay.java | 3 ++- .../client/plugins/npchighlight/NpcSceneOverlay.java | 3 ++- 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsConfig.java index 1ef10c50d8..6ef25f3bb3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsConfig.java @@ -100,6 +100,17 @@ public interface NpcIndicatorsConfig extends Config @ConfigItem( position = 6, + keyName = "highlightDeadNPCs", + name = "Highlight dead NPCs", + description = "Highlight dead NPCs" + ) + default boolean highlightDeadNpcs() + { + return false; + } + + @ConfigItem( + position = 7, keyName = "showRespawnTimer", name = "Show respawn timer", description = "Show respawn timer of tagged NPCs") diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsPlugin.java index 8b19b4ca91..200eedfd8b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsPlugin.java @@ -260,7 +260,7 @@ public class NpcIndicatorsPlugin extends Plugin if (config.highlightMenuNames() && NPC_MENU_ACTIONS.contains(MenuAction.of(type)) && - highlightedNpcs.stream().anyMatch(npc -> npc.getIndex() == event.getIdentifier())) + highlightedNpcs.stream().anyMatch(npc -> npc.getIndex() == event.getIdentifier() && (!npc.isDead() || config.highlightDeadNpcs()))) { MenuEntry[] menuEntries = client.getMenuEntries(); final MenuEntry menuEntry = menuEntries[menuEntries.length - 1]; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcMinimapOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcMinimapOverlay.java index fd036adb95..dc6871cfcb 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcMinimapOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcMinimapOverlay.java @@ -68,7 +68,8 @@ public class NpcMinimapOverlay extends Overlay private void renderNpcOverlay(Graphics2D graphics, NPC actor, String name, Color color) { NPCComposition npcComposition = actor.getTransformedComposition(); - if (npcComposition == null || !npcComposition.isInteractible()) + if (npcComposition == null || !npcComposition.isInteractible() + || (actor.isDead() && !config.highlightDeadNpcs())) { return; } 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 b1a5ed8ada..a1d1bffda9 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 @@ -146,7 +146,8 @@ public class NpcSceneOverlay extends Overlay private void renderNpcOverlay(Graphics2D graphics, NPC actor, Color color) { NPCComposition npcComposition = actor.getTransformedComposition(); - if (npcComposition == null || !npcComposition.isInteractible()) + if (npcComposition == null || !npcComposition.isInteractible() + || (actor.isDead() && !config.highlightDeadNpcs())) { return; } From f0cef4589be604013e43db7c170d34f44e4c3078 Mon Sep 17 00:00:00 2001 From: Hydrox6 Date: Wed, 13 May 2020 22:53:03 +0100 Subject: [PATCH 07/12] Add all other pearl rod animations There are 2 animations for each pearl rod (except Oily). Usually it seems that only one is used when actually fishing, which were the ones present before this commit. However, it seems that Jagex is not consistent about what animations are used, as Anglerfish fishing uses the other animation of the normal pearl rod. Given that the other two exist, and they're technically usable (and can be used as the starting animation), it's only a matter of time before Jagex accidentally gets them the wrong way round again, so this is a pre-emptive measure. It also means that the UI won't show "Not Fishing" for a split second when casting out. --- .../src/main/java/net/runelite/api/AnimationID.java | 7 +++++-- .../runelite/client/plugins/fishing/FishingOverlay.java | 3 +++ .../client/plugins/idlenotifier/IdleNotifierPlugin.java | 3 +++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/runelite-api/src/main/java/net/runelite/api/AnimationID.java b/runelite-api/src/main/java/net/runelite/api/AnimationID.java index ca40b93a7e..4d3d6623a5 100644 --- a/runelite-api/src/main/java/net/runelite/api/AnimationID.java +++ b/runelite-api/src/main/java/net/runelite/api/AnimationID.java @@ -121,8 +121,11 @@ public final class AnimationID public static final int FISHING_BAREHAND_CAUGHT_TUNA_1 = 6710; public static final int FISHING_BAREHAND_CAUGHT_TUNA_2 = 6711; public static final int FISHING_PEARL_ROD = 8188; - public static final int FISHING_PEARL_FLY_ROD = 8192; - public static final int FISHING_PEARL_BARBARIAN_ROD = 8193; + public static final int FISHING_PEARL_FLY_ROD = 8189; + public static final int FISHING_PEARL_BARBARIAN_ROD = 8190; + public static final int FISHING_PEARL_ROD_2 = 8191; + public static final int FISHING_PEARL_FLY_ROD_2 = 8192; + public static final int FISHING_PEARL_BARBARIAN_ROD_2 = 8193; public static final int FISHING_PEARL_OILY_ROD = 6932; public static final int MINING_BRONZE_PICKAXE = 625; public static final int MINING_IRON_PICKAXE = 626; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingOverlay.java index a60bed3bab..07d9897fef 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingOverlay.java @@ -73,6 +73,9 @@ class FishingOverlay extends OverlayPanel AnimationID.FISHING_PEARL_ROD, AnimationID.FISHING_PEARL_FLY_ROD, AnimationID.FISHING_PEARL_BARBARIAN_ROD, + AnimationID.FISHING_PEARL_ROD_2, + AnimationID.FISHING_PEARL_FLY_ROD_2, + AnimationID.FISHING_PEARL_BARBARIAN_ROD_2, AnimationID.FISHING_PEARL_OILY_ROD); private final Client client; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPlugin.java index 5c4b78d3a2..1b7c8a2419 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPlugin.java @@ -205,6 +205,9 @@ public class IdleNotifierPlugin extends Plugin case FISHING_PEARL_ROD: case FISHING_PEARL_FLY_ROD: case FISHING_PEARL_BARBARIAN_ROD: + case FISHING_PEARL_ROD_2: + case FISHING_PEARL_FLY_ROD_2: + case FISHING_PEARL_BARBARIAN_ROD_2: case FISHING_PEARL_OILY_ROD: /* Mining(Normal) */ case MINING_BRONZE_PICKAXE: From 2622cc2ac6727c616f4c2e5fc1386e037588f6c6 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 29 May 2020 13:25:20 -0400 Subject: [PATCH 08/12] http-api: use separate class for ge trade history --- .../http/api/ge/GrandExchangeTrade.java | 2 - .../service/ge/GrandExchangeController.java | 6 +-- .../service/ge/GrandExchangeTradeHistory.java | 38 +++++++++++++++++++ 3 files changed, 41 insertions(+), 5 deletions(-) create mode 100644 http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeTradeHistory.java diff --git a/http-api/src/main/java/net/runelite/http/api/ge/GrandExchangeTrade.java b/http-api/src/main/java/net/runelite/http/api/ge/GrandExchangeTrade.java index b5d0012b16..17b6effb0f 100644 --- a/http-api/src/main/java/net/runelite/http/api/ge/GrandExchangeTrade.java +++ b/http-api/src/main/java/net/runelite/http/api/ge/GrandExchangeTrade.java @@ -24,7 +24,6 @@ */ package net.runelite.http.api.ge; -import java.time.Instant; import lombok.Data; @Data @@ -34,5 +33,4 @@ public class GrandExchangeTrade private int itemId; private int quantity; private int price; - private Instant time; } diff --git a/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeController.java b/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeController.java index 94c759b130..ba291385cf 100644 --- a/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeController.java +++ b/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeController.java @@ -69,7 +69,7 @@ public class GrandExchangeController } @GetMapping - public Collection get(HttpServletRequest request, HttpServletResponse response, + public Collection get(HttpServletRequest request, HttpServletResponse response, @RequestParam(required = false, defaultValue = "1024") int limit, @RequestParam(required = false, defaultValue = "0") int offset) throws IOException { @@ -85,9 +85,9 @@ public class GrandExchangeController .collect(Collectors.toList()); } - private static GrandExchangeTrade convert(TradeEntry tradeEntry) + private static GrandExchangeTradeHistory convert(TradeEntry tradeEntry) { - GrandExchangeTrade grandExchangeTrade = new GrandExchangeTrade(); + GrandExchangeTradeHistory grandExchangeTrade = new GrandExchangeTradeHistory(); grandExchangeTrade.setBuy(tradeEntry.getAction() == TradeAction.BUY); grandExchangeTrade.setItemId(tradeEntry.getItem()); grandExchangeTrade.setQuantity(tradeEntry.getQuantity()); diff --git a/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeTradeHistory.java b/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeTradeHistory.java new file mode 100644 index 0000000000..c45f5acf4f --- /dev/null +++ b/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeTradeHistory.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020, 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.http.service.ge; + +import java.time.Instant; +import lombok.Data; + +@Data +class GrandExchangeTradeHistory +{ + private boolean buy; + private int itemId; + private int quantity; + private int price; + private Instant time; +} From 6d46bb09c4c66942fa1cccc966a2ce07e0756b0a Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 29 May 2020 13:45:37 -0400 Subject: [PATCH 09/12] ge plugin: submit trades even when not logged in --- .../net/runelite/http/api/RuneLiteAPI.java | 1 + .../http/api/ge/GrandExchangeClient.java | 21 ++++-- .../grandexchange/GrandExchangePlugin.java | 66 ++++++++++++------- 3 files changed, 61 insertions(+), 27 deletions(-) diff --git a/http-api/src/main/java/net/runelite/http/api/RuneLiteAPI.java b/http-api/src/main/java/net/runelite/http/api/RuneLiteAPI.java index 2f0ba34bc0..0b017518c8 100644 --- a/http-api/src/main/java/net/runelite/http/api/RuneLiteAPI.java +++ b/http-api/src/main/java/net/runelite/http/api/RuneLiteAPI.java @@ -43,6 +43,7 @@ public class RuneLiteAPI private static final Logger logger = LoggerFactory.getLogger(RuneLiteAPI.class); public static final String RUNELITE_AUTH = "RUNELITE-AUTH"; + public static final String RUNELITE_MACHINEID = "RUNELITE-MACHINEID"; public static final OkHttpClient CLIENT; public static final Gson GSON = new Gson(); diff --git a/http-api/src/main/java/net/runelite/http/api/ge/GrandExchangeClient.java b/http-api/src/main/java/net/runelite/http/api/ge/GrandExchangeClient.java index 78e64d383a..fd02f37ffc 100644 --- a/http-api/src/main/java/net/runelite/http/api/ge/GrandExchangeClient.java +++ b/http-api/src/main/java/net/runelite/http/api/ge/GrandExchangeClient.java @@ -27,7 +27,7 @@ package net.runelite.http.api.ge; import com.google.gson.Gson; import java.io.IOException; import java.util.UUID; -import lombok.AllArgsConstructor; +import lombok.Setter; import lombok.extern.slf4j.Slf4j; import net.runelite.http.api.RuneLiteAPI; import static net.runelite.http.api.RuneLiteAPI.JSON; @@ -39,12 +39,14 @@ import okhttp3.RequestBody; import okhttp3.Response; @Slf4j -@AllArgsConstructor public class GrandExchangeClient { private static final Gson GSON = RuneLiteAPI.GSON; - private final UUID uuid; + @Setter + private UUID uuid; + @Setter + private String machineId; public void submit(GrandExchangeTrade grandExchangeTrade) { @@ -52,8 +54,17 @@ public class GrandExchangeClient .addPathSegment("ge") .build(); - Request request = new Request.Builder() - .header(RuneLiteAPI.RUNELITE_AUTH, uuid.toString()) + Request.Builder builder = new Request.Builder(); + if (uuid != null) + { + builder.header(RuneLiteAPI.RUNELITE_AUTH, uuid.toString()); + } + if (machineId != null) + { + builder.header(RuneLiteAPI.RUNELITE_MACHINEID, machineId); + } + + Request request = builder .post(RequestBody.create(JSON, GSON.toJson(grandExchangeTrade))) .url(url) .build(); 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 8215e16675..e43cf40475 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 @@ -29,17 +29,21 @@ package net.runelite.client.plugins.grandexchange; import com.google.common.annotations.VisibleForTesting; +import com.google.common.hash.Hasher; +import com.google.common.hash.Hashing; import com.google.common.primitives.Shorts; import com.google.gson.Gson; import com.google.inject.Provides; import java.awt.Color; import java.awt.image.BufferedImage; import java.io.IOException; +import java.net.NetworkInterface; import java.time.Duration; import java.time.Instant; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; +import java.util.Enumeration; import java.util.List; import java.util.Locale; import java.util.concurrent.ScheduledExecutorService; @@ -80,7 +84,6 @@ import net.runelite.client.account.SessionManager; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.events.ConfigChanged; -import net.runelite.client.events.SessionClose; import net.runelite.client.events.SessionOpen; import net.runelite.client.game.ItemManager; import net.runelite.client.input.KeyManager; @@ -91,6 +94,7 @@ import net.runelite.client.ui.ClientToolbar; import net.runelite.client.ui.NavigationButton; import net.runelite.client.util.ColorUtil; import net.runelite.client.util.ImageUtil; +import net.runelite.client.util.OSType; import net.runelite.client.util.QuantityFormatter; import net.runelite.client.util.Text; import net.runelite.http.api.ge.GrandExchangeClient; @@ -176,10 +180,42 @@ public class GrandExchangePlugin extends Plugin private int osbItem; private OSBGrandExchangeResult osbGrandExchangeResult; + @Inject private GrandExchangeClient grandExchangeClient; + private static String machineUuid; private boolean wasFuzzySearch; + static + { + try + { + Hasher hasher = Hashing.sha256().newHasher(); + Runtime runtime = Runtime.getRuntime(); + + hasher.putByte((byte) OSType.getOSType().ordinal()); + hasher.putByte((byte) runtime.availableProcessors()); + hasher.putUnencodedChars(System.getProperty("os.arch", "")); + hasher.putUnencodedChars(System.getProperty("os.version", "")); + hasher.putUnencodedChars(System.getProperty("user.name", "")); + Enumeration networkInterfaces = NetworkInterface.getNetworkInterfaces(); + while (networkInterfaces.hasMoreElements()) + { + NetworkInterface networkInterface = networkInterfaces.nextElement(); + byte[] hardwareAddress = networkInterface.getHardwareAddress(); + if (hardwareAddress != null) + { + hasher.putBytes(hardwareAddress); + } + } + machineUuid = hasher.hash().toString(); + } + catch (Exception ex) + { + log.warn("unable to generate machine id", ex); + } + } + /** * Logic from {@link org.apache.commons.text.similarity.FuzzyScore} */ @@ -274,8 +310,13 @@ public class GrandExchangePlugin extends Plugin AccountSession accountSession = sessionManager.getAccountSession(); if (accountSession != null) { - grandExchangeClient = new GrandExchangeClient(accountSession.getUuid()); + grandExchangeClient.setUuid(accountSession.getUuid()); } + else + { + grandExchangeClient.setUuid(null); + } + grandExchangeClient.setMachineId(machineUuid); osbItem = -1; osbGrandExchangeResult = null; @@ -289,27 +330,13 @@ public class GrandExchangePlugin extends Plugin keyManager.unregisterKeyListener(inputListener); grandExchangeText = null; grandExchangeItem = null; - grandExchangeClient = null; } @Subscribe public void onSessionOpen(SessionOpen sessionOpen) { AccountSession accountSession = sessionManager.getAccountSession(); - if (accountSession.getUuid() != null) - { - grandExchangeClient = new GrandExchangeClient(accountSession.getUuid()); - } - else - { - grandExchangeClient = null; - } - } - - @Subscribe - public void onSessionClose(SessionClose sessionClose) - { - grandExchangeClient = null; + grandExchangeClient.setUuid(accountSession.getUuid()); } @Subscribe @@ -351,11 +378,6 @@ public class GrandExchangePlugin extends Plugin private void submitTrades(int slot, GrandExchangeOffer offer) { - if (grandExchangeClient == null) - { - return; - } - if (offer.getState() != GrandExchangeOfferState.BOUGHT && offer.getState() != GrandExchangeOfferState.SOLD && offer.getState() != GrandExchangeOfferState.CANCELLED_BUY && offer.getState() != GrandExchangeOfferState.CANCELLED_SELL) { From 17d6921a4a7ad3bdf71f20f937b02163501276a1 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 29 May 2020 13:49:38 -0400 Subject: [PATCH 10/12] ge plugin: submit partially completed trades --- .../http/api/ge/GrandExchangeTrade.java | 3 + .../service/ge/GrandExchangeController.java | 20 +- .../grandexchange/GrandExchangePlugin.java | 90 ++++++--- .../GrandExchangePluginTest.java | 176 ++++++++++++++++++ 4 files changed, 258 insertions(+), 31 deletions(-) diff --git a/http-api/src/main/java/net/runelite/http/api/ge/GrandExchangeTrade.java b/http-api/src/main/java/net/runelite/http/api/ge/GrandExchangeTrade.java index 17b6effb0f..85dccbc793 100644 --- a/http-api/src/main/java/net/runelite/http/api/ge/GrandExchangeTrade.java +++ b/http-api/src/main/java/net/runelite/http/api/ge/GrandExchangeTrade.java @@ -30,7 +30,10 @@ import lombok.Data; public class GrandExchangeTrade { private boolean buy; + private boolean cancel; private int itemId; private int quantity; + private int total; private int price; + private int offer; } diff --git a/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeController.java b/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeController.java index ba291385cf..63555cbe7b 100644 --- a/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeController.java +++ b/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeController.java @@ -29,6 +29,7 @@ import java.util.Collection; import java.util.stream.Collectors; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import net.runelite.http.api.RuneLiteAPI; import net.runelite.http.api.ge.GrandExchangeTrade; import net.runelite.http.service.account.AuthFilter; import net.runelite.http.service.account.beans.SessionEntry; @@ -58,14 +59,23 @@ public class GrandExchangeController @PostMapping public void submit(HttpServletRequest request, HttpServletResponse response, @RequestBody GrandExchangeTrade grandExchangeTrade) throws IOException { - SessionEntry session = authFilter.handle(request, response); - - if (session == null) + SessionEntry session = null; + if (request.getHeader(RuneLiteAPI.RUNELITE_AUTH) != null) { - return; + session = authFilter.handle(request, response); + if (session == null) + { + // error is set here on the response, so we shouldn't continue + return; + } } + Integer userId = session == null ? null : session.getUser(); - grandExchangeService.add(session.getUser(), grandExchangeTrade); + // We don't keep track of pending trades in the web UI, so only add cancelled or completed trades + if (userId != null && (grandExchangeTrade.isCancel() || grandExchangeTrade.getQuantity() == grandExchangeTrade.getTotal())) + { + grandExchangeService.add(userId, grandExchangeTrade); + } } @GetMapping 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 e43cf40475..46dbb93c64 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 @@ -371,39 +371,88 @@ public class GrandExchangePlugin extends Plugin BufferedImage itemImage = itemManager.getImage(offer.getItemId(), offer.getTotalQuantity(), shouldStack); SwingUtilities.invokeLater(() -> panel.getOffersPanel().updateOffer(offerItem, itemImage, offer, slot)); - submitTrades(slot, offer); + submitTrade(slot, offer); updateConfig(slot, offer); } - private void submitTrades(int slot, GrandExchangeOffer offer) + @VisibleForTesting + void submitTrade(int slot, GrandExchangeOffer offer) { - if (offer.getState() != GrandExchangeOfferState.BOUGHT && offer.getState() != GrandExchangeOfferState.SOLD && - offer.getState() != GrandExchangeOfferState.CANCELLED_BUY && offer.getState() != GrandExchangeOfferState.CANCELLED_SELL) - { - return; - } + GrandExchangeOfferState state = offer.getState(); - // Cancelled offers may have been cancelled before buying/selling any items - if (offer.getQuantitySold() == 0) + if (state != GrandExchangeOfferState.CANCELLED_BUY && state != GrandExchangeOfferState.CANCELLED_SELL && state != GrandExchangeOfferState.BUYING && state != GrandExchangeOfferState.SELLING) { return; } SavedOffer savedOffer = getOffer(slot); - if (!shouldUpdate(savedOffer, offer)) + if (savedOffer == null && (state == GrandExchangeOfferState.BUYING || state == GrandExchangeOfferState.SELLING) && offer.getQuantitySold() == 0) + { + // new offer + GrandExchangeTrade grandExchangeTrade = new GrandExchangeTrade(); + grandExchangeTrade.setBuy(state == GrandExchangeOfferState.BUYING); + grandExchangeTrade.setItemId(offer.getItemId()); + grandExchangeTrade.setQuantity(0); + grandExchangeTrade.setTotal(offer.getTotalQuantity()); + grandExchangeTrade.setPrice(0); + grandExchangeTrade.setOffer(offer.getPrice()); + + log.debug("Submitting new trade: {}", grandExchangeTrade); + grandExchangeClient.submit(grandExchangeTrade); + return; + } + + if (savedOffer == null || savedOffer.getItemId() != offer.getItemId() || savedOffer.getPrice() != offer.getPrice() || savedOffer.getTotalQuantity() != offer.getTotalQuantity()) + { + // desync + return; + } + + if (savedOffer.getState() == offer.getState() && savedOffer.getQuantitySold() == offer.getQuantitySold()) + { + // no change + return; + } + + if (state == GrandExchangeOfferState.CANCELLED_BUY || state == GrandExchangeOfferState.CANCELLED_SELL) + { + GrandExchangeTrade grandExchangeTrade = new GrandExchangeTrade(); + grandExchangeTrade.setBuy(state == GrandExchangeOfferState.CANCELLED_BUY); + grandExchangeTrade.setCancel(true); + grandExchangeTrade.setItemId(offer.getItemId()); + grandExchangeTrade.setQuantity(offer.getQuantitySold()); + grandExchangeTrade.setTotal(offer.getTotalQuantity()); + grandExchangeTrade.setPrice(offer.getQuantitySold() > 0 ? offer.getSpent() / offer.getQuantitySold() : 0); + grandExchangeTrade.setOffer(offer.getPrice()); + + log.debug("Submitting cancelled: {}", grandExchangeTrade); + grandExchangeClient.submit(grandExchangeTrade); + return; + } + + final int qty = offer.getQuantitySold() - savedOffer.getQuantitySold(); + if (qty <= 0) { return; } - // getPrice() is the price of the offer, not necessarily what the item bought at - int priceEach = offer.getSpent() / offer.getQuantitySold(); + // offer.getPrice() is the price of the offer, not necessarily what the item bought at, so we compute it + // based on how much was spent & the qty + final int dspent = offer.getSpent() - savedOffer.getSpent(); + final int price = dspent / qty; + if (price <= 0) + { + return; + } GrandExchangeTrade grandExchangeTrade = new GrandExchangeTrade(); - grandExchangeTrade.setBuy(offer.getState() == GrandExchangeOfferState.BOUGHT || offer.getState() == GrandExchangeOfferState.CANCELLED_BUY); + grandExchangeTrade.setBuy(state == GrandExchangeOfferState.BUYING); grandExchangeTrade.setItemId(offer.getItemId()); - grandExchangeTrade.setQuantity(offer.getQuantitySold()); - grandExchangeTrade.setPrice(priceEach); + grandExchangeTrade.setQuantity(qty); + grandExchangeTrade.setTotal(offer.getTotalQuantity()); + grandExchangeTrade.setPrice(price); + grandExchangeTrade.setOffer(offer.getPrice()); log.debug("Submitting trade: {}", grandExchangeTrade); grandExchangeClient.submit(grandExchangeTrade); @@ -430,17 +479,6 @@ public class GrandExchangePlugin extends Plugin } } - private boolean shouldUpdate(SavedOffer savedOffer, GrandExchangeOffer grandExchangeOffer) - { - if (savedOffer == null) - { - return false; - } - - // Only update offer if state has changed - return savedOffer.getState() != grandExchangeOffer.getState(); - } - @Subscribe public void onChatMessage(ChatMessage event) { diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/grandexchange/GrandExchangePluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/grandexchange/GrandExchangePluginTest.java index dc16d25dfc..d95df70528 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/grandexchange/GrandExchangePluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/grandexchange/GrandExchangePluginTest.java @@ -24,14 +24,100 @@ */ package net.runelite.client.plugins.grandexchange; +import com.google.inject.Guice; +import com.google.inject.testing.fieldbinder.Bind; +import com.google.inject.testing.fieldbinder.BoundFieldModule; import java.util.Arrays; import java.util.List; +import java.util.concurrent.ScheduledExecutorService; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.GrandExchangeOffer; +import net.runelite.api.GrandExchangeOfferState; +import net.runelite.api.ItemID; +import net.runelite.client.Notifier; +import net.runelite.client.account.SessionManager; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.config.RuneLiteConfig; +import net.runelite.client.game.ItemManager; +import net.runelite.client.input.KeyManager; +import net.runelite.client.input.MouseManager; import static net.runelite.client.plugins.grandexchange.GrandExchangePlugin.findFuzzyIndices; +import static net.runelite.http.api.RuneLiteAPI.GSON; +import net.runelite.http.api.ge.GrandExchangeClient; +import net.runelite.http.api.ge.GrandExchangeTrade; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import static org.mockito.ArgumentMatchers.any; +import org.mockito.Mock; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import org.mockito.junit.MockitoJUnitRunner; +@RunWith(MockitoJUnitRunner.class) public class GrandExchangePluginTest { + @Inject + private GrandExchangePlugin grandExchangePlugin; + + @Mock + @Bind + private GrandExchangeConfig grandExchangeConfig; + + @Mock + @Bind + private Notifier notifier; + + @Mock + @Bind + private SessionManager sessionManager; + + @Mock + @Bind + private ConfigManager configManager; + + @Mock + @Bind + private ItemManager itemManager; + + @Mock + @Bind + private KeyManager keyManager; + + @Mock + @Bind + private MouseManager mouseManager; + + @Mock + @Bind + private ScheduledExecutorService scheduledExecutorService; + + @Mock + @Bind + private GrandExchangeClient grandExchangeClient; + + @Mock + @Bind + private Client client; + + @Mock + @Bind + private RuneLiteConfig runeLiteConfig; + + @Before + public void setUp() + { + Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this); + when(client.getUsername()).thenReturn("adam"); + } + @Test public void testFindFuzzyIndices() { @@ -39,4 +125,94 @@ public class GrandExchangePluginTest // robe bottom assertEquals(Arrays.asList(11, 12, 15), fuzzyIndices); } + + @Test + public void testSubmitTrade() + { + SavedOffer savedOffer = new SavedOffer(); + savedOffer.setItemId(ItemID.ABYSSAL_WHIP); + savedOffer.setQuantitySold(1); + savedOffer.setTotalQuantity(10); + savedOffer.setPrice(1000); + savedOffer.setSpent(25); + savedOffer.setState(GrandExchangeOfferState.BUYING); + when(configManager.getConfiguration("geoffer.adam", "0")).thenReturn(GSON.toJson(savedOffer)); + + // buy 2 @ 10/ea + GrandExchangeOffer grandExchangeOffer = mock(GrandExchangeOffer.class); + when(grandExchangeOffer.getQuantitySold()).thenReturn(1 + 2); + when(grandExchangeOffer.getItemId()).thenReturn(ItemID.ABYSSAL_WHIP); + when(grandExchangeOffer.getTotalQuantity()).thenReturn(10); + when(grandExchangeOffer.getPrice()).thenReturn(1000); + when(grandExchangeOffer.getSpent()).thenReturn(25 + 10 * 2); + when(grandExchangeOffer.getState()).thenReturn(GrandExchangeOfferState.BUYING); + grandExchangePlugin.submitTrade(0, grandExchangeOffer); + + ArgumentCaptor captor = ArgumentCaptor.forClass(GrandExchangeTrade.class); + verify(grandExchangeClient).submit(captor.capture()); + + GrandExchangeTrade trade = captor.getValue(); + assertTrue(trade.isBuy()); + assertEquals(ItemID.ABYSSAL_WHIP, trade.getItemId()); + assertEquals(2, trade.getQuantity()); + assertEquals(10, trade.getTotal()); + assertEquals(10, trade.getPrice()); + } + + @Test + public void testDuplicateTrade() + { + SavedOffer savedOffer = new SavedOffer(); + savedOffer.setItemId(ItemID.ABYSSAL_WHIP); + savedOffer.setQuantitySold(1); + savedOffer.setTotalQuantity(10); + savedOffer.setPrice(1000); + savedOffer.setSpent(25); + savedOffer.setState(GrandExchangeOfferState.BUYING); + when(configManager.getConfiguration("geoffer.adam", "0")).thenReturn(GSON.toJson(savedOffer)); + + GrandExchangeOffer grandExchangeOffer = mock(GrandExchangeOffer.class); + when(grandExchangeOffer.getQuantitySold()).thenReturn(1); + when(grandExchangeOffer.getItemId()).thenReturn(ItemID.ABYSSAL_WHIP); + when(grandExchangeOffer.getTotalQuantity()).thenReturn(10); + when(grandExchangeOffer.getPrice()).thenReturn(1000); + lenient().when(grandExchangeOffer.getSpent()).thenReturn(25); + when(grandExchangeOffer.getState()).thenReturn(GrandExchangeOfferState.BUYING); + grandExchangePlugin.submitTrade(0, grandExchangeOffer); + + verify(grandExchangeClient, never()).submit(any(GrandExchangeTrade.class)); + } + + @Test + public void testCancelTrade() + { + SavedOffer savedOffer = new SavedOffer(); + savedOffer.setItemId(ItemID.ABYSSAL_WHIP); + savedOffer.setQuantitySold(1); + savedOffer.setTotalQuantity(10); + savedOffer.setPrice(1000); + savedOffer.setSpent(25); + savedOffer.setState(GrandExchangeOfferState.BUYING); + when(configManager.getConfiguration("geoffer.adam", "0")).thenReturn(GSON.toJson(savedOffer)); + + GrandExchangeOffer grandExchangeOffer = mock(GrandExchangeOffer.class); + when(grandExchangeOffer.getQuantitySold()).thenReturn(1); + when(grandExchangeOffer.getItemId()).thenReturn(ItemID.ABYSSAL_WHIP); + when(grandExchangeOffer.getTotalQuantity()).thenReturn(10); + when(grandExchangeOffer.getPrice()).thenReturn(1000); + when(grandExchangeOffer.getSpent()).thenReturn(25); + when(grandExchangeOffer.getState()).thenReturn(GrandExchangeOfferState.CANCELLED_BUY); + grandExchangePlugin.submitTrade(0, grandExchangeOffer); + + ArgumentCaptor captor = ArgumentCaptor.forClass(GrandExchangeTrade.class); + verify(grandExchangeClient).submit(captor.capture()); + + GrandExchangeTrade trade = captor.getValue(); + assertTrue(trade.isBuy()); + assertTrue(trade.isCancel()); + assertEquals(ItemID.ABYSSAL_WHIP, trade.getItemId()); + assertEquals(1, trade.getQuantity()); + assertEquals(10, trade.getTotal()); + assertEquals(25, trade.getPrice()); + } } \ No newline at end of file From 44ea83734629859e7054d9d99d8c6ba18b9e8acc Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 29 May 2020 18:53:10 -0400 Subject: [PATCH 11/12] ge controller: publish trade data to redis --- .../service/ge/GrandExchangeController.java | 26 +++++++++++- .../net/runelite/http/service/ge/Trade.java | 42 +++++++++++++++++++ 2 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 http-service/src/main/java/net/runelite/http/service/ge/Trade.java diff --git a/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeController.java b/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeController.java index 63555cbe7b..cfba3812fb 100644 --- a/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeController.java +++ b/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeController.java @@ -24,6 +24,7 @@ */ package net.runelite.http.service.ge; +import com.google.gson.Gson; import java.io.IOException; import java.util.Collection; import java.util.stream.Collectors; @@ -33,6 +34,7 @@ import net.runelite.http.api.RuneLiteAPI; import net.runelite.http.api.ge.GrandExchangeTrade; import net.runelite.http.service.account.AuthFilter; import net.runelite.http.service.account.beans.SessionEntry; +import net.runelite.http.service.util.redis.RedisPool; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; @@ -41,19 +43,24 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import redis.clients.jedis.Jedis; @RestController @RequestMapping("/ge") public class GrandExchangeController { + private static final Gson GSON = RuneLiteAPI.GSON; + private final GrandExchangeService grandExchangeService; private final AuthFilter authFilter; + private final RedisPool redisPool; @Autowired - public GrandExchangeController(GrandExchangeService grandExchangeService, AuthFilter authFilter) + public GrandExchangeController(GrandExchangeService grandExchangeService, AuthFilter authFilter, RedisPool redisPool) { this.grandExchangeService = grandExchangeService; this.authFilter = authFilter; + this.redisPool = redisPool; } @PostMapping @@ -76,6 +83,23 @@ public class GrandExchangeController { grandExchangeService.add(userId, grandExchangeTrade); } + + Trade trade = new Trade(); + trade.setBuy(grandExchangeTrade.isBuy()); + trade.setCancel(grandExchangeTrade.isCancel()); + trade.setItemId(grandExchangeTrade.getItemId()); + trade.setQuantity(grandExchangeTrade.getQuantity()); + trade.setPrice(grandExchangeTrade.getPrice()); + trade.setOffer(grandExchangeTrade.getOffer()); + trade.setTime((int) (System.currentTimeMillis() / 1000L)); + trade.setMachineId(request.getHeader(RuneLiteAPI.RUNELITE_MACHINEID)); + trade.setUserId(userId); + trade.setIp(request.getHeader("X-Forwarded-For")); + String json = GSON.toJson(trade); + try (Jedis jedis = redisPool.getResource()) + { + jedis.publish("ge", json); + } } @GetMapping diff --git a/http-service/src/main/java/net/runelite/http/service/ge/Trade.java b/http-service/src/main/java/net/runelite/http/service/ge/Trade.java new file mode 100644 index 0000000000..e78f2073a3 --- /dev/null +++ b/http-service/src/main/java/net/runelite/http/service/ge/Trade.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2020, 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.http.service.ge; + +import lombok.Data; + +@Data +class Trade +{ + private boolean buy; + private boolean cancel; + private int itemId; + private int quantity; + private int price; + private int offer; + private int time; + private String machineId; + private Integer userId; + private String ip; +} From 6a2e15643f7815bf32e6ff490242ccfbb39157f2 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 30 May 2020 19:58:20 -0400 Subject: [PATCH 12/12] ge plugin: include world type in trades --- .../http/api/ge/GrandExchangeTrade.java | 2 ++ .../service/ge/GrandExchangeController.java | 2 ++ .../net/runelite/http/service/ge/Trade.java | 2 ++ .../grandexchange/GrandExchangePlugin.java | 22 +++++++++++++++++++ .../GrandExchangePluginTest.java | 3 +++ 5 files changed, 31 insertions(+) diff --git a/http-api/src/main/java/net/runelite/http/api/ge/GrandExchangeTrade.java b/http-api/src/main/java/net/runelite/http/api/ge/GrandExchangeTrade.java index 85dccbc793..a3ef3f484d 100644 --- a/http-api/src/main/java/net/runelite/http/api/ge/GrandExchangeTrade.java +++ b/http-api/src/main/java/net/runelite/http/api/ge/GrandExchangeTrade.java @@ -25,6 +25,7 @@ package net.runelite.http.api.ge; import lombok.Data; +import net.runelite.http.api.worlds.WorldType; @Data public class GrandExchangeTrade @@ -36,4 +37,5 @@ public class GrandExchangeTrade private int total; private int price; private int offer; + private WorldType worldType; } diff --git a/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeController.java b/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeController.java index cfba3812fb..2a67655b6a 100644 --- a/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeController.java +++ b/http-service/src/main/java/net/runelite/http/service/ge/GrandExchangeController.java @@ -95,6 +95,8 @@ public class GrandExchangeController trade.setMachineId(request.getHeader(RuneLiteAPI.RUNELITE_MACHINEID)); trade.setUserId(userId); trade.setIp(request.getHeader("X-Forwarded-For")); + trade.setWorldType(grandExchangeTrade.getWorldType()); + String json = GSON.toJson(trade); try (Jedis jedis = redisPool.getResource()) { diff --git a/http-service/src/main/java/net/runelite/http/service/ge/Trade.java b/http-service/src/main/java/net/runelite/http/service/ge/Trade.java index e78f2073a3..6e71efbb13 100644 --- a/http-service/src/main/java/net/runelite/http/service/ge/Trade.java +++ b/http-service/src/main/java/net/runelite/http/service/ge/Trade.java @@ -25,6 +25,7 @@ package net.runelite.http.service.ge; import lombok.Data; +import net.runelite.http.api.worlds.WorldType; @Data class Trade @@ -39,4 +40,5 @@ class Trade private String machineId; private Integer userId; private String ip; + private WorldType worldType; } 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 46dbb93c64..b421dd7aaf 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 @@ -43,6 +43,7 @@ import java.time.Instant; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; +import java.util.EnumSet; import java.util.Enumeration; import java.util.List; import java.util.Locale; @@ -102,6 +103,7 @@ import net.runelite.http.api.ge.GrandExchangeTrade; import net.runelite.http.api.item.ItemStats; import net.runelite.http.api.osbuddy.OSBGrandExchangeClient; import net.runelite.http.api.osbuddy.OSBGrandExchangeResult; +import net.runelite.http.api.worlds.WorldType; import org.apache.commons.lang3.time.DurationFormatUtils; import org.apache.commons.text.similarity.FuzzyScore; @@ -397,6 +399,7 @@ public class GrandExchangePlugin extends Plugin grandExchangeTrade.setTotal(offer.getTotalQuantity()); grandExchangeTrade.setPrice(0); grandExchangeTrade.setOffer(offer.getPrice()); + grandExchangeTrade.setWorldType(getGeWorldType()); log.debug("Submitting new trade: {}", grandExchangeTrade); grandExchangeClient.submit(grandExchangeTrade); @@ -425,6 +428,7 @@ public class GrandExchangePlugin extends Plugin grandExchangeTrade.setTotal(offer.getTotalQuantity()); grandExchangeTrade.setPrice(offer.getQuantitySold() > 0 ? offer.getSpent() / offer.getQuantitySold() : 0); grandExchangeTrade.setOffer(offer.getPrice()); + grandExchangeTrade.setWorldType(getGeWorldType()); log.debug("Submitting cancelled: {}", grandExchangeTrade); grandExchangeClient.submit(grandExchangeTrade); @@ -453,11 +457,29 @@ public class GrandExchangePlugin extends Plugin grandExchangeTrade.setTotal(offer.getTotalQuantity()); grandExchangeTrade.setPrice(price); grandExchangeTrade.setOffer(offer.getPrice()); + grandExchangeTrade.setWorldType(getGeWorldType()); log.debug("Submitting trade: {}", grandExchangeTrade); grandExchangeClient.submit(grandExchangeTrade); } + private WorldType getGeWorldType() + { + EnumSet worldTypes = client.getWorldType(); + if (worldTypes.contains(net.runelite.api.WorldType.DEADMAN)) + { + return WorldType.DEADMAN; + } + else if (worldTypes.contains(net.runelite.api.WorldType.DEADMAN_TOURNAMENT)) + { + return WorldType.DEADMAN_TOURNAMENT; + } + else + { + return null; + } + } + private void updateConfig(int slot, GrandExchangeOffer offer) { if (offer.getState() == GrandExchangeOfferState.EMPTY) diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/grandexchange/GrandExchangePluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/grandexchange/GrandExchangePluginTest.java index d95df70528..d4afc5cf0e 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/grandexchange/GrandExchangePluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/grandexchange/GrandExchangePluginTest.java @@ -28,6 +28,7 @@ import com.google.inject.Guice; import com.google.inject.testing.fieldbinder.Bind; import com.google.inject.testing.fieldbinder.BoundFieldModule; import java.util.Arrays; +import java.util.EnumSet; import java.util.List; import java.util.concurrent.ScheduledExecutorService; import javax.inject.Inject; @@ -35,6 +36,7 @@ import net.runelite.api.Client; import net.runelite.api.GrandExchangeOffer; import net.runelite.api.GrandExchangeOfferState; import net.runelite.api.ItemID; +import net.runelite.api.WorldType; import net.runelite.client.Notifier; import net.runelite.client.account.SessionManager; import net.runelite.client.config.ConfigManager; @@ -116,6 +118,7 @@ public class GrandExchangePluginTest { Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this); when(client.getUsername()).thenReturn("adam"); + when(client.getWorldType()).thenReturn(EnumSet.noneOf(WorldType.class)); } @Test