plugins: readd quest list plugin

This adds back the quest search functionality which is not included in vanilla now
This commit is contained in:
Adam
2022-03-25 10:34:47 -04:00
parent b640c22c75
commit eaf2f462bb
7 changed files with 377 additions and 0 deletions

View File

@@ -0,0 +1,218 @@
/*
* Copyright (c) 2019 Spudjb <https://github.com/spudjb>
* Copyright (c) 2022 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.plugins.questlist;
import com.google.common.base.Strings;
import javax.inject.Inject;
import net.runelite.api.Client;
import net.runelite.api.ParamID;
import net.runelite.api.ScriptID;
import net.runelite.api.SoundEffectID;
import net.runelite.api.SpriteID;
import net.runelite.api.VarClientInt;
import net.runelite.api.Varbits;
import net.runelite.api.events.ScriptCallbackEvent;
import net.runelite.api.events.ScriptPostFired;
import net.runelite.api.events.VarClientIntChanged;
import net.runelite.api.events.VarbitChanged;
import net.runelite.api.widgets.JavaScriptCallback;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetInfo;
import net.runelite.api.widgets.WidgetPositionMode;
import net.runelite.api.widgets.WidgetType;
import net.runelite.client.callback.ClientThread;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.game.chatbox.ChatboxPanelManager;
import net.runelite.client.game.chatbox.ChatboxTextInput;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
@PluginDescriptor(
name = "Quest List",
description = "Adds a search filter to the quest list"
)
public class QuestListPlugin extends Plugin
{
private static final String MENU_OPEN = "Open";
private static final String MENU_CLOSE = "Close";
private static final String MENU_SEARCH = "Search";
@Inject
private Client client;
@Inject
private ChatboxPanelManager chatboxPanelManager;
@Inject
private ClientThread clientThread;
private ChatboxTextInput searchInput;
private Widget questSearchButton;
@Override
protected void startUp()
{
clientThread.invoke(this::addQuestButtons);
}
@Override
protected void shutDown()
{
Widget header = client.getWidget(WidgetInfo.QUESTLIST_BOX);
if (header != null)
{
header.deleteAllChildren();
}
}
@Subscribe
public void onScriptPostFired(ScriptPostFired event)
{
if (event.getScriptId() == ScriptID.QUESTLIST_INIT)
{
addQuestButtons();
}
}
private void addQuestButtons()
{
Widget header = client.getWidget(WidgetInfo.QUESTLIST_BOX);
if (header != null)
{
header.deleteAllChildren();
questSearchButton = header.createChild(-1, WidgetType.GRAPHIC);
questSearchButton.setSpriteId(SpriteID.GE_SEARCH);
questSearchButton.setOriginalWidth(18);
questSearchButton.setOriginalHeight(17);
questSearchButton.setXPositionMode(WidgetPositionMode.ABSOLUTE_RIGHT);
questSearchButton.setOriginalX(5);
questSearchButton.setOriginalY(0);
questSearchButton.setHasListener(true);
questSearchButton.setAction(1, MENU_OPEN);
questSearchButton.setOnOpListener((JavaScriptCallback) e -> openSearch());
questSearchButton.setName(MENU_SEARCH);
questSearchButton.revalidate();
}
}
@Subscribe
public void onVarbitChanged(VarbitChanged varbitChanged)
{
if (isChatboxOpen() && !isOnQuestTab())
{
chatboxPanelManager.close();
}
}
@Subscribe
public void onVarClientIntChanged(VarClientIntChanged varClientIntChanged)
{
if (varClientIntChanged.getIndex() == VarClientInt.INVENTORY_TAB.getIndex())
{
if (isChatboxOpen() && !isOnQuestTab())
{
chatboxPanelManager.close();
}
}
}
@Subscribe
public void onScriptCallbackEvent(ScriptCallbackEvent scriptCallbackEvent)
{
if (!"questFilter".equals(scriptCallbackEvent.getEventName()) || !isChatboxOpen())
{
return;
}
final String filter = searchInput.getValue();
if (Strings.isNullOrEmpty(filter))
{
return;
}
final int[] intStack = client.getIntStack();
final int intStackSize = client.getIntStackSize();
final int questStruct = intStack[intStackSize - 1];
final String questName = client.getStructComposition(questStruct)
.getStringValue(ParamID.QUEST_NAME);
intStack[intStackSize - 2] = questName.toLowerCase().contains(filter.toLowerCase()) ? 0 : 1;
}
private boolean isOnQuestTab()
{
return client.getVar(Varbits.QUEST_TAB) == 0 && client.getVar(VarClientInt.INVENTORY_TAB) == 2;
}
private boolean isChatboxOpen()
{
return searchInput != null && chatboxPanelManager.getCurrentInput() == searchInput;
}
private void closeSearch()
{
chatboxPanelManager.close();
redrawQuests();
client.playSoundEffect(SoundEffectID.UI_BOOP);
}
private void openSearch()
{
client.playSoundEffect(SoundEffectID.UI_BOOP);
questSearchButton.setAction(1, MENU_CLOSE);
questSearchButton.setOnOpListener((JavaScriptCallback) e -> closeSearch());
searchInput = chatboxPanelManager.openTextInput("Search quest list")
.onChanged(s -> redrawQuests())
.onDone(s -> false)
.onClose(() ->
{
redrawQuests();
questSearchButton.setOnOpListener((JavaScriptCallback) e -> openSearch());
questSearchButton.setAction(1, MENU_OPEN);
})
.build();
}
private void redrawQuests()
{
Widget w = client.getWidget(WidgetInfo.QUESTLIST_CONTAINER);
if (w == null)
{
return;
}
Object[] onVarTransmitListener = w.getOnVarTransmitListener();
if (onVarTransmitListener == null)
{
return;
}
clientThread.invokeLater(() ->
client.runScript(onVarTransmitListener));
}
}

View File

@@ -0,0 +1 @@
3FA5FFC8DB18A42971CED41A9BC7CEA407A0EC98061D56B2822F66CD910E4BAF

View File

@@ -0,0 +1,129 @@
.id 3238
.int_stack_count 4
.string_stack_count 0
.int_var_count 5 ; +1 for filter result
.string_var_count 0
iconst -1 ; set to 1 to hide, 0 to show
iload 0 ; quest struct
sconst "questFilter"
runelite_callback
pop_int ; quest struct
istore 4 ; save result
; compare with -1
iload 4 ; load result
iconst -1
if_icmpeq continue
; return value
iload 4
return
continue:
iload 0
iconst 611
struct_param
iconst 1
if_icmpeq LABEL6
jump LABEL12
LABEL6:
invoke 4025
iconst 1
if_icmpeq LABEL10
jump LABEL12
LABEL10:
iconst 1
return
LABEL12:
iload 0
iconst 611
struct_param
iconst 0
if_icmpeq LABEL18
jump LABEL24
LABEL18:
get_varbit 13774
iconst 1
if_icmpeq LABEL22
jump LABEL24
LABEL22:
iconst 1
return
LABEL24:
iload 1
iconst 0
if_icmpeq LABEL28
jump LABEL34
LABEL28:
get_varbit 13775
iconst 1
if_icmpeq LABEL32
jump LABEL34
LABEL32:
iconst 1
return
LABEL34:
iload 1
iconst 1
if_icmpeq LABEL38
jump LABEL44
LABEL38:
get_varbit 13776
iconst 1
if_icmpeq LABEL42
jump LABEL44
LABEL42:
iconst 1
return
LABEL44:
iload 1
iconst 2
if_icmpeq LABEL48
jump LABEL54
LABEL48:
get_varbit 13777
iconst 1
if_icmpeq LABEL52
jump LABEL54
LABEL52:
iconst 1
return
LABEL54:
iload 1
iconst 1
if_icmpeq LABEL58
jump LABEL68
LABEL58:
get_varbit 13778
iconst 2
if_icmpeq LABEL62
jump LABEL68
LABEL62:
iload 2
iconst 0
if_icmpeq LABEL66
jump LABEL68
LABEL66:
iconst 1
return
LABEL68:
iload 1
iconst 1
if_icmpeq LABEL72
jump LABEL82
LABEL72:
get_varbit 13779
iconst 2
if_icmpeq LABEL76
jump LABEL82
LABEL76:
iload 3
iconst 0
if_icmpeq LABEL80
jump LABEL82
LABEL80:
iconst 1
return
LABEL82:
iconst 0
return
iconst -1
return