Hiscore plugin: lookup menu item (#22)
Hiscore plugin: lookup menu item
This commit is contained in:
@@ -204,6 +204,26 @@ public class Client
|
||||
return client.getWidgetPositionsY();
|
||||
}
|
||||
|
||||
public String[] getPlayerOptions()
|
||||
{
|
||||
return client.getPlayerOptions();
|
||||
}
|
||||
|
||||
public boolean[] getPlayerOptionsPriorities()
|
||||
{
|
||||
return client.getPlayerOptionsPriorities();
|
||||
}
|
||||
|
||||
public int[] getPlayerMenuType()
|
||||
{
|
||||
return client.getPlayerMenuTypes();
|
||||
}
|
||||
|
||||
public String[] getMenuOptions()
|
||||
{
|
||||
return client.getMenuOptions();
|
||||
}
|
||||
|
||||
public int getMapScale()
|
||||
{
|
||||
return client.getMapScale();
|
||||
|
||||
@@ -37,6 +37,7 @@ import javax.imageio.ImageIO;
|
||||
import joptsimple.OptionParser;
|
||||
import joptsimple.OptionSet;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.client.menus.MenuManager;
|
||||
import net.runelite.client.plugins.PluginManager;
|
||||
import net.runelite.client.ui.ClientUI;
|
||||
import net.runelite.client.ui.overlay.OverlayRenderer;
|
||||
@@ -59,6 +60,7 @@ public class RuneLite
|
||||
|
||||
private ClientUI gui;
|
||||
private PluginManager pluginManager;
|
||||
private MenuManager menuManager = new MenuManager(this);
|
||||
private OverlayRenderer renderer;
|
||||
private EventBus eventBus = new EventBus(this::eventExceptionHandler);
|
||||
private final ScheduledExecutorService executor = Executors.newScheduledThreadPool(4);
|
||||
@@ -89,6 +91,8 @@ public class RuneLite
|
||||
{
|
||||
gui = new ClientUI();
|
||||
|
||||
eventBus.register(menuManager);
|
||||
|
||||
if (SystemTray.isSupported())
|
||||
{
|
||||
SystemTray systemTray = SystemTray.getSystemTray();
|
||||
@@ -134,6 +138,11 @@ public class RuneLite
|
||||
return pluginManager;
|
||||
}
|
||||
|
||||
public MenuManager getMenuManager()
|
||||
{
|
||||
return menuManager;
|
||||
}
|
||||
|
||||
public OverlayRenderer getRenderer()
|
||||
{
|
||||
return renderer;
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Robin <robin.weymans@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.client.events;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author robin
|
||||
*/
|
||||
public class MenuOptionClicked
|
||||
{
|
||||
private String menuOption;
|
||||
private String menuTarget;
|
||||
private int menuAction;
|
||||
|
||||
public String getMenuOption()
|
||||
{
|
||||
return menuOption;
|
||||
}
|
||||
|
||||
public void setMenuOption(String menuOption)
|
||||
{
|
||||
this.menuOption = menuOption;
|
||||
}
|
||||
|
||||
public String getMenuTarget()
|
||||
{
|
||||
return menuTarget;
|
||||
}
|
||||
|
||||
public void setMenuTarget(String menuTarget)
|
||||
{
|
||||
this.menuTarget = menuTarget;
|
||||
}
|
||||
|
||||
public int getMenuAction()
|
||||
{
|
||||
return menuAction;
|
||||
}
|
||||
|
||||
public void setMenuAction(int menuAction)
|
||||
{
|
||||
this.menuAction = menuAction;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.client.events;
|
||||
|
||||
public class PlayerMenuOptionClicked
|
||||
{
|
||||
private String menuOption;
|
||||
private String menuTarget;
|
||||
|
||||
public String getMenuOption()
|
||||
{
|
||||
return menuOption;
|
||||
}
|
||||
|
||||
public void setMenuOption(String menuOption)
|
||||
{
|
||||
this.menuOption = menuOption;
|
||||
}
|
||||
|
||||
public String getMenuTarget()
|
||||
{
|
||||
return menuTarget;
|
||||
}
|
||||
|
||||
public void setMenuTarget(String menuTarget)
|
||||
{
|
||||
this.menuTarget = menuTarget;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Robin <robin.weymans@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.client.events;
|
||||
|
||||
public class PlayerMenuOptionsChanged
|
||||
{
|
||||
/**
|
||||
* Index in playerOptions which changed
|
||||
*/
|
||||
private int index;
|
||||
|
||||
public int getIndex()
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
public void setIndex(int index)
|
||||
{
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Robin <robin.weymans@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.client.menus;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.client.RuneLite;
|
||||
import net.runelite.client.events.MenuOptionClicked;
|
||||
import net.runelite.client.events.PlayerMenuOptionClicked;
|
||||
import net.runelite.client.events.PlayerMenuOptionsChanged;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class MenuManager
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(MenuManager.class);
|
||||
|
||||
/* 1007 is the highest number the rs client uses for actions. There is no way to see which ones are used,
|
||||
* so im starting from 1500. Its just a number well over their maximum, so if a new action gets added, chances are little
|
||||
* it interferes with the action the MenuManager uses.
|
||||
*/
|
||||
private static final int MENU_ACTION = 1500;
|
||||
|
||||
/*
|
||||
* The index needs to be between 4 and 7,
|
||||
*/
|
||||
private static final int IDX_LOWER = 4;
|
||||
private static final int IDX_UPPER = 8;
|
||||
|
||||
private final RuneLite runeLite;
|
||||
|
||||
//Maps the indexes that are being used to the menu option.
|
||||
private final Map<Integer, String> playerMenuIndexMap = new HashMap<>();
|
||||
|
||||
public MenuManager(RuneLite runeLite)
|
||||
{
|
||||
this.runeLite = runeLite;
|
||||
}
|
||||
|
||||
public void addPlayerMenuItem(String menuText)
|
||||
{
|
||||
Preconditions.checkNotNull(menuText);
|
||||
|
||||
int playerMenuIndex = findEmptyPlayerMenuIndex();
|
||||
if (playerMenuIndex == IDX_UPPER)
|
||||
{
|
||||
return; // no more slots
|
||||
}
|
||||
|
||||
addPlayerMenuItem(playerMenuIndex, menuText);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onPlayerMenuOptionsChanged(PlayerMenuOptionsChanged event)
|
||||
{
|
||||
int idx = event.getIndex();
|
||||
|
||||
String menuText = playerMenuIndexMap.get(idx);
|
||||
if (menuText == null)
|
||||
{
|
||||
return; // not our menu
|
||||
}
|
||||
|
||||
// find new index for this option
|
||||
int newIdx = findEmptyPlayerMenuIndex();
|
||||
if (newIdx == IDX_UPPER)
|
||||
{
|
||||
logger.debug("Client has updated player menu index {} where option {} was, and there are no more free slots available", idx, menuText);
|
||||
return;
|
||||
}
|
||||
|
||||
logger.debug("Client has updated player menu index {} where option {} was, moving to index {}", idx, menuText, newIdx);
|
||||
|
||||
playerMenuIndexMap.remove(idx);
|
||||
addPlayerMenuItem(newIdx, menuText);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onMenuOptionClicked(MenuOptionClicked event)
|
||||
{
|
||||
if (event.getMenuAction() != MENU_ACTION)
|
||||
{
|
||||
return; // not a player menu
|
||||
}
|
||||
|
||||
String target = event.getMenuTarget();
|
||||
String username = target.split("[<>]")[2]; // <col=ffffff>username<col=40ff00> (level-42)
|
||||
|
||||
PlayerMenuOptionClicked playerMenuOptionClicked = new PlayerMenuOptionClicked();
|
||||
playerMenuOptionClicked.setMenuOption(event.getMenuOption());
|
||||
playerMenuOptionClicked.setMenuTarget(username);
|
||||
|
||||
runeLite.getEventBus().post(playerMenuOptionClicked);
|
||||
}
|
||||
|
||||
private void addPlayerMenuItem(int playerOptionIndex, String menuText)
|
||||
{
|
||||
Client client = RuneLite.getClient();
|
||||
|
||||
client.getPlayerOptions()[playerOptionIndex] = menuText;
|
||||
client.getPlayerOptionsPriorities()[playerOptionIndex] = true;
|
||||
client.getPlayerMenuType()[playerOptionIndex] = MENU_ACTION;
|
||||
|
||||
playerMenuIndexMap.put(playerOptionIndex, menuText);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the next empty player menu slot index
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private int findEmptyPlayerMenuIndex()
|
||||
{
|
||||
int index = IDX_LOWER;
|
||||
|
||||
String[] playerOptions = RuneLite.getClient().getPlayerOptions();
|
||||
while (index < IDX_UPPER && playerOptions[index] != null)
|
||||
{
|
||||
index++;
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
}
|
||||
@@ -24,12 +24,15 @@
|
||||
*/
|
||||
package net.runelite.client.plugins.hiscore;
|
||||
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.ImageIcon;
|
||||
import net.runelite.client.RuneLite;
|
||||
import net.runelite.client.events.PlayerMenuOptionClicked;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.ui.ClientUI;
|
||||
import net.runelite.client.ui.NavigationButton;
|
||||
@@ -41,10 +44,13 @@ public class Hiscore extends Plugin implements ActionListener
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(Hiscore.class);
|
||||
|
||||
private static final String LOOKUP = "Lookup";
|
||||
|
||||
private final NavigationButton navButton = new NavigationButton("Hiscore");
|
||||
private final HiscorePanel hiscorePanel = new HiscorePanel();
|
||||
|
||||
private final ClientUI ui = RuneLite.getRunelite().getGui();
|
||||
private final RuneLite runeLite = RuneLite.getRunelite();
|
||||
private final ClientUI ui = runeLite.getGui();
|
||||
|
||||
public Hiscore()
|
||||
{
|
||||
@@ -61,6 +67,8 @@ public class Hiscore extends Plugin implements ActionListener
|
||||
}
|
||||
|
||||
ui.getNavigationPanel().addNavigation(navButton);
|
||||
|
||||
runeLite.getMenuManager().addPlayerMenuItem(LOOKUP);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -76,4 +84,14 @@ public class Hiscore extends Plugin implements ActionListener
|
||||
ui.expand();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onLookupMenuClicked(PlayerMenuOptionClicked event)
|
||||
{
|
||||
if (event.getMenuOption().equals(LOOKUP))
|
||||
{
|
||||
ScheduledExecutorService executor = runeLite.getExecutor();
|
||||
executor.execute(() -> hiscorePanel.lookup(event.getMenuTarget()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -150,6 +150,12 @@ public class HiscorePanel extends PluginPanel
|
||||
return iconLevel;
|
||||
}
|
||||
|
||||
public void lookup(String username)
|
||||
{
|
||||
input.setText(username);
|
||||
lookup();
|
||||
}
|
||||
|
||||
private void lookup()
|
||||
{
|
||||
String lookup = input.getText();
|
||||
|
||||
@@ -27,6 +27,8 @@ package net.runelite.inject.callbacks;
|
||||
import net.runelite.client.RuneLite;
|
||||
import net.runelite.client.events.ExperienceChanged;
|
||||
import net.runelite.client.events.MapRegionChanged;
|
||||
import net.runelite.client.events.MenuOptionClicked;
|
||||
import net.runelite.client.events.PlayerMenuOptionsChanged;
|
||||
import net.runelite.client.events.AnimationChanged;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -61,6 +63,13 @@ public class Hooks
|
||||
runelite.getEventBus().post(regionChanged);
|
||||
break;
|
||||
}
|
||||
case "playerMenuOptionsChanged":
|
||||
{
|
||||
PlayerMenuOptionsChanged optionsChanged = new PlayerMenuOptionsChanged();
|
||||
optionsChanged.setIndex(idx);
|
||||
runelite.getEventBus().post(optionsChanged);
|
||||
break;
|
||||
}
|
||||
case "animationChanged":
|
||||
{
|
||||
AnimationChanged animationChange = new AnimationChanged();
|
||||
@@ -74,8 +83,32 @@ public class Hooks
|
||||
}
|
||||
|
||||
if (object != null)
|
||||
{
|
||||
logger.trace("Event {} (idx {}) triggered on {}", name, idx, object);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.trace("Event {} (idx {}) triggered", name, idx);
|
||||
}
|
||||
}
|
||||
|
||||
public static void menuActionHook(int var0, int var1, int menuAction, int var3, String menuOption, String menuTarget, int var6, int var7)
|
||||
{
|
||||
/* Along the way, the RuneScape client may change a menuAction by incrementing it with 2000.
|
||||
* I have no idea why, but it does. Their code contains the same conditional statement.
|
||||
*/
|
||||
if (menuAction >= 2000)
|
||||
{
|
||||
menuAction -= 2000;
|
||||
}
|
||||
|
||||
logger.debug("Menu action clicked: {} ({}) on {}", menuOption, menuAction, menuTarget.isEmpty() ? "<nothing>" : menuTarget);
|
||||
|
||||
MenuOptionClicked playerMenuOptionClicked = new MenuOptionClicked();
|
||||
playerMenuOptionClicked.setMenuOption(menuOption);
|
||||
playerMenuOptionClicked.setMenuTarget(menuTarget);
|
||||
playerMenuOptionClicked.setMenuAction(menuAction);
|
||||
|
||||
runelite.getEventBus().post(playerMenuOptionClicked);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,8 +125,14 @@ public interface Client extends GameEngine
|
||||
@Import(value = "username", setter = true)
|
||||
void setUsername(String username);
|
||||
|
||||
@Import("menuActions")
|
||||
String[] getMenuActions();
|
||||
@Import("playerOptions")
|
||||
String[] getPlayerOptions();
|
||||
|
||||
@Import("playerOptionsPriorities")
|
||||
boolean[] getPlayerOptionsPriorities();
|
||||
|
||||
@Import("playerMenuTypes")
|
||||
int[] getPlayerMenuTypes();
|
||||
|
||||
@Import("menuTargets")
|
||||
String[] getMenuTargets();
|
||||
|
||||
Reference in New Issue
Block a user