project: Implement the new menu entry handling

This commit is contained in:
Owain van Brakel
2021-12-16 09:45:44 +01:00
parent 7ef3e6b980
commit a42c845ad3
35 changed files with 665 additions and 402 deletions

View File

@@ -24,6 +24,7 @@ import com.openosrs.injector.injectors.raw.RasterizerAlpha;
import com.openosrs.injector.injectors.raw.RenderDraw;
import com.openosrs.injector.injectors.raw.CopyRuneLiteClasses;
import com.openosrs.injector.injectors.raw.RuneLiteIterables;
import com.openosrs.injector.injectors.raw.RuneliteMenuEntry;
import com.openosrs.injector.injectors.raw.RuneliteObject;
import com.openosrs.injector.injectors.raw.ScriptVM;
import com.openosrs.injector.rsapi.RSApi;
@@ -150,6 +151,8 @@ public class Injector extends InjectData implements InjectTaskHandler
inject(new AddPlayerToMenu(this));
inject(new RuneliteMenuEntry(this));
validate(new InjectorValidator(this));
transform(new SourceChanger(this));

View File

@@ -38,7 +38,8 @@ public class CopyRuneLiteClasses extends AbstractInjector
"RuneLiteObject",
"RuneLiteIterableLinkDeque",
"RuneLiteIterableNodeDeque",
"RuneLiteIterableNodeHashTable"
"RuneLiteIterableNodeHashTable",
"RuneLiteMenuEntry"
);
public CopyRuneLiteClasses(InjectData inject)

View File

@@ -0,0 +1,99 @@
/*
* Copyright (c) 2021, Owain van Brakel <https://github.com/Owain94>
* All rights reserved.
*
* This code is licensed under GPL3, see the complete license in
* the LICENSE file in the root directory of this submodule.
*/
package com.openosrs.injector.injectors.raw;
import com.openosrs.injector.InjectUtil;
import com.openosrs.injector.injection.InjectData;
import com.openosrs.injector.injectors.AbstractInjector;
import java.util.List;
import java.util.ListIterator;
import net.runelite.asm.ClassFile;
import net.runelite.asm.Method;
import net.runelite.asm.attributes.Code;
import net.runelite.asm.attributes.code.Instruction;
import net.runelite.asm.attributes.code.InstructionType;
import net.runelite.asm.attributes.code.Instructions;
import net.runelite.asm.attributes.code.instructions.BAStore;
import net.runelite.asm.attributes.code.instructions.Dup;
import net.runelite.asm.attributes.code.instructions.ILoad;
import net.runelite.asm.attributes.code.instructions.InvokeSpecial;
import net.runelite.asm.attributes.code.instructions.InvokeStatic;
import net.runelite.asm.attributes.code.instructions.New;
import net.runelite.asm.attributes.code.instructions.Return;
import net.runelite.asm.signature.Signature;
public class RuneliteMenuEntry extends AbstractInjector
{
private static final String RUNELITE_MENU_ENTRY = "RuneLiteMenuEntry";
public RuneliteMenuEntry(InjectData inject)
{
super(inject);
}
public void inject()
{
addInvoke();
addSwap(InjectUtil.findMethod(inject, "incrementMenuEntries"));
addSwap(InjectUtil.findMethod(inject, "decrementMenuEntries"));
}
private void addInvoke()
{
ClassFile runeliteMenuEntryVanilla = inject.vanilla.findClass(RUNELITE_MENU_ENTRY);
final ClassFile clientVanilla = inject.toVanilla(
inject.getDeobfuscated()
.findClass("Client")
);
Method copy = clientVanilla.findMethod("newRuneliteMenuEntry");
copy.setPublic();
final Code code = new Code(copy);
code.setMaxStack(3);
copy.setCode(code);
final Instructions instructions = code.getInstructions();
final List<Instruction> ins = instructions.getInstructions();
ins.add(new New(instructions, runeliteMenuEntryVanilla.getPoolClass()));
ins.add(new Dup(instructions));
ins.add(new ILoad(instructions, 0));
ins.add(new InvokeSpecial(instructions, new net.runelite.asm.pool.Method(runeliteMenuEntryVanilla.getPoolClass(), "<init>", new Signature("(I)V"))));
ins.add(new Return(instructions, InstructionType.ARETURN));
}
private void addSwap(Method method)
{
final ClassFile clientVanilla = inject.toVanilla(
inject.getDeobfuscated()
.findClass("Client")
);
Instructions ins = method.getCode().getInstructions();
ListIterator<Instruction> iterator = ins.getInstructions().listIterator();
while (iterator.hasNext())
{
Instruction i = iterator.next();
if (!(i instanceof BAStore))
{
continue;
}
ILoad i1 = new ILoad(ins, 2);
InvokeStatic i2 = new InvokeStatic(ins, new net.runelite.asm.pool.Method(clientVanilla.getPoolClass(), "swapMenuEntries", new Signature("(I)V")));
iterator.add(i1);
iterator.add(i2);
return;
}
}
}

View File

@@ -2124,24 +2124,6 @@ public interface Client extends GameEngine
*/
void scaleSprite(int[] canvas, int[] pixels, int color, int pixelX, int pixelY, int canvasIdx, int canvasOffset, int newWidth, int newHeight, int pixelWidth, int pixelHeight, int oldWidth);
/**
* Get the MenuEntry at client.getMenuOptionCount() - 1
* <p>
* This is useful so you don't have to use getMenuEntries,
* which will create a big array, when you only want to change
* the left click one.
*/
MenuEntry getLeftClickMenuEntry();
/**
* Set the MenuEntry at client.getMenuOptionCount() - 1
* <p>
* This is useful so you don't have to use setMenuEntries,
* which will arraycopy a big array to several smaller arrays lol,
* when you only want to change the left click one.
*/
void setLeftClickMenuEntry(MenuEntry entry);
/**
* If this field is set to true, getting 5 minute logged won't show
* the "You have been disconnected." message anymore.

View File

@@ -24,240 +24,72 @@
*/
package net.runelite.api;
import java.util.Arrays;
import java.util.function.Consumer;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* A menu entry in a right-click menu.
*/
@Data
@NoArgsConstructor
public class MenuEntry implements Cloneable
public interface MenuEntry
{
/**
* The option text added to the menu. (ie. "Walk here", "Use")
*/
private String option;
String getOption();
MenuEntry setOption(String option);
/**
* The target of the action. (ie. Item or Actor name)
* <p>
* If the option does not apply to any target, this field
* will be set to empty string.
*/
private String target;
String getTarget();
MenuEntry setTarget(String target);
/**
* An identifier value for the target of the action.
*/
private int identifier;
int getIdentifier();
MenuEntry setIdentifier(int identifier);
/**
* The action the entry will trigger.
* {@link MenuAction}
*/
private int opcode;
MenuAction getType();
MenuEntry setType(MenuAction type);
/**
* An additional parameter for the action.
*/
private int param0;
int getParam0();
MenuEntry setParam0(int param0);
/**
* A second additional parameter for the action.
*/
private int param1;
int getParam1();
MenuEntry setParam1(int param1);
/**
* If this field is true and you have single mouse button on and this entry is
* If this is true and you have single mouse button on and this entry is
* the top entry the right click menu will not be opened when you left click
*
* This is used for shift click
*/
private boolean forceLeftClick;
public MenuEntry(String option, String target, int type, int opcode, int param0, int param1, boolean forceLeftClick)
{
this.option = option;
this.target = target;
this.identifier = type;
this.opcode = opcode;
this.param0 = param0;
this.param1 = param1;
this.forceLeftClick = forceLeftClick;
}
@Override
public MenuEntry clone()
{
try
{
return (MenuEntry) super.clone();
}
catch (CloneNotSupportedException ex)
{
throw new RuntimeException(ex);
}
}
public String getOption()
{
return option;
}
public MenuEntry setOption(String option)
{
this.option = option;
return this;
}
public String getTarget()
{
return target;
}
public MenuEntry setTarget(String target)
{
this.target = target;
return this;
}
public int getIdentifier()
{
return this.identifier;
}
public MenuEntry setIdentifier(int identifier)
{
this.identifier = identifier;
return this;
}
public MenuAction getType()
{
return MenuAction.of(this.opcode);
}
public MenuEntry setType(MenuAction type)
{
this.opcode = type.getId();
return this;
}
public int getParam0()
{
return this.param0;
}
public MenuEntry setParam0(int param0)
{
this.param0 = param0;
return this;
}
public int getParam1()
{
return this.param1;
}
public MenuEntry setParam1(int param1)
{
this.param1 = param1;
return this;
}
public boolean isForceLeftClick()
{
return this.forceLeftClick;
}
public MenuEntry setForceLeftClick(boolean forceLeftClick)
{
this.forceLeftClick = forceLeftClick;
return this;
}
public boolean isDeprioritized()
{
return opcode >= MenuAction.MENU_ACTION_DEPRIORITIZE_OFFSET;
}
public MenuEntry setDeprioritized(boolean deprioritized)
{
if (deprioritized)
{
if (opcode < MenuAction.MENU_ACTION_DEPRIORITIZE_OFFSET)
{
opcode += MenuAction.MENU_ACTION_DEPRIORITIZE_OFFSET;
}
}
else
{
if (opcode >= MenuAction.MENU_ACTION_DEPRIORITIZE_OFFSET)
{
opcode -= MenuAction.MENU_ACTION_DEPRIORITIZE_OFFSET;
}
}
return this;
}
public MenuEntry onClick(Consumer<MenuEntry> callback)
{
return this;
}
public void setActionParam0(int i)
{
this.param0 = i;
}
public int getActionParam0()
{
return this.param0;
}
public void setActionParam1(int i)
{
this.param1 = i;
}
public int getActionParam1()
{
return this.param1;
}
public void setType(int i)
{
this.opcode = i;
}
public void setId(int i)
{
this.identifier = i;
}
public int getId()
{
return this.identifier;
}
boolean isForceLeftClick();
MenuEntry setForceLeftClick(boolean forceLeftClick);
/**
* Get opcode, but as it's enum counterpart
* Deprioritized menus are sorted in the menu to be below the other menu entries.
* @return
*/
public MenuAction getMenuAction()
{
return MenuAction.of(getOpcode());
}
boolean isDeprioritized();
MenuEntry setDeprioritized(boolean deprioritized);
// TODO: Remove this after properly implementing the menu
public void add(Client client)
{
MenuEntry[] menuEntries = client.getMenuEntries();
menuEntries = Arrays.copyOf(menuEntries, menuEntries.length + 1);
MenuEntry menuEntry = menuEntries[menuEntries.length - 1] = new MenuEntry();
menuEntry.setOption(option);
menuEntry.setTarget(target);
menuEntry.setParam0(param0);
menuEntry.setParam1(param1);
menuEntry.setIdentifier(identifier);
menuEntry.setType(MenuAction.of(getOpcode()));
client.setMenuEntries(menuEntries);
}
}
/**
* Set a callback to be called when this menu option is clicked
* @param callback
* @return
*/
MenuEntry onClick(Consumer<MenuEntry> callback);
}

View File

@@ -142,9 +142,7 @@ public class MenuManager
.setTarget(currentMenu.getMenuTarget())
.setType(MenuAction.RUNELITE)
.setParam1(widgetId)
.onClick(currentMenu.callback)
// TODO: remove
.add(client);
.onClick(currentMenu.callback);
}
}

View File

@@ -362,9 +362,7 @@ public class BankTagsPlugin extends Plugin implements MouseWheelListener
.setOption(text)
.setType(MenuAction.RUNELITE)
.setIdentifier(event.getIdentifier())
.onClick(this::editTags)
// TODO: remove
.add(client);
.onClick(this::editTags);
}
tabInterface.handleAdd(event);

View File

@@ -1196,8 +1196,6 @@ public class TabInterface
.setTarget(target)
.setOption(option)
.setType(MenuAction.RUNELITE)
.setIdentifier(event.getIdentifier())
// TODO: remove
.add(client);
.setIdentifier(event.getIdentifier());
}
}

View File

@@ -242,9 +242,7 @@ public class ChatHistoryPlugin extends Plugin implements KeyListener
{
final StringSelection stringSelection = new StringSelection(Text.removeTags(currentMessage));
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(stringSelection, null);
})
// TODO: remove
.add(client);
});
}
@Subscribe
@@ -290,9 +288,7 @@ public class ChatHistoryPlugin extends Plugin implements KeyListener
}
optionBuilder.append(CLEAR_HISTORY);
clearEntry.setOption(optionBuilder.toString())
// TODO: remove
.add(client);
clearEntry.setOption(optionBuilder.toString());
}
private void clearMessageQueue(ChatboxTab tab)

View File

@@ -185,9 +185,7 @@ public class FriendListPlugin extends Plugin
.type(ChatMessageType.CONSOLE)
.value("Login notifications for " + friend + " are now " + (hidden ? "shown." : "hidden."))
.build());
})
// TODO: remove
.add(client);
});
}
}

View File

@@ -266,9 +266,7 @@ public class FriendNotesPlugin extends Plugin
log.debug("Set note for '{}': '{}'", sanitizedTarget, content);
setFriendNote(sanitizedTarget, content);
}).build();
})
// TODO: remove
.add(client);
});
}
else if (hoveredFriend != null)
{

View File

@@ -251,9 +251,7 @@ public class GroundMarkerPlugin extends Plugin
{
markTile(target.getLocalLocation());
}
})
// TODO: remove
.add(client);
});
if (exists)
{
@@ -268,9 +266,7 @@ public class GroundMarkerPlugin extends Plugin
{
labelTile(target);
}
})
// TODO: remove
.add(client);
});
}
}
}

View File

@@ -178,9 +178,7 @@ public class HiscorePlugin extends Plugin
HiscoreEndpoint endpoint = findHiscoreEndpointFromPlayerName(e.getTarget());
String target = Text.removeTags(e.getTarget());
lookupPlayer(target, endpoint);
})
// TODO: remove
.add(client);
});
}
}

View File

@@ -198,9 +198,7 @@ public class InventoryTagsPlugin extends Plugin
{
unsetTag(itemId);
}
})
// TODO: remove
.add(client);
});
}
}
}

View File

@@ -598,9 +598,7 @@ public class MenuEntrySwapperPlugin extends Plugin
.setOption(RESET)
.setTarget(configuringShiftClick ? SHIFT_CLICK_MENU_TARGET : LEFT_CLICK_MENU_TARGET)
.setType(MenuAction.RUNELITE)
.onClick(e -> unsetSwapConfig(configuringShiftClick, itemId))
// TODO: remove
.add(client);
.onClick(e -> unsetSwapConfig(configuringShiftClick, itemId));
}
@Subscribe

View File

@@ -296,19 +296,15 @@ public class NpcIndicatorsPlugin extends Plugin
.setTarget(event.getTarget())
.setIdentifier(event.getIdentifier())
.setType(MenuAction.RUNELITE)
.onClick(this::tag)
// TODO: remove
.add(client);
.onClick(this::tag);
}
client.createMenuEntry(-1)
MenuEntry i = client.createMenuEntry(-1)
.setOption(npcTags.contains(npc.getIndex()) ? UNTAG : TAG)
.setTarget(event.getTarget())
.setIdentifier(event.getIdentifier())
.setType(MenuAction.RUNELITE)
.onClick(this::tag)
// TODO: remove
.add(client);
.onClick(this::tag);
}
}

View File

@@ -235,9 +235,7 @@ public class ObjectIndicatorsPlugin extends Plugin
.setParam1(event.getActionParam1())
.setIdentifier(event.getIdentifier())
.setType(MenuAction.RUNELITE)
.onClick(this::markObject)
// TODO: remove
.add(client);
.onClick(this::markObject);
}
private void markObject(MenuEntry entry)

View File

@@ -418,9 +418,7 @@ public class WikiPlugin extends Plugin
.addPathSegment("w")
.addPathSegment(Text.removeTags(ev.getTarget()))
.addQueryParameter(UTM_SORUCE_KEY, UTM_SORUCE_VALUE)
.build().toString()))
// TODO: remove
.add(client);
.build().toString()));
}
}
}

View File

@@ -405,9 +405,7 @@ public class WorldHopperPlugin extends Plugin
{
hop(p.getWorld());
}
})
// TODO: remove
.add(client);
});
}
}

View File

@@ -532,9 +532,7 @@ public class XpTrackerPlugin extends Plugin
{
addOverlay(skill);
}
})
// TODO: remove
.add(client);
});
}
XpStateSingle getSkillState(Skill skill)

View File

@@ -185,9 +185,7 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
.setOption(overlayMenuEntry.getOption())
.setTarget(ColorUtil.wrapWithColorTag(overlayMenuEntry.getTarget(), JagexColors.MENU_TARGET))
.setType(overlayMenuEntry.getMenuAction())
.onClick(e -> eventBus.post(new OverlayMenuClicked(overlayMenuEntry, overlay)))
// TODO: remove
.add(client);
.onClick(e -> eventBus.post(new OverlayMenuClicked(overlayMenuEntry, overlay)));
}
}

View File

@@ -114,9 +114,7 @@ public class WorldMapOverlay extends Overlay
.setOption(FOCUS_ON)
.setType(MenuAction.RUNELITE)
.onClick(m -> client.getRenderOverview().setWorldMapPositionTarget(
MoreObjects.firstNonNull(worldPoint.getTarget(), worldPoint.getWorldPoint())))
// TODO: remove
.add(client);
MoreObjects.firstNonNull(worldPoint.getTarget(), worldPoint.getWorldPoint())));
});
bottomBar.setHasListener(true);

View File

@@ -30,7 +30,7 @@ import net.runelite.api.MenuAction;
import net.runelite.api.MenuEntry;
@EqualsAndHashCode(callSuper = false)
public class TestMenuEntry extends MenuEntry
public class TestMenuEntry implements MenuEntry
{
private String option;
private String target;

View File

@@ -163,36 +163,6 @@ public abstract class MenuMixin implements RSClient
}
}
@Inject
@Override
public MenuEntry getLeftClickMenuEntry()
{
final int i = getMenuOptionCount() - 1;
return new MenuEntry(
getMenuOptions()[i],
getMenuTargets()[i],
getMenuIdentifiers()[i],
getMenuOpcodes()[i],
getMenuArguments1()[i],
getMenuArguments2()[i],
getMenuForceLeftClick()[i]
);
}
@Inject
@Override
public void setLeftClickMenuEntry(final MenuEntry entry)
{
final int i = getMenuOptionCount() - 1;
getMenuOptions()[i] = entry.getOption();
getMenuTargets()[i] = entry.getTarget();
getMenuIdentifiers()[i] = entry.getIdentifier();
getMenuOpcodes()[i] = entry.getOpcode();
getMenuArguments1()[i] = entry.getParam0();
getMenuArguments2()[i] = entry.getParam1();
getMenuForceLeftClick()[i] = entry.isForceLeftClick();
}
@Inject
@FieldHook("tempMenuAction")
public static void onTempMenuActionChanged(int idx)
@@ -213,7 +183,7 @@ public abstract class MenuMixin implements RSClient
}
tempMenuAction.setOption(entry.getOption());
tempMenuAction.setOpcode(entry.getOpcode());
tempMenuAction.setOpcode(entry.getType().getId());
tempMenuAction.setIdentifier(entry.getIdentifier());
tempMenuAction.setParam0(entry.getParam0());
tempMenuAction.setParam1(entry.getParam1());

View File

@@ -156,6 +156,7 @@ import net.runelite.rs.api.RSNodeDeque;
import net.runelite.rs.api.RSNodeHashTable;
import net.runelite.rs.api.RSPacketBuffer;
import net.runelite.rs.api.RSPlayer;
import net.runelite.rs.api.RSRuneLiteMenuEntry;
import net.runelite.rs.api.RSScene;
import net.runelite.rs.api.RSScriptEvent;
import net.runelite.rs.api.RSSpritePixels;
@@ -294,6 +295,12 @@ public abstract class RSClientMixin implements RSClient
@Inject
private static ArrayList<Widget> hiddenWidgets = new ArrayList<>();
@Inject
private static final RSRuneLiteMenuEntry[] rl$menuEntries = new RSRuneLiteMenuEntry[500];
@Inject
private static int tmpMenuOptionsCount;
@Inject
@Override
public void setPrintMenuActions(boolean yes)
@@ -789,119 +796,210 @@ public abstract class RSClientMixin implements RSClient
setChatCycle(getCycleCntr());
}
@Inject
public static RSRuneLiteMenuEntry newRuneliteMenuEntry(int idx)
{
return null;
}
@Inject
@Override
public MenuEntry createMenuEntry(int idx)
{
// TODO: Implement this
if (client.getMenuOptionCount() >= 500)
{
throw new IllegalStateException();
}
else
{
if (idx < 0)
{
idx = client.getMenuOptionCount() + idx + 1;
if (idx < 0)
{
throw new IllegalArgumentException();
}
}
return new MenuEntry();
RSRuneLiteMenuEntry menuEntry;
if (idx < client.getMenuOptionCount())
{
RSRuneLiteMenuEntry tmpEntry = rl$menuEntries[client.getMenuOptionCount()];
if (tmpEntry == null)
{
tmpEntry = rl$menuEntries[client.getMenuOptionCount()] = newRuneliteMenuEntry(client.getMenuOptionCount());
}
for (int i = client.getMenuOptionCount(); i > idx; rl$menuEntries[i].setIdx(i--))
{
client.getMenuOptions()[i] = client.getMenuOptions()[i - 1];
client.getMenuTargets()[i] = client.getMenuTargets()[i - 1];
client.getMenuIdentifiers()[i] = client.getMenuIdentifiers()[i - 1];
client.getMenuOpcodes()[i] = client.getMenuOpcodes()[i - 1];
client.getMenuArguments1()[i] = client.getMenuArguments1()[i - 1];
client.getMenuArguments2()[i] = client.getMenuArguments2()[i - 1];
client.getMenuForceLeftClick()[i] = client.getMenuForceLeftClick()[i - 1];
rl$menuEntries[i] = rl$menuEntries[i - 1];
}
client.setMenuOptionCount(client.getMenuOptionCount() + 1);
tmpMenuOptionsCount = client.getMenuOptionCount();
menuEntry = tmpEntry;
rl$menuEntries[idx] = tmpEntry;
tmpEntry.setIdx(idx);
}
else
{
if (idx != client.getMenuOptionCount())
{
throw new IllegalArgumentException();
}
menuEntry = rl$menuEntries[client.getMenuOptionCount()];
if (menuEntry == null)
{
menuEntry = rl$menuEntries[client.getMenuOptionCount()] = newRuneliteMenuEntry(client.getMenuOptionCount());
}
client.setMenuOptionCount(client.getMenuOptionCount() + 1);
tmpMenuOptionsCount = client.getMenuOptionCount();
}
menuEntry.setOption("");
menuEntry.setTarget("");
menuEntry.setIdentifier(0);
menuEntry.setType(MenuAction.RUNELITE);
menuEntry.setParam0(0);
menuEntry.setParam1(0);
menuEntry.setConsumer(null);
return menuEntry;
}
}
@Inject
@Override
public MenuEntry[] getMenuEntries()
{
int count = getMenuOptionCount();
String[] menuOptions = getMenuOptions();
String[] menuTargets = getMenuTargets();
int[] menuIdentifiers = getMenuIdentifiers();
int[] menuTypes = getMenuOpcodes();
int[] params0 = getMenuArguments1();
int[] params1 = getMenuArguments2();
boolean[] leftClick = getMenuForceLeftClick();
MenuEntry[] entries = new MenuEntry[count];
for (int i = 0; i < count; ++i)
{
MenuEntry entry = entries[i] = new MenuEntry();
entry.setOption(menuOptions[i]);
entry.setTarget(menuTargets[i]);
entry.setIdentifier(menuIdentifiers[i]);
entry.setOpcode(menuTypes[i]);
entry.setParam0(params0[i]);
entry.setParam1(params1[i]);
entry.setForceLeftClick(leftClick[i]);
}
return entries;
return Arrays.copyOf(rl$menuEntries, client.getMenuOptionCount());
}
@Inject
@Override
public void setMenuEntries(MenuEntry[] entries)
public void setMenuEntries(MenuEntry[] menuEntries)
{
int count = 0;
String[] menuOptions = getMenuOptions();
String[] menuTargets = getMenuTargets();
int[] menuIdentifiers = getMenuIdentifiers();
int[] menuTypes = getMenuOpcodes();
int[] params0 = getMenuArguments1();
int[] params1 = getMenuArguments2();
boolean[] leftClick = getMenuForceLeftClick();
for (MenuEntry entry : entries)
for (int i = 0; i < menuEntries.length; ++i)
{
if (entry == null)
RSRuneLiteMenuEntry menuEntry = (RSRuneLiteMenuEntry) menuEntries[i];
if (menuEntry.getIdx() != i)
{
continue;
sortMenuEntries(menuEntry.getIdx(), i);
}
menuOptions[count] = entry.getOption();
menuTargets[count] = entry.getTarget();
menuIdentifiers[count] = entry.getIdentifier();
menuTypes[count] = entry.getOpcode();
params0[count] = entry.getParam0();
params1[count] = entry.getParam1();
leftClick[count] = entry.isForceLeftClick();
++count;
}
setMenuOptionCount(count);
oldMenuEntryCount = count;
client.setMenuOptionCount(menuEntries.length);
tmpMenuOptionsCount = menuEntries.length;
}
@Inject
public static void sortMenuEntries(int left, int right)
{
String menuOption = client.getMenuOptions()[left];
client.getMenuOptions()[left] = client.getMenuOptions()[right];
client.getMenuOptions()[right] = menuOption;
String menuTarget = client.getMenuTargets()[left];
client.getMenuTargets()[left] = client.getMenuTargets()[right];
client.getMenuTargets()[right] = menuTarget;
int menuIdentifier = client.getMenuIdentifiers()[left];
client.getMenuIdentifiers()[left] = client.getMenuIdentifiers()[right];
client.getMenuIdentifiers()[right] = menuIdentifier;
int menuOpcode = client.getMenuOpcodes()[left];
client.getMenuOpcodes()[left] = client.getMenuOpcodes()[right];
client.getMenuOpcodes()[right] = menuOpcode;
int menuArguments1 = client.getMenuArguments1()[left];
client.getMenuArguments1()[left] = client.getMenuArguments1()[right];
client.getMenuArguments1()[right] = menuArguments1;
int menuArgument2 = client.getMenuArguments2()[left];
client.getMenuArguments2()[left] = client.getMenuArguments2()[right];
client.getMenuArguments2()[right] = menuArgument2;
boolean menuForceLeftClick = client.getMenuForceLeftClick()[left];
client.getMenuForceLeftClick()[left] = client.getMenuForceLeftClick()[right];
client.getMenuForceLeftClick()[right] = menuForceLeftClick;
RSRuneLiteMenuEntry tmpEntry = rl$menuEntries[left];
rl$menuEntries[left] = rl$menuEntries[right];
rl$menuEntries[right] = tmpEntry;
rl$menuEntries[left].setIdx(left);
rl$menuEntries[right].setIdx(right);
}
@Inject
public static void swapMenuEntries(int var0)
{
RSRuneLiteMenuEntry var1 = rl$menuEntries[var0];
RSRuneLiteMenuEntry var2 = rl$menuEntries[var0 + 1];
rl$menuEntries[var0] = var2;
rl$menuEntries[var0 + 1] = var1;
var1.setIdx(var0 + 1);
var2.setIdx(var0);
}
@FieldHook("menuOptionsCount")
@Inject
public static void onMenuOptionsChanged(int idx)
{
int oldCount = oldMenuEntryCount;
int newCount = client.getMenuOptionCount();
int tmpOptionsCount = tmpMenuOptionsCount;
int optionCount = client.getMenuOptionCount();
oldMenuEntryCount = newCount;
tmpMenuOptionsCount = optionCount;
final String[] options = client.getMenuOptions();
final String[] targets = client.getMenuTargets();
final int[] identifiers = client.getMenuIdentifiers();
final int[] opcodes = client.getMenuOpcodes();
final int[] arguments1 = client.getMenuArguments1();
final int[] arguments2 = client.getMenuArguments2();
final boolean[] forceLeftClick = client.getMenuForceLeftClick();
if (newCount == oldCount + 1)
if (optionCount < tmpOptionsCount)
{
MenuEntryAdded event = new MenuEntryAdded(
options[oldCount],
targets[oldCount],
identifiers[oldCount],
opcodes[oldCount],
arguments1[oldCount],
arguments2[oldCount],
forceLeftClick[oldCount]
);
client.getCallbacks().post(event);
if (event.isModified() && client.getMenuOptionCount() == newCount)
for (int i = optionCount; i < tmpOptionsCount; ++i)
{
options[oldCount] = event.getOption();
targets[oldCount] = event.getTarget();
identifiers[oldCount] = event.getIdentifier();
opcodes[oldCount] = event.getType();
arguments1[oldCount] = event.getActionParam0();
arguments2[oldCount] = event.getActionParam1();
forceLeftClick[oldCount] = event.isForceLeftClick();
rl$menuEntries[i].setConsumer(null);
}
}
else if (optionCount == tmpOptionsCount + 1)
{
String menuOption = client.getMenuOptions()[tmpOptionsCount];
String menuTarget = client.getMenuTargets()[tmpOptionsCount];
int menuOpcode = client.getMenuOpcodes()[tmpOptionsCount];
int menuIdentifier = client.getMenuIdentifiers()[tmpOptionsCount];
int menuArgument1 = client.getMenuArguments1()[tmpOptionsCount];
int menuArgument2 = client.getMenuArguments2()[tmpOptionsCount];
if (rl$menuEntries[tmpOptionsCount] == null)
{
rl$menuEntries[tmpOptionsCount] = newRuneliteMenuEntry(tmpOptionsCount);
}
else
{
rl$menuEntries[tmpOptionsCount].setConsumer(null);
}
MenuEntryAdded menuEntryAdded = new MenuEntryAdded(
menuOption,
menuTarget,
menuOpcode,
menuIdentifier,
menuArgument1,
menuArgument2
);
client.getCallbacks().post(menuEntryAdded);
}
}
@Inject
@@ -1479,6 +1577,17 @@ public abstract class RSClientMixin implements RSClient
@Replace("menuAction")
static void copy$menuAction(int param0, int param1, int opcode, int id, String option, String target, int canvasX, int canvasY)
{
RSRuneLiteMenuEntry menuEntry = null;
for (int i = client.getMenuOptionCount() - 1; i >= 0; --i)
{
if (client.getMenuOptions()[i] == option && client.getMenuTargets()[i] == target && client.getMenuIdentifiers()[i] == id && client.getMenuOpcodes()[i] == opcode)
{
menuEntry = rl$menuEntries[i];
break;
}
}
/*
* The RuneScape client may deprioritize an action in the menu by incrementing the opcode with 2000,
* undo it here so we can get the correct opcode
@@ -1501,6 +1610,11 @@ public abstract class RSClientMixin implements RSClient
client.getCallbacks().post(menuOptionClicked);
if (menuEntry != null && menuEntry.getConsumer() != null)
{
menuEntry.getConsumer().accept(menuEntry);
}
if (menuOptionClicked.isConsumed())
{
return;

View File

@@ -1,4 +0,0 @@
package net.runelite.rs.api;
public interface RSRuneLiteIterableHashTable
{}

View File

@@ -0,0 +1,4 @@
package net.runelite.rs.api;
public interface RSRuneLiteIterableNodeHashTable
{}

View File

@@ -0,0 +1,13 @@
package net.runelite.rs.api;
import java.util.function.Consumer;
import net.runelite.api.MenuEntry;
public interface RSRuneLiteMenuEntry extends MenuEntry
{
Consumer getConsumer();
void setConsumer(Consumer consumer);
int getIdx();
void setIdx(int idx);
}

View File

@@ -27,6 +27,8 @@ group = "com.openosrs.rs"
description = "RuneScape Client"
dependencies {
api(project(":runelite-api"))
implementation(project(":injection-annotations"))
implementation(group = "org.bouncycastle", name = "bcprov-jdk15on", version = "1.52")

View File

@@ -161,7 +161,7 @@ public class ChatChannel {
Client.meslayerContinueWidget = null;
}
FileSystem.method3084();
FileSystem.decrementMenuEntries();
class115.revalidateWidgetScroll(MouseRecorder.Widget_interfaceComponents[var0 >> 16], var4, false);
class33.runWidgetOnLoadListener(var1);
if (Client.rootInterface != -1) {

View File

@@ -6401,7 +6401,7 @@ public final class Client extends GameEngine implements Usernamed, OAuthTokens {
)
@Export("menu")
final void menu() {
Message.method1115();
Message.incrementMenuEntries();
if (class143.dragInventoryWidget == null) {
if (clickedWidget == null) {
int var1 = MouseHandler.MouseHandler_lastButton;

View File

@@ -30,7 +30,8 @@ public class FileSystem {
descriptor = "(I)V",
garbageValue = "497428397"
)
static void method3084() {
@Export("decrementMenuEntries")
static void decrementMenuEntries() {
for (int var0 = 0; var0 < Client.menuOptionsCount; ++var0) {
if (InvDefinition.method3157(Client.menuOpcodes[var0])) {
if (var0 < Client.menuOptionsCount - 1) {

View File

@@ -166,7 +166,8 @@ public class Message extends DualNode {
descriptor = "(I)V",
garbageValue = "1989735073"
)
static final void method1115() {
@Export("incrementMenuEntries")
static final void incrementMenuEntries() {
boolean var0 = false;
while (!var0) {

View File

@@ -0,0 +1,285 @@
import java.util.function.Consumer;
import net.runelite.api.MenuAction;
import net.runelite.api.MenuEntry;
public class RuneLiteMenuEntry implements MenuEntry
{
public Consumer consumer;
public int idx;
public RuneLiteMenuEntry(int idx)
{
this.idx = idx;
}
public Consumer getConsumer()
{
return consumer;
}
public void setConsumer(Consumer consumer)
{
this.consumer = consumer;
}
public int getIdx()
{
return idx;
}
public void setIdx(int idx)
{
this.idx = idx;
}
@Override
public String getOption()
{
return Client.menuActions[this.idx];
}
@Override
public MenuEntry setOption(String option)
{
Client.menuActions[this.idx] = option;
return this;
}
@Override
public String getTarget()
{
return Client.menuTargets[this.idx];
}
@Override
public MenuEntry setTarget(String target)
{
Client.menuTargets[this.idx] = target;
return this;
}
@Override
public MenuAction getType()
{
int opcode = Client.menuOpcodes[this.idx];
if (opcode >= 2000)
{
opcode -= 2000;
}
return MenuAction.of(opcode);
}
@Override
public MenuEntry setType(MenuAction menuAction)
{
int opcode = Client.menuOpcodes[this.idx];
short mod = 0;
if (opcode >= 2000)
{
mod = 2000;
}
Client.menuOpcodes[this.idx] = menuAction.getId() + mod;
return this;
}
@Override
public int getIdentifier()
{
return Client.menuIdentifiers[this.idx];
}
@Override
public MenuEntry setIdentifier(int identifier)
{
Client.menuIdentifiers[this.idx] = identifier;
return this;
}
@Override
public int getParam0()
{
return Client.menuArguments1[this.idx];
}
@Override
public MenuEntry setParam0(int param0)
{
Client.menuArguments1[this.idx] = param0;
return this;
}
@Override
public int getParam1()
{
return Client.menuArguments2[this.idx];
}
@Override
public MenuEntry setParam1(int param1)
{
Client.menuArguments2[this.idx] = param1;
return this;
}
@Override
public boolean isDeprioritized()
{
return Client.menuOpcodes[this.idx] >= 2000;
}
@Override
public MenuEntry setDeprioritized(boolean deprioritize)
{
int[] opcodes;
if (deprioritize)
{
if (Client.menuOpcodes[this.idx] < 2000)
{
opcodes = Client.menuOpcodes;
opcodes[this.idx] += 2000;
}
}
else if (Client.menuOpcodes[this.idx] >= 2000)
{
opcodes = Client.menuOpcodes;
opcodes[this.idx] -= 2000;
}
return this;
}
@Override
public boolean isForceLeftClick()
{
return Client.menuShiftClick[this.idx];
}
@Override
public MenuEntry setForceLeftClick(boolean forceLeftClick)
{
Client.menuShiftClick[this.idx] = forceLeftClick;
return this;
}
@Override
public MenuEntry onClick(Consumer consumer)
{
this.consumer = consumer;
return this;
}
public boolean instanceOf(Object o)
{
return o instanceof RuneLiteMenuEntry;
}
@Override
public boolean equals(Object o)
{
if (o == this)
{
return true;
}
else if (!(o instanceof RuneLiteMenuEntry))
{
return false;
}
else
{
RuneLiteMenuEntry menuEntry = (RuneLiteMenuEntry) o;
if (!menuEntry.instanceOf(this))
{
return false;
}
else if (this.getIdentifier() != menuEntry.getIdentifier())
{
return false;
}
else if (this.getParam0() != menuEntry.getParam0())
{
return false;
}
else if (this.getParam1() != menuEntry.getParam1())
{
return false;
}
else if (this.isForceLeftClick() != menuEntry.isForceLeftClick())
{
return false;
}
else if (this.isDeprioritized() != menuEntry.isDeprioritized())
{
return false;
}
else
{
String option = this.getOption();
String menuEntryOption = menuEntry.getOption();
if (option == null)
{
if (menuEntryOption != null)
{
return false;
}
}
else if (!option.equals(menuEntryOption))
{
return false;
}
String target = this.getTarget();
String menuEntryTarget = menuEntry.getTarget();
if (target == null)
{
if (menuEntryTarget != null)
{
return false;
}
}
else if (!target.equals(menuEntryTarget))
{
return false;
}
MenuAction type = this.getType();
MenuAction menuEntryType = menuEntry.getType();
if (type == null)
{
if (menuEntryType == null)
{
return true;
}
}
else if (type.equals(menuEntryType))
{
return true;
}
return false;
}
}
}
@Override
public int hashCode()
{
byte b = 1;
int hash = b * 59 + this.getIdentifier();
hash = hash * 59 + this.getParam0();
hash = hash * 59 + this.getParam1();
hash = hash * 59 + (this.isForceLeftClick() ? 79 : 97);
hash = hash * 59 + (this.isDeprioritized() ? 79 : 97);
String option = this.getOption();
hash = hash * 59 + (option == null ? 43 : option.hashCode());
String target = this.getTarget();
hash = hash * 59 + (target == null ? 43 : target.hashCode());
MenuAction type = this.getType();
hash = hash * 59 + (type == null ? 43 : type.hashCode());
return hash;
}
}

View File

@@ -320,7 +320,7 @@ public class class10 {
SecureRandomCallable.invalidateWidget(var4);
}
FileSystem.method3084();
FileSystem.decrementMenuEntries();
if (Client.rootInterface != -1) {
Message.runIntfCloseListeners(Client.rootInterface, 1);
}