ge plugin: better handle trades updating on login
After login there are two sets of offer updates, I suspect the first is from the server and the second is from the ge server - this also flags ge server trade updates as on login. To do this we assume it always happens in the first few ticks after the login burst.
This commit is contained in:
@@ -119,7 +119,9 @@ import org.apache.commons.text.similarity.FuzzyScore;
|
||||
@Slf4j
|
||||
public class GrandExchangePlugin extends Plugin
|
||||
{
|
||||
private static final int GE_SLOTS = 8;
|
||||
@VisibleForTesting
|
||||
static final int GE_SLOTS = 8;
|
||||
private static final int GE_LOGIN_BURST_WINDOW = 2; // ticks
|
||||
private static final int OFFER_CONTAINER_ITEM = 21;
|
||||
private static final int OFFER_DEFAULT_ITEM_ID = 6512;
|
||||
private static final String OSB_GE_TEXT = "<br>OSBuddy Actively traded price: ";
|
||||
@@ -141,6 +143,7 @@ public class GrandExchangePlugin extends Plugin
|
||||
private NavigationButton button;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
@Setter(AccessLevel.PACKAGE)
|
||||
private GrandExchangePanel panel;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
@@ -189,7 +192,7 @@ public class GrandExchangePlugin extends Plugin
|
||||
|
||||
@Inject
|
||||
private GrandExchangeClient grandExchangeClient;
|
||||
private boolean loginBurstGeUpdates;
|
||||
private int lastLoginTick;
|
||||
|
||||
@Inject
|
||||
private OSBGrandExchangeClient osbGrandExchangeClient;
|
||||
@@ -314,6 +317,8 @@ public class GrandExchangePlugin extends Plugin
|
||||
|
||||
osbItem = -1;
|
||||
osbGrandExchangeResult = null;
|
||||
|
||||
lastLoginTick = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -370,12 +375,12 @@ public class GrandExchangePlugin extends Plugin
|
||||
if (offer.getState() == GrandExchangeOfferState.EMPTY && client.getGameState() != GameState.LOGGED_IN)
|
||||
{
|
||||
// Trades are cleared by the client during LOGIN_SCREEN/HOPPING/LOGGING_IN, ignore those so we don't
|
||||
// zero and re-submit the trade on login as an update
|
||||
// clear the offer config.
|
||||
return;
|
||||
}
|
||||
|
||||
log.debug("GE offer updated: state: {}, slot: {}, item: {}, qty: {}, login: {}",
|
||||
offer.getState(), slot, offer.getItemId(), offer.getQuantitySold(), loginBurstGeUpdates);
|
||||
log.debug("GE offer updated: state: {}, slot: {}, item: {}, qty: {}, lastLoginTick: {}",
|
||||
offer.getState(), slot, offer.getItemId(), offer.getQuantitySold(), lastLoginTick);
|
||||
|
||||
ItemComposition offerItem = itemManager.getItemComposition(offer.getItemId());
|
||||
boolean shouldStack = offerItem.isStackable() || offer.getTotalQuantity() > 1;
|
||||
@@ -385,11 +390,6 @@ public class GrandExchangePlugin extends Plugin
|
||||
submitTrade(slot, offer);
|
||||
|
||||
updateConfig(slot, offer);
|
||||
|
||||
if (loginBurstGeUpdates && slot == GE_SLOTS - 1) // slots are sent sequentially on login; this is the last one
|
||||
{
|
||||
loginBurstGeUpdates = false;
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -403,6 +403,7 @@ public class GrandExchangePlugin extends Plugin
|
||||
}
|
||||
|
||||
SavedOffer savedOffer = getOffer(slot);
|
||||
boolean login = client.getTickCount() <= lastLoginTick + GE_LOGIN_BURST_WINDOW;
|
||||
if (savedOffer == null && (state == GrandExchangeOfferState.BUYING || state == GrandExchangeOfferState.SELLING) && offer.getQuantitySold() == 0)
|
||||
{
|
||||
// new offer
|
||||
@@ -413,7 +414,7 @@ public class GrandExchangePlugin extends Plugin
|
||||
grandExchangeTrade.setOffer(offer.getPrice());
|
||||
grandExchangeTrade.setSlot(slot);
|
||||
grandExchangeTrade.setWorldType(getGeWorldType());
|
||||
grandExchangeTrade.setLogin(loginBurstGeUpdates);
|
||||
grandExchangeTrade.setLogin(login);
|
||||
|
||||
log.debug("Submitting new trade: {}", grandExchangeTrade);
|
||||
grandExchangeClient.submit(grandExchangeTrade);
|
||||
@@ -444,7 +445,7 @@ public class GrandExchangePlugin extends Plugin
|
||||
grandExchangeTrade.setOffer(offer.getPrice());
|
||||
grandExchangeTrade.setSlot(slot);
|
||||
grandExchangeTrade.setWorldType(getGeWorldType());
|
||||
grandExchangeTrade.setLogin(loginBurstGeUpdates);
|
||||
grandExchangeTrade.setLogin(login);
|
||||
|
||||
log.debug("Submitting cancelled: {}", grandExchangeTrade);
|
||||
grandExchangeClient.submit(grandExchangeTrade);
|
||||
@@ -469,7 +470,7 @@ public class GrandExchangePlugin extends Plugin
|
||||
grandExchangeTrade.setOffer(offer.getPrice());
|
||||
grandExchangeTrade.setSlot(slot);
|
||||
grandExchangeTrade.setWorldType(getGeWorldType());
|
||||
grandExchangeTrade.setLogin(loginBurstGeUpdates);
|
||||
grandExchangeTrade.setLogin(login);
|
||||
|
||||
log.debug("Submitting trade: {}", grandExchangeTrade);
|
||||
grandExchangeClient.submit(grandExchangeTrade);
|
||||
@@ -532,14 +533,19 @@ public class GrandExchangePlugin extends Plugin
|
||||
@Subscribe
|
||||
public void onGameStateChanged(GameStateChanged gameStateChanged)
|
||||
{
|
||||
if (gameStateChanged.getGameState() == GameState.LOGIN_SCREEN)
|
||||
switch (gameStateChanged.getGameState())
|
||||
{
|
||||
panel.getOffersPanel().resetOffers();
|
||||
loginBurstGeUpdates = true;
|
||||
}
|
||||
else if (gameStateChanged.getGameState() == GameState.LOGGED_IN)
|
||||
{
|
||||
grandExchangeClient.setMachineId(getMachineUuid());
|
||||
case LOGIN_SCREEN:
|
||||
panel.getOffersPanel().resetOffers();
|
||||
break;
|
||||
case LOGGING_IN:
|
||||
case HOPPING:
|
||||
case CONNECTION_LOST:
|
||||
lastLoginTick = client.getTickCount();
|
||||
break;
|
||||
case LOGGED_IN:
|
||||
grandExchangeClient.setMachineId(getMachineUuid());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,15 +29,19 @@ 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.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.GrandExchangeOffer;
|
||||
import net.runelite.api.GrandExchangeOfferState;
|
||||
import net.runelite.api.ItemComposition;
|
||||
import net.runelite.api.ItemID;
|
||||
import net.runelite.api.WorldType;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.GrandExchangeOfferChanged;
|
||||
import net.runelite.client.Notifier;
|
||||
import net.runelite.client.account.SessionManager;
|
||||
@@ -52,14 +56,18 @@ import net.runelite.http.api.ge.GrandExchangeClient;
|
||||
import net.runelite.http.api.ge.GrandExchangeTrade;
|
||||
import net.runelite.http.api.osbuddy.OSBGrandExchangeClient;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
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 static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import org.mockito.Mock;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.lenient;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
@@ -243,4 +251,82 @@ public class GrandExchangePluginTest
|
||||
|
||||
verify(configManager, never()).unsetRSProfileConfiguration(anyString(), anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLogin()
|
||||
{
|
||||
GrandExchangePanel panel = mock(GrandExchangePanel.class);
|
||||
when(panel.getOffersPanel()).thenReturn(mock(GrandExchangeOffersPanel.class));
|
||||
grandExchangePlugin.setPanel(panel);
|
||||
|
||||
when(itemManager.getItemComposition(anyInt())).thenReturn(mock(ItemComposition.class));
|
||||
|
||||
// provide config support so getOffer and setOffer work
|
||||
final Map<String, Object> config = new HashMap<>();
|
||||
doAnswer(a ->
|
||||
{
|
||||
Object[] arguments = a.getArguments();
|
||||
config.put((String) arguments[1], arguments[2]);
|
||||
return null;
|
||||
}).when(configManager).setRSProfileConfiguration(eq("geoffer"), anyString(), anyString());
|
||||
|
||||
when(configManager.getRSProfileConfiguration(eq("geoffer"), anyString())).thenAnswer(a ->
|
||||
{
|
||||
Object[] arguments = a.getArguments();
|
||||
return config.get((String) arguments[1]);
|
||||
});
|
||||
|
||||
// set loginBurstGeUpdates
|
||||
GameStateChanged gameStateChanged = new GameStateChanged();
|
||||
gameStateChanged.setGameState(GameState.LOGIN_SCREEN);
|
||||
|
||||
grandExchangePlugin.onGameStateChanged(gameStateChanged);
|
||||
|
||||
// 8x buy 10 whip @ 1k ea, bought 1 sofar.
|
||||
for (int i = 0; i < GrandExchangePlugin.GE_SLOTS; ++i)
|
||||
{
|
||||
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(1000);
|
||||
when(grandExchangeOffer.getState()).thenReturn(GrandExchangeOfferState.SELLING);
|
||||
|
||||
GrandExchangeOfferChanged grandExchangeOfferChanged = new GrandExchangeOfferChanged();
|
||||
grandExchangeOfferChanged.setSlot(i);
|
||||
grandExchangeOfferChanged.setOffer(grandExchangeOffer);
|
||||
grandExchangePlugin.onGrandExchangeOfferChanged(grandExchangeOfferChanged);
|
||||
}
|
||||
|
||||
// Now send update for one of the slots
|
||||
GrandExchangeOffer grandExchangeOffer = mock(GrandExchangeOffer.class);
|
||||
when(grandExchangeOffer.getQuantitySold()).thenReturn(2);
|
||||
when(grandExchangeOffer.getItemId()).thenReturn(ItemID.ABYSSAL_WHIP);
|
||||
when(grandExchangeOffer.getTotalQuantity()).thenReturn(10);
|
||||
when(grandExchangeOffer.getPrice()).thenReturn(1000);
|
||||
when(grandExchangeOffer.getSpent()).thenReturn(2000);
|
||||
when(grandExchangeOffer.getState()).thenReturn(GrandExchangeOfferState.SELLING);
|
||||
|
||||
GrandExchangeOfferChanged grandExchangeOfferChanged = new GrandExchangeOfferChanged();
|
||||
grandExchangeOfferChanged.setSlot(2);
|
||||
grandExchangeOfferChanged.setOffer(grandExchangeOffer);
|
||||
grandExchangePlugin.onGrandExchangeOfferChanged(grandExchangeOfferChanged);
|
||||
|
||||
// verify trade update
|
||||
ArgumentCaptor<GrandExchangeTrade> captor = ArgumentCaptor.forClass(GrandExchangeTrade.class);
|
||||
verify(grandExchangeClient).submit(captor.capture());
|
||||
|
||||
GrandExchangeTrade trade = captor.getValue();
|
||||
assertFalse(trade.isBuy());
|
||||
assertEquals(ItemID.ABYSSAL_WHIP, trade.getItemId());
|
||||
assertEquals(2, trade.getQty());
|
||||
assertEquals(1, trade.getDqty());
|
||||
assertEquals(10, trade.getTotal());
|
||||
assertEquals(1000, trade.getDspent());
|
||||
assertEquals(2000, trade.getSpent());
|
||||
assertEquals(1000, trade.getOffer());
|
||||
assertEquals(2, trade.getSlot());
|
||||
assertTrue(trade.isLogin());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user