From 5c83be7c2f16ef0fa0e9f26d353d5ff96841c005 Mon Sep 17 00:00:00 2001 From: Dennis de V Date: Fri, 16 Mar 2018 17:10:43 -0400 Subject: [PATCH 1/6] runelite-api: expose dragging widget fields --- .../main/java/net/runelite/api/Client.java | 10 +++++++++ .../java/net/runelite/rs/api/RSClient.java | 21 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/runelite-api/src/main/java/net/runelite/api/Client.java b/runelite-api/src/main/java/net/runelite/api/Client.java index af87977084..a7ba3ab1b4 100644 --- a/runelite-api/src/main/java/net/runelite/api/Client.java +++ b/runelite-api/src/main/java/net/runelite/api/Client.java @@ -98,6 +98,16 @@ public interface Client extends GameEngine int getBaseY(); + int getMouseCurrentButton(); + + boolean isDraggingWidget(); + + Widget getDraggedWidget(); + + Widget getDraggedOnWidget(); + + void setDraggedOnWidget(Widget widget); + Widget[] getWidgetRoots(); Widget getWidget(WidgetInfo widget); diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java b/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java index db869e309f..95dc51eaea 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java @@ -28,6 +28,7 @@ import java.util.Map; import net.runelite.api.BufferProvider; import net.runelite.api.Client; import net.runelite.api.World; +import net.runelite.api.widgets.Widget; import net.runelite.mapping.Construct; import net.runelite.mapping.Import; @@ -111,6 +112,26 @@ public interface RSClient extends RSGameEngine, Client @Import("gameState") int getRSGameState(); + @Import("mouseCurrentButton") + @Override + int getMouseCurrentButton(); + + @Import("draggingWidget") + @Override + boolean isDraggingWidget(); + + @Import("draggedWidget") + @Override + RSWidget getDraggedWidget(); + + @Import("draggedOnWidget") + @Override + RSWidget getDraggedOnWidget(); + + @Import("draggedOnWidget") + @Override + void setDraggedOnWidget(Widget widget); + @Import("widgets") RSWidget[][] getWidgets(); From 56f8ebe4da70a6015a5f6551179f12d06172c916 Mon Sep 17 00:00:00 2001 From: Dennis de V Date: Fri, 16 Mar 2018 17:11:56 -0400 Subject: [PATCH 2/6] runelite-api: add event for dragging widget --- .../api/events/DraggingWidgetChanged.java | 33 +++++++++++++++++++ .../net/runelite/mixins/RSClientMixin.java | 10 ++++++ 2 files changed, 43 insertions(+) create mode 100644 runelite-api/src/main/java/net/runelite/api/events/DraggingWidgetChanged.java diff --git a/runelite-api/src/main/java/net/runelite/api/events/DraggingWidgetChanged.java b/runelite-api/src/main/java/net/runelite/api/events/DraggingWidgetChanged.java new file mode 100644 index 0000000000..cb7928c421 --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/events/DraggingWidgetChanged.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2018, 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.api.events; + +import lombok.Data; + +@Data +public class DraggingWidgetChanged +{ + private boolean draggingWidget; +} diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java index 6ebf1db531..3527bb3c47 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java @@ -55,6 +55,7 @@ import net.runelite.api.SpritePixels; import net.runelite.api.Varbits; import net.runelite.api.WidgetNode; import net.runelite.api.coords.LocalPoint; +import net.runelite.api.events.DraggingWidgetChanged; import net.runelite.api.events.ExperienceChanged; import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.GrandExchangeOfferChanged; @@ -464,6 +465,15 @@ public abstract class RSClientMixin implements RSClient return clanMemberManager != null && clanMemberManager.isMember(createName(name, getLoginType())); } + @FieldHook("draggingWidget") + @Inject + public static void draggingWidgetChanged(int idx) + { + DraggingWidgetChanged draggingWidgetChanged = new DraggingWidgetChanged(); + draggingWidgetChanged.setDraggingWidget(client.isDraggingWidget()); + eventBus.post(draggingWidgetChanged); + } + @Inject @Override public SpritePixels createItemSprite(int itemId, int quantity, int border, int shadowColor, int stackable, boolean noted, int scale) From 15ef09cd5e9b65a465ced9e1f71b0605687998a4 Mon Sep 17 00:00:00 2001 From: Dennis de V Date: Fri, 16 Mar 2018 17:13:24 -0400 Subject: [PATCH 3/6] runelite-api: add widget open event --- .../net/runelite/api/events/WidgetOpened.java | 35 +++++++++++++++++++ .../net/runelite/mixins/RSClientMixin.java | 13 +++++-- 2 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 runelite-api/src/main/java/net/runelite/api/events/WidgetOpened.java diff --git a/runelite-api/src/main/java/net/runelite/api/events/WidgetOpened.java b/runelite-api/src/main/java/net/runelite/api/events/WidgetOpened.java new file mode 100644 index 0000000000..8ad22dead2 --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/events/WidgetOpened.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2018, 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.api.events; + +import lombok.Data; + +@Data +public class WidgetOpened +{ + private int parentId; + private int groupId; + private int autoClose; +} diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java index 3527bb3c47..1b5c8dd827 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java @@ -63,6 +63,7 @@ import net.runelite.api.events.MapRegionChanged; import net.runelite.api.events.PlayerMenuOptionsChanged; import net.runelite.api.events.ResizeableChanged; import net.runelite.api.events.VarbitChanged; +import net.runelite.api.events.WidgetOpened; import net.runelite.api.mixins.Copy; import net.runelite.api.mixins.FieldHook; import net.runelite.api.mixins.Inject; @@ -505,17 +506,23 @@ public abstract class RSClientMixin implements RSClient } @Copy("openWidget") - public static WidgetNode rs$openWidget(int parentHash, int widgetId, int autoClose) + public static WidgetNode rs$openWidget(int parentId, int groupId, int autoClose) { throw new RuntimeException(); } @Replace("openWidget") - public static WidgetNode rl$openWidget(int parentHash, int widgetId, int autoClose) + public static WidgetNode rl$openWidget(int parentId, int groupId, int autoClose) { MenuEntry[] entries = client.getMenuEntries(); - WidgetNode widgetNode = rs$openWidget(parentHash, widgetId, autoClose); + WidgetNode widgetNode = rs$openWidget(parentId, groupId, autoClose); client.setMenuEntries(entries); + + WidgetOpened event = new WidgetOpened(); + event.setParentId(parentId); + event.setGroupId(groupId); + event.setAutoClose(autoClose); + eventBus.post(event); return widgetNode; } From ef02e6e316794e2b38284ea670168e64ca3356eb Mon Sep 17 00:00:00 2001 From: Dennis de V Date: Fri, 16 Mar 2018 17:14:13 -0400 Subject: [PATCH 4/6] runelite-mixins: add null check for widget group in getGroup() --- .../src/main/java/net/runelite/mixins/RSClientMixin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java index 1b5c8dd827..2ad69d4bb7 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java @@ -192,7 +192,7 @@ public abstract class RSClientMixin implements RSClient { RSWidget[][] widgets = getWidgets(); - if (widgets == null || groupId < 0 || groupId >= widgets.length) + if (widgets == null || groupId < 0 || groupId >= widgets.length || widgets[groupId] == null) { return null; } From 814dac53c87d7bd62a2a1476ad48a2db9490426e Mon Sep 17 00:00:00 2001 From: Dennis de V Date: Fri, 16 Mar 2018 17:14:40 -0400 Subject: [PATCH 5/6] runelite-api: add widget config --- .../runelite/api/widgets/WidgetConfig.java | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 runelite-api/src/main/java/net/runelite/api/widgets/WidgetConfig.java diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetConfig.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetConfig.java new file mode 100644 index 0000000000..2a17a7a902 --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetConfig.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018, 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.api.widgets; + +public class WidgetConfig +{ + public static final int DRAG_ON = 1 << 17; + public static final int DRAG = 1 << 20; +} From 164078751ff0bf3b643374d79f984568b7d99984 Mon Sep 17 00:00:00 2001 From: Dennis de V Date: Fri, 16 Mar 2018 17:15:02 -0400 Subject: [PATCH 6/6] runelite-client: add prayer reordering plugin --- .../java/net/runelite/api/widgets/Widget.java | 6 + .../net/runelite/api/widgets/WidgetID.java | 51 ++ .../net/runelite/api/widgets/WidgetInfo.java | 32 ++ .../reorderprayers/PrayerTabState.java | 32 ++ .../reorderprayers/ReorderPrayersConfig.java | 77 +++ .../reorderprayers/ReorderPrayersPlugin.java | 439 ++++++++++++++++++ .../java/net/runelite/rs/api/RSWidget.java | 7 + 7 files changed, 644 insertions(+) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/reorderprayers/PrayerTabState.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/reorderprayers/ReorderPrayersConfig.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/reorderprayers/ReorderPrayersPlugin.java diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/Widget.java b/runelite-api/src/main/java/net/runelite/api/widgets/Widget.java index 3e6c44caa0..9b87b12ccd 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/Widget.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/Widget.java @@ -40,12 +40,18 @@ public interface Widget void setContentType(int contentType); + int getConfig(); + + void setConfig(int config); + Widget getParent(); int getParentId(); Widget getChild(int index); + Widget[] getChildren(); + Widget[] getDynamicChildren(); Widget[] getStaticChildren(); diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java index 4f626cc142..3f51196bf0 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java @@ -45,6 +45,7 @@ public class WidgetID public static final int RESIZABLE_VIEWPORT_OLD_SCHOOL_BOX_GROUP_ID = 161; public static final int RESIZABLE_VIEWPORT_BOTTOM_LINE_GROUP_ID = 164; public static final int PRAYER_GROUP_ID = 541; + public static final int QUICK_PRAYERS_GROUP_ID = 77; public static final int SHOP_GROUP_ID = 300; public static final int SHOP_INVENTORY_GROUP_ID = 301; public static final int GUIDE_PRICES_GROUP_ID = 464; @@ -194,6 +195,21 @@ public class WidgetID static final int RESIZABLE_VIEWPORT_BOTTOM_LINE = 12; } + static class FixedViewport + { + static final int PRAYER_TAB = 53; + } + + static class ResizableViewport + { + static final int PRAYER_TAB = 56; + } + + static class ResizableViewportBottomLine + { + static final int PRAYER_TAB = 53; + } + static class Chatbox { static final int CHATBOX_MESSAGES = 29; @@ -234,6 +250,41 @@ public class WidgetID static final int AUGURY = 31; } + public static class QuickPrayer + { + static final int PRAYERS = 4; + + public static final int THICK_SKIN_CHILD_ID = 0; + public static final int BURST_OF_STRENGTH_CHILD_ID = 1; + public static final int CLARITY_OF_THOUGHT_CHILD_ID = 2; + public static final int SHARP_EYE_CHILD_ID = 18; + public static final int MYSTIC_WILL_CHILD_ID = 19; + public static final int ROCK_SKIN_CHILD_ID = 3; + public static final int SUPERHUMAN_STRENGTH_CHILD_ID = 4; + public static final int IMPROVED_REFLEXES_CHILD_ID = 5; + public static final int RAPID_RESTORE_CHILD_ID = 6; + public static final int RAPID_HEAL_CHILD_ID = 7; + public static final int PROTECT_ITEM_CHILD_ID = 8; + public static final int HAWK_EYE_CHILD_ID = 20; + public static final int MYSTIC_LORE_CHILD_ID = 21; + public static final int STEEL_SKIN_CHILD_ID = 9; + public static final int ULTIMATE_STRENGTH_CHILD_ID = 10; + public static final int INCREDIBLE_REFLEXES_CHILD_ID = 11; + public static final int PROTECT_FROM_MAGIC_CHILD_ID = 12; + public static final int PROTECT_FROM_MISSILES_CHILD_ID = 13; + public static final int PROTECT_FROM_MELEE_CHILD_ID = 14; + public static final int EAGLE_EYE_CHILD_ID = 22; + public static final int MYSTIC_MIGHT_CHILD_ID = 23; + public static final int RETRIBUTION_CHILD_ID = 15; + public static final int REDEMPTION_CHILD_ID = 16; + public static final int SMITE_CHILD_ID = 17; + public static final int PRESERVE_CHILD_ID = 28; + public static final int CHIVALRY_CHILD_ID = 25; + public static final int PIETY_CHILD_ID = 26; + public static final int RIGOUR_CHILD_ID = 24; + public static final int AUGURY_CHILD_ID = 27; + } + static class Combat { static final int WEAPON_NAME = 1; diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java index 5c783df6cb..5e84d3b431 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java @@ -109,12 +109,44 @@ public enum WidgetInfo LOGIN_CLICK_TO_PLAY_SCREEN(WidgetID.LOGIN_CLICK_TO_PLAY_GROUP_ID, 0), FIXED_VIEWPORT(WidgetID.FIXED_VIEWPORT_GROUP_ID, WidgetID.Viewport.FIXED_VIEWPORT), + FIXED_VIEWPORT_PRAYER_TAB(WidgetID.FIXED_VIEWPORT_GROUP_ID, WidgetID.FixedViewport.PRAYER_TAB), MINIMAP_WIDGET(WidgetID.RESIZABLE_VIEWPORT_OLD_SCHOOL_BOX_GROUP_ID, WidgetID.Viewport.MINIMAP_WIDGET), RESIZABLE_VIEWPORT_OLD_SCHOOL_BOX(WidgetID.RESIZABLE_VIEWPORT_OLD_SCHOOL_BOX_GROUP_ID, WidgetID.Viewport.RESIZABLE_VIEWPORT_OLD_SCHOOL_BOX), + RESIZABLE_VIEWPORT_PRAYER_TAB(WidgetID.RESIZABLE_VIEWPORT_OLD_SCHOOL_BOX_GROUP_ID, WidgetID.ResizableViewport.PRAYER_TAB), RESIZABLE_VIEWPORT_BOTTOM_LINE(WidgetID.RESIZABLE_VIEWPORT_BOTTOM_LINE_GROUP_ID, WidgetID.Viewport.RESIZABLE_VIEWPORT_BOTTOM_LINE), + RESIZABLE_VIEWPORT_BOTTOM_LINE_PRAYER_TAB(WidgetID.RESIZABLE_VIEWPORT_BOTTOM_LINE_GROUP_ID, WidgetID.ResizableViewportBottomLine.PRAYER_TAB), + PRAYER_THICK_SKIN(WidgetID.PRAYER_GROUP_ID, WidgetID.Prayer.THICK_SKIN), + PRAYER_BURST_OF_STRENGTH(WidgetID.PRAYER_GROUP_ID, WidgetID.Prayer.BURST_OF_STRENGTH), + PRAYER_CLARITY_OF_THOUGHT(WidgetID.PRAYER_GROUP_ID, WidgetID.Prayer.CLARITY_OF_THOUGHT), + PRAYER_SHARP_EYE(WidgetID.PRAYER_GROUP_ID, WidgetID.Prayer.SHARP_EYE), + PRAYER_MYSTIC_WILL(WidgetID.PRAYER_GROUP_ID, WidgetID.Prayer.MYSTIC_WILL), + PRAYER_ROCK_SKIN(WidgetID.PRAYER_GROUP_ID, WidgetID.Prayer.ROCK_SKIN), + PRAYER_SUPERHUMAN_STRENGTH(WidgetID.PRAYER_GROUP_ID, WidgetID.Prayer.SUPERHUMAN_STRENGTH), + PRAYER_IMPROVED_REFLEXES(WidgetID.PRAYER_GROUP_ID, WidgetID.Prayer.IMPROVED_REFLEXES), + PRAYER_RAPID_RESTORE(WidgetID.PRAYER_GROUP_ID, WidgetID.Prayer.RAPID_RESTORE), + PRAYER_RAPID_HEAL(WidgetID.PRAYER_GROUP_ID, WidgetID.Prayer.RAPID_HEAL), + PRAYER_PROTECT_ITEM(WidgetID.PRAYER_GROUP_ID, WidgetID.Prayer.PROTECT_ITEM), + PRAYER_HAWK_EYE(WidgetID.PRAYER_GROUP_ID, WidgetID.Prayer.HAWK_EYE), + PRAYER_MYSTIC_LORE(WidgetID.PRAYER_GROUP_ID, WidgetID.Prayer.MYSTIC_LORE), + PRAYER_STEEL_SKIN(WidgetID.PRAYER_GROUP_ID, WidgetID.Prayer.STEEL_SKIN), + PRAYER_ULTIMATE_STRENGTH(WidgetID.PRAYER_GROUP_ID, WidgetID.Prayer.ULTIMATE_STRENGTH), + PRAYER_INCREDIBLE_REFLEXES(WidgetID.PRAYER_GROUP_ID, WidgetID.Prayer.INCREDIBLE_REFLEXES), PRAYER_PROTECT_FROM_MAGIC(WidgetID.PRAYER_GROUP_ID, WidgetID.Prayer.PROTECT_FROM_MAGIC), PRAYER_PROTECT_FROM_MISSILES(WidgetID.PRAYER_GROUP_ID, WidgetID.Prayer.PROTECT_FROM_MISSILES), + PRAYER_PROTECT_FROM_MELEE(WidgetID.PRAYER_GROUP_ID, WidgetID.Prayer.PROTECT_FROM_MELEE), + PRAYER_EAGLE_EYE(WidgetID.PRAYER_GROUP_ID, WidgetID.Prayer.EAGLE_EYE), + PRAYER_MYSTIC_MIGHT(WidgetID.PRAYER_GROUP_ID, WidgetID.Prayer.MYSTIC_MIGHT), + PRAYER_RETRIBUTION(WidgetID.PRAYER_GROUP_ID, WidgetID.Prayer.RETRIBUTION), + PRAYER_REDEMPTION(WidgetID.PRAYER_GROUP_ID, WidgetID.Prayer.REDEMPTION), + PRAYER_SMITE(WidgetID.PRAYER_GROUP_ID, WidgetID.Prayer.SMITE), + PRAYER_PRESERVE(WidgetID.PRAYER_GROUP_ID, WidgetID.Prayer.PRESERVE), + PRAYER_CHIVALRY(WidgetID.PRAYER_GROUP_ID, WidgetID.Prayer.CHIVALRY), + PRAYER_PIETY(WidgetID.PRAYER_GROUP_ID, WidgetID.Prayer.PIETY), + PRAYER_RIGOUR(WidgetID.PRAYER_GROUP_ID, WidgetID.Prayer.RIGOUR), + PRAYER_AUGURY(WidgetID.PRAYER_GROUP_ID, WidgetID.Prayer.AUGURY), + + QUICK_PRAYER_PRAYERS(WidgetID.QUICK_PRAYERS_GROUP_ID, WidgetID.QuickPrayer.PRAYERS), COMBAT_LEVEL(WidgetID.COMBAT_GROUP_ID, WidgetID.Combat.LEVEL), COMBAT_STYLE_ONE(WidgetID.COMBAT_GROUP_ID, WidgetID.Combat.STYLE_ONE), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/reorderprayers/PrayerTabState.java b/runelite-client/src/main/java/net/runelite/client/plugins/reorderprayers/PrayerTabState.java new file mode 100644 index 0000000000..993a74f917 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/reorderprayers/PrayerTabState.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018, 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.client.plugins.reorderprayers; + +public enum PrayerTabState +{ + NONE, + PRAYERS, + QUICK_PRAYERS +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/reorderprayers/ReorderPrayersConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/reorderprayers/ReorderPrayersConfig.java new file mode 100644 index 0000000000..807955f104 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/reorderprayers/ReorderPrayersConfig.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018, 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.client.plugins.reorderprayers; + +import net.runelite.api.Prayer; +import net.runelite.client.config.Config; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigItem; + +@ConfigGroup( + keyName = ReorderPrayersPlugin.CONFIG_GROUP_KEY, + name = "Reorder Prayers", + description = "Configuration for the data orb regeneration meters" +) +public interface ReorderPrayersConfig extends Config +{ + + @ConfigItem( + keyName = ReorderPrayersPlugin.CONFIG_UNLOCK_REORDERING_KEY, + name = "Unlock Prayer Reordering", + description = "Configures whether or not you can reorder the prayers", + position = 1 + ) + default boolean unlockPrayerReordering() + { + return false; + } + + @ConfigItem( + keyName = ReorderPrayersPlugin.CONFIG_UNLOCK_REORDERING_KEY, + name = "", + description = "" + ) + void unlockPrayerReordering(boolean unlock); + + @ConfigItem( + keyName = ReorderPrayersPlugin.CONFIG_PRAYER_ORDER_KEY, + name = "Prayer Order", + description = "Configures the order of the prayers", + hidden = true, + position = 2 + ) + default String prayerOrder() + { + return ReorderPrayersPlugin.prayerOrderToString(Prayer.values()); + } + + @ConfigItem( + keyName = ReorderPrayersPlugin.CONFIG_PRAYER_ORDER_KEY, + name = "", + description = "" + ) + void prayerOrder(String prayerOrder); + +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/reorderprayers/ReorderPrayersPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/reorderprayers/ReorderPrayersPlugin.java new file mode 100644 index 0000000000..7a187ce4a4 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/reorderprayers/ReorderPrayersPlugin.java @@ -0,0 +1,439 @@ +/* + * Copyright (c) 2018, 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.client.plugins.reorderprayers; + +import com.google.common.collect.ImmutableList; +import com.google.common.eventbus.Subscribe; +import com.google.inject.Provides; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import javax.inject.Inject; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.HashTable; +import net.runelite.api.Node; +import net.runelite.api.Prayer; +import net.runelite.api.WidgetNode; +import net.runelite.api.events.ConfigChanged; +import net.runelite.api.events.DraggingWidgetChanged; +import net.runelite.api.events.WidgetMenuOptionClicked; +import net.runelite.api.events.WidgetOpened; +import net.runelite.api.widgets.Widget; +import static net.runelite.api.widgets.WidgetConfig.DRAG; +import static net.runelite.api.widgets.WidgetConfig.DRAG_ON; +import net.runelite.api.widgets.WidgetID; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.menus.MenuManager; +import net.runelite.client.menus.WidgetMenuOption; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; + +@Slf4j +@PluginDescriptor(name = "Reorder Prayers") +public class ReorderPrayersPlugin extends Plugin +{ + + static final String CONFIG_GROUP_KEY = "reorderprayers"; + + static final String CONFIG_UNLOCK_REORDERING_KEY = "unlockPrayerReordering"; + + static final String CONFIG_PRAYER_ORDER_KEY = "prayerOrder"; + + private static final int PRAYER_WIDTH = 34; + + private static final int PRAYER_HEIGHT = 34; + + private static final int PRAYER_X_OFFSET = 37; + + private static final int PRAYER_Y_OFFSET = 37; + + private static final int QUICK_PRAYER_SPRITE_X_OFFSET = 2; + + private static final int QUICK_PRAYER_SPRITE_Y_OFFSET = 2; + + private static final int PRAYER_COLUMN_COUNT = 5; + + private static final int PRAYER_COUNT = Prayer.values().length; + + private static final List PRAYER_WIDGET_INFO_LIST = ImmutableList.of( + WidgetInfo.PRAYER_THICK_SKIN, + WidgetInfo.PRAYER_BURST_OF_STRENGTH, + WidgetInfo.PRAYER_CLARITY_OF_THOUGHT, + WidgetInfo.PRAYER_SHARP_EYE, + WidgetInfo.PRAYER_MYSTIC_WILL, + WidgetInfo.PRAYER_ROCK_SKIN, + WidgetInfo.PRAYER_SUPERHUMAN_STRENGTH, + WidgetInfo.PRAYER_IMPROVED_REFLEXES, + WidgetInfo.PRAYER_RAPID_RESTORE, + WidgetInfo.PRAYER_RAPID_HEAL, + WidgetInfo.PRAYER_PROTECT_ITEM, + WidgetInfo.PRAYER_HAWK_EYE, + WidgetInfo.PRAYER_MYSTIC_LORE, + WidgetInfo.PRAYER_STEEL_SKIN, + WidgetInfo.PRAYER_ULTIMATE_STRENGTH, + WidgetInfo.PRAYER_INCREDIBLE_REFLEXES, + WidgetInfo.PRAYER_PROTECT_FROM_MAGIC, + WidgetInfo.PRAYER_PROTECT_FROM_MISSILES, + WidgetInfo.PRAYER_PROTECT_FROM_MELEE, + WidgetInfo.PRAYER_EAGLE_EYE, + WidgetInfo.PRAYER_MYSTIC_MIGHT, + WidgetInfo.PRAYER_RETRIBUTION, + WidgetInfo.PRAYER_REDEMPTION, + WidgetInfo.PRAYER_SMITE, + WidgetInfo.PRAYER_PRESERVE, + WidgetInfo.PRAYER_CHIVALRY, + WidgetInfo.PRAYER_PIETY, + WidgetInfo.PRAYER_RIGOUR, + WidgetInfo.PRAYER_AUGURY + ); + + private static final List QUICK_PRAYER_CHILD_IDS = ImmutableList.of( + WidgetID.QuickPrayer.THICK_SKIN_CHILD_ID, + WidgetID.QuickPrayer.BURST_OF_STRENGTH_CHILD_ID, + WidgetID.QuickPrayer.CLARITY_OF_THOUGHT_CHILD_ID, + WidgetID.QuickPrayer.SHARP_EYE_CHILD_ID, + WidgetID.QuickPrayer.MYSTIC_WILL_CHILD_ID, + WidgetID.QuickPrayer.ROCK_SKIN_CHILD_ID, + WidgetID.QuickPrayer.SUPERHUMAN_STRENGTH_CHILD_ID, + WidgetID.QuickPrayer.IMPROVED_REFLEXES_CHILD_ID, + WidgetID.QuickPrayer.RAPID_RESTORE_CHILD_ID, + WidgetID.QuickPrayer.RAPID_HEAL_CHILD_ID, + WidgetID.QuickPrayer.PROTECT_ITEM_CHILD_ID, + WidgetID.QuickPrayer.HAWK_EYE_CHILD_ID, + WidgetID.QuickPrayer.MYSTIC_LORE_CHILD_ID, + WidgetID.QuickPrayer.STEEL_SKIN_CHILD_ID, + WidgetID.QuickPrayer.ULTIMATE_STRENGTH_CHILD_ID, + WidgetID.QuickPrayer.INCREDIBLE_REFLEXES_CHILD_ID, + WidgetID.QuickPrayer.PROTECT_FROM_MAGIC_CHILD_ID, + WidgetID.QuickPrayer.PROTECT_FROM_MISSILES_CHILD_ID, + WidgetID.QuickPrayer.PROTECT_FROM_MELEE_CHILD_ID, + WidgetID.QuickPrayer.EAGLE_EYE_CHILD_ID, + WidgetID.QuickPrayer.MYSTIC_MIGHT_CHILD_ID, + WidgetID.QuickPrayer.RETRIBUTION_CHILD_ID, + WidgetID.QuickPrayer.REDEMPTION_CHILD_ID, + WidgetID.QuickPrayer.SMITE_CHILD_ID, + WidgetID.QuickPrayer.PRESERVE_CHILD_ID, + WidgetID.QuickPrayer.CHIVALRY_CHILD_ID, + WidgetID.QuickPrayer.PIETY_CHILD_ID, + WidgetID.QuickPrayer.RIGOUR_CHILD_ID, + WidgetID.QuickPrayer.AUGURY_CHILD_ID + ); + + private static final String LOCK = "Lock"; + + private static final String UNLOCK = "Unlock"; + + private static final String MENU_TARGET = "Reordering"; + + private static final WidgetMenuOption FIXED_PRAYER_TAB_LOCK = new WidgetMenuOption(LOCK, + MENU_TARGET, WidgetInfo.FIXED_VIEWPORT_PRAYER_TAB); + + private static final WidgetMenuOption FIXED_PRAYER_TAB_UNLOCK = new WidgetMenuOption(UNLOCK, + MENU_TARGET, WidgetInfo.FIXED_VIEWPORT_PRAYER_TAB); + + private static final WidgetMenuOption RESIZABLE_PRAYER_TAB_LOCK = new WidgetMenuOption(LOCK, + MENU_TARGET, WidgetInfo.RESIZABLE_VIEWPORT_PRAYER_TAB); + + private static final WidgetMenuOption RESIZABLE_PRAYER_TAB_UNLOCK = new WidgetMenuOption(UNLOCK, + MENU_TARGET, WidgetInfo.RESIZABLE_VIEWPORT_PRAYER_TAB); + + private static final WidgetMenuOption RESIZABLE_BOTTOM_LINE_PRAYER_TAB_LOCK = new WidgetMenuOption(LOCK, + MENU_TARGET, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_PRAYER_TAB); + + private static final WidgetMenuOption RESIZABLE_BOTTOM_LINE_PRAYER_TAB_UNLOCK = new WidgetMenuOption(UNLOCK, + MENU_TARGET, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_PRAYER_TAB); + + @Inject + private Client client; + + @Inject + private ReorderPrayersConfig config; + + @Inject + private MenuManager menuManager; + + private Prayer[] prayerOrder; + + static String prayerOrderToString(Prayer[] prayerOrder) + { + return Arrays.stream(prayerOrder) + .map(Prayer::name) + .collect(Collectors.joining(",")); + } + + private static Prayer[] stringToPrayerOrder(String string) + { + return Arrays.stream(string.split(",")) + .map(Prayer::valueOf) + .toArray(Prayer[]::new); + } + + private static int getPrayerIndex(Widget widget) + { + int x = widget.getOriginalX() / PRAYER_X_OFFSET; + int y = widget.getOriginalY() / PRAYER_Y_OFFSET; + return x + y * PRAYER_COLUMN_COUNT; + } + + private static void setWidgetPosition(Widget widget, int x, int y) + { + widget.setRelativeX(x); + widget.setRelativeY(y); + widget.setOriginalX(x); + widget.setOriginalY(y); + } + + @Provides + ReorderPrayersConfig provideConfig(ConfigManager configManager) + { + return configManager.getConfig(ReorderPrayersConfig.class); + } + + @Override + protected void startUp() throws Exception + { + refreshPrayerTabOption(); + prayerOrder = stringToPrayerOrder(config.prayerOrder()); + reorderPrayers(); + } + + @Override + protected void shutDown() throws Exception + { + clearPrayerTabMenus(); + prayerOrder = Prayer.values(); + reorderPrayers(); + } + + @Subscribe + public void onConfigChanged(ConfigChanged event) + { + if (event.getGroup().equals(CONFIG_GROUP_KEY)) + { + if (event.getKey().equals(CONFIG_PRAYER_ORDER_KEY)) + { + prayerOrder = stringToPrayerOrder(config.prayerOrder()); + } + else if (event.getKey().equals(CONFIG_UNLOCK_REORDERING_KEY)) + { + refreshPrayerTabOption(); + } + reorderPrayers(); + } + } + + @Subscribe + public void onWidgetOpened(WidgetOpened event) + { + if (event.getGroupId() == WidgetID.PRAYER_GROUP_ID || event.getGroupId() == WidgetID.QUICK_PRAYERS_GROUP_ID) + { + reorderPrayers(); + } + } + + @Subscribe + public void onDraggingWidgetChanged(DraggingWidgetChanged event) + { + // is dragging widget and mouse button released + if (event.isDraggingWidget() && client.getMouseCurrentButton() == 0) + { + Widget draggedWidget = client.getDraggedWidget(); + Widget draggedOnWidget = client.getDraggedOnWidget(); + if (draggedWidget != null && draggedOnWidget != null) + { + int draggedGroupId = WidgetInfo.TO_GROUP(draggedWidget.getId()); + int draggedOnGroupId = WidgetInfo.TO_GROUP(draggedOnWidget.getId()); + if (draggedGroupId != WidgetID.PRAYER_GROUP_ID || draggedOnGroupId != WidgetID.PRAYER_GROUP_ID + || draggedOnWidget.getWidth() != PRAYER_WIDTH || draggedOnWidget.getHeight() != PRAYER_HEIGHT) + { + return; + } + // reset dragged on widget to prevent sending a drag widget packet to the server + client.setDraggedOnWidget(null); + + int fromPrayerIndex = getPrayerIndex(draggedWidget); + int toPrayerIndex = getPrayerIndex(draggedOnWidget); + + Prayer tmp = prayerOrder[toPrayerIndex]; + prayerOrder[toPrayerIndex] = prayerOrder[fromPrayerIndex]; + prayerOrder[fromPrayerIndex] = tmp; + + save(); + } + } + } + + @Subscribe + public void onWidgetMenuOptionClicked(WidgetMenuOptionClicked event) + { + if (event.getWidget() == WidgetInfo.FIXED_VIEWPORT_PRAYER_TAB + || event.getWidget() == WidgetInfo.RESIZABLE_VIEWPORT_PRAYER_TAB + || event.getWidget() == WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_PRAYER_TAB) + { + config.unlockPrayerReordering(event.getMenuOption().equals(UNLOCK)); + } + } + + private void clearPrayerTabMenus() + { + menuManager.removeManagedCustomMenu(FIXED_PRAYER_TAB_LOCK); + menuManager.removeManagedCustomMenu(RESIZABLE_PRAYER_TAB_LOCK); + menuManager.removeManagedCustomMenu(RESIZABLE_BOTTOM_LINE_PRAYER_TAB_LOCK); + menuManager.removeManagedCustomMenu(FIXED_PRAYER_TAB_UNLOCK); + menuManager.removeManagedCustomMenu(RESIZABLE_PRAYER_TAB_UNLOCK); + menuManager.removeManagedCustomMenu(RESIZABLE_BOTTOM_LINE_PRAYER_TAB_UNLOCK); + } + + private void refreshPrayerTabOption() + { + clearPrayerTabMenus(); + if (config.unlockPrayerReordering()) + { + menuManager.addManagedCustomMenu(FIXED_PRAYER_TAB_LOCK); + menuManager.addManagedCustomMenu(RESIZABLE_PRAYER_TAB_LOCK); + menuManager.addManagedCustomMenu(RESIZABLE_BOTTOM_LINE_PRAYER_TAB_LOCK); + } + else + { + menuManager.addManagedCustomMenu(FIXED_PRAYER_TAB_UNLOCK); + menuManager.addManagedCustomMenu(RESIZABLE_PRAYER_TAB_UNLOCK); + menuManager.addManagedCustomMenu(RESIZABLE_BOTTOM_LINE_PRAYER_TAB_UNLOCK); + } + } + + private PrayerTabState getPrayerTabState() + { + HashTable componentTable = client.getComponentTable(); + for (Node node : componentTable.getNodes()) + { + WidgetNode widgetNode = (WidgetNode) node; + if (widgetNode.getId() == WidgetID.PRAYER_GROUP_ID) + { + return PrayerTabState.PRAYERS; + } + else if (widgetNode.getId() == WidgetID.QUICK_PRAYERS_GROUP_ID) + { + return PrayerTabState.QUICK_PRAYERS; + } + } + return PrayerTabState.NONE; + } + + private void save() + { + config.prayerOrder(prayerOrderToString(prayerOrder)); + } + + private void reorderPrayers() + { + if (client.getGameState() != GameState.LOGGED_IN) + { + return; + } + + PrayerTabState prayerTabState = getPrayerTabState(); + + if (prayerTabState == PrayerTabState.PRAYERS) + { + List prayerWidgets = PRAYER_WIDGET_INFO_LIST.stream() + .map(client::getWidget) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + + if (prayerWidgets.size() != PRAYER_WIDGET_INFO_LIST.size()) + { + return; + } + + for (int index = 0; index < prayerOrder.length; index++) + { + Prayer prayer = prayerOrder[index]; + Widget prayerWidget = prayerWidgets.get(prayer.ordinal()); + + int widgetConfig = prayerWidget.getConfig(); + if (config.unlockPrayerReordering()) + { + // allow dragging of this widget + widgetConfig |= DRAG; + // allow this widget to be dragged on + widgetConfig |= DRAG_ON; + } + else + { + // remove drag flag + widgetConfig &= ~DRAG; + // remove drag on flag + widgetConfig &= ~DRAG_ON; + } + prayerWidget.setConfig(widgetConfig); + + int x = index % PRAYER_COLUMN_COUNT; + int y = index / PRAYER_COLUMN_COUNT; + int widgetX = x * PRAYER_X_OFFSET; + int widgetY = y * PRAYER_Y_OFFSET; + setWidgetPosition(prayerWidget, widgetX, widgetY); + } + } + else if (prayerTabState == PrayerTabState.QUICK_PRAYERS) + { + Widget prayersContainer = client.getWidget(WidgetInfo.QUICK_PRAYER_PRAYERS); + if (prayersContainer == null) + { + return; + } + Widget[] prayerWidgets = prayersContainer.getDynamicChildren(); + if (prayerWidgets == null || prayerWidgets.length != PRAYER_COUNT * 3) + { + return; + } + + for (int index = 0; index < prayerOrder.length; index++) + { + Prayer prayer = prayerOrder[index]; + + int x = index % PRAYER_COLUMN_COUNT; + int y = index / PRAYER_COLUMN_COUNT; + + Widget prayerWidget = prayerWidgets[QUICK_PRAYER_CHILD_IDS.get(prayer.ordinal())]; + setWidgetPosition(prayerWidget, x * PRAYER_X_OFFSET, y * PRAYER_Y_OFFSET); + + int childId = PRAYER_COUNT + 2 * prayer.ordinal(); + + Widget prayerSpriteWidget = prayerWidgets[childId]; + setWidgetPosition(prayerSpriteWidget, + QUICK_PRAYER_SPRITE_X_OFFSET + x * PRAYER_X_OFFSET, + QUICK_PRAYER_SPRITE_Y_OFFSET + y * PRAYER_Y_OFFSET); + + Widget prayerToggleWidget = prayerWidgets[childId + 1]; + setWidgetPosition(prayerToggleWidget, x * PRAYER_X_OFFSET, y * PRAYER_Y_OFFSET); + } + } + } + +} diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSWidget.java b/runescape-api/src/main/java/net/runelite/rs/api/RSWidget.java index 370931a397..ae59ab017b 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSWidget.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSWidget.java @@ -33,6 +33,7 @@ public interface RSWidget extends Widget int[][] getDynamicValues(); @Import("children") + @Override RSWidget[] getChildren(); @Import("id") @@ -42,6 +43,12 @@ public interface RSWidget extends Widget @Import("parentId") int getRSParentId(); + @Import("config") + int getConfig(); + + @Import("config") + void setConfig(int config); + @Import("boundsIndex") int getBoundsIndex();