diff --git a/runelite-api/src/main/java/net/runelite/api/queries/BankItemQuery.java b/runelite-api/src/main/java/net/runelite/api/queries/BankItemQuery.java
index 31bfc77f25..2153072fb8 100644
--- a/runelite-api/src/main/java/net/runelite/api/queries/BankItemQuery.java
+++ b/runelite-api/src/main/java/net/runelite/api/queries/BankItemQuery.java
@@ -67,7 +67,7 @@ public class BankItemQuery extends WidgetItemQuery
Rectangle bounds = child.getBounds();
bounds.setBounds(bounds.x - 1, bounds.y - 1, 32, 32);
// Index is set to 0 because the widget's index does not correlate to the order in the bank
- widgetItems.add(new WidgetItem(child.getItemId(), child.getItemQuantity(), 0, bounds, child));
+ widgetItems.add(new WidgetItem(child.getItemId(), child.getItemQuantity(), 0, bounds, child, false));
}
}
return widgetItems;
diff --git a/runelite-api/src/main/java/net/runelite/api/queries/DialogQuery.java b/runelite-api/src/main/java/net/runelite/api/queries/DialogQuery.java
index 426bdf00a4..0b4cfb8c03 100644
--- a/runelite-api/src/main/java/net/runelite/api/queries/DialogQuery.java
+++ b/runelite-api/src/main/java/net/runelite/api/queries/DialogQuery.java
@@ -73,7 +73,7 @@ public class DialogQuery extends WidgetItemQuery
// set bounds to same size as default inventory
Rectangle bounds = child.getBounds();
bounds.setBounds(bounds.x - 1, bounds.y - 1, 32, 32);
- widgetItems.add(new WidgetItem(child.getId(), child.getItemQuantity(), i - 1, bounds, child));
+ widgetItems.add(new WidgetItem(child.getId(), child.getItemQuantity(), i - 1, bounds, child, false));
}
}
return widgetItems;
diff --git a/runelite-api/src/main/java/net/runelite/api/queries/InventoryWidgetItemQuery.java b/runelite-api/src/main/java/net/runelite/api/queries/InventoryWidgetItemQuery.java
index e6d4e2a588..9072dbeeda 100644
--- a/runelite-api/src/main/java/net/runelite/api/queries/InventoryWidgetItemQuery.java
+++ b/runelite-api/src/main/java/net/runelite/api/queries/InventoryWidgetItemQuery.java
@@ -30,6 +30,7 @@ import java.util.Collection;
import java.util.Objects;
import java.util.stream.Collectors;
import net.runelite.api.Client;
+import net.runelite.api.Point;
import net.runelite.api.QueryResults;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetInfo;
@@ -79,10 +80,20 @@ public class InventoryWidgetItemQuery extends WidgetItemQuery
for (int i = 0; i < children.length; i++)
{
Widget child = children[i];
+ boolean isDragged = child.isWidgetItemDragged(child.getItemId());
+ int dragOffsetX = 0;
+ int dragOffsetY = 0;
+
+ if (isDragged)
+ {
+ Point p = child.getWidgetItemDragOffsets();
+ dragOffsetX = p.getX();
+ dragOffsetY = p.getY();
+ }
// set bounds to same size as default inventory
Rectangle bounds = child.getBounds();
- bounds.setBounds(bounds.x - 1, bounds.y - 1, 32, 32);
- widgetItems.add(new WidgetItem(child.getItemId(), child.getItemQuantity(), i, bounds, child));
+ bounds.setBounds(bounds.x + dragOffsetX, bounds.y + dragOffsetY, 32, 32);
+ widgetItems.add(new WidgetItem(child.getItemId(), child.getItemQuantity(), i, bounds, child, isDragged));
}
break;
}
diff --git a/runelite-api/src/main/java/net/runelite/api/queries/ShopItemQuery.java b/runelite-api/src/main/java/net/runelite/api/queries/ShopItemQuery.java
index 92116d2b9a..a76851fe0a 100644
--- a/runelite-api/src/main/java/net/runelite/api/queries/ShopItemQuery.java
+++ b/runelite-api/src/main/java/net/runelite/api/queries/ShopItemQuery.java
@@ -60,7 +60,7 @@ public class ShopItemQuery extends WidgetItemQuery
// set bounds to same size as default inventory
Rectangle bounds = child.getBounds();
bounds.setBounds(bounds.x - 1, bounds.y - 1, 32, 32);
- widgetItems.add(new WidgetItem(child.getItemId(), child.getItemQuantity(), i - 1, bounds, child));
+ widgetItems.add(new WidgetItem(child.getItemId(), child.getItemQuantity(), i - 1, bounds, child, false)); // todo: maybe this shouldnt just be "false"
}
}
return widgetItems;
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 b8cb626ae6..e003e30950 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
@@ -946,4 +946,8 @@ public interface Widget
* @param args A ScriptID, then the args for the script
*/
void setOnReleaseListener(Object ...args);
+
+ boolean isWidgetItemDragged(int index);
+
+ Point getWidgetItemDragOffsets();
}
diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetItem.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetItem.java
index 7cec838c98..57b0d522f5 100644
--- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetItem.java
+++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetItem.java
@@ -63,6 +63,10 @@ public class WidgetItem
* The widget which contains this item.
*/
private final Widget widget;
+ /**
+ * Whether or not this widget item is being dragged.
+ */
+ private final boolean dragging;
/**
* Gets the upper-left coordinate of where the widget is being drawn
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/PluginManager.java b/runelite-client/src/main/java/net/runelite/client/plugins/PluginManager.java
index 8f1f097f26..ebf5ed2f89 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/PluginManager.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/PluginManager.java
@@ -41,7 +41,6 @@ import com.google.inject.Key;
import com.google.inject.Module;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
@@ -73,7 +72,6 @@ import net.runelite.client.eventbus.EventBus;
import net.runelite.client.events.PluginChanged;
import net.runelite.client.events.SessionClose;
import net.runelite.client.events.SessionOpen;
-import net.runelite.client.task.Schedule;
import net.runelite.client.task.ScheduledMethod;
import net.runelite.client.task.Scheduler;
import net.runelite.client.ui.RuneLiteSplashScreen;
@@ -541,22 +539,10 @@ public class PluginManager
return plugins;
}
- private void schedule(Plugin plugin)
+ public void schedule(Object plugin)
{
- for (Method method : plugin.getClass().getMethods())
- {
- Schedule schedule = method.getAnnotation(Schedule.class);
-
- if (schedule == null)
- {
- continue;
- }
-
- ScheduledMethod scheduledMethod = new ScheduledMethod(schedule, method, plugin);
- log.debug("Scheduled task {}", scheduledMethod);
-
- scheduler.addScheduledMethod(scheduledMethod);
- }
+ // note to devs: this method will almost certainly merge conflict in the future, just apply the changes in the scheduler instead
+ scheduler.registerObject(plugin);
}
private void unschedule(Plugin plugin)
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java
index 3f7c821000..ab4e716cf9 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java
@@ -94,7 +94,7 @@ public class ChatCommandsPlugin extends Plugin
{
private static final Pattern KILLCOUNT_PATTERN = Pattern.compile("Your (.+) (?:kill|harvest|lap|completion) count is:
(\\d+)");
private static final Pattern RAIDS_PATTERN = Pattern.compile("Your completed (.+) count is: (\\d+)");
- private static final Pattern RAIDS_DURATION_PATTERN = Pattern.compile("Congratulations - your raid is complete! Duration ([0-9:]+)");
+ private static final Pattern RAIDS_DURATION_PATTERN = Pattern.compile("Congratulations - your raid is complete! Duration: ([0-9:]+)");
private static final Pattern WINTERTODT_PATTERN = Pattern.compile("Your subdued Wintertodt count is: (\\d+)");
private static final Pattern BARROWS_PATTERN = Pattern.compile("Your Barrows chest count is: (\\d+)");
private static final Pattern KILL_DURATION_PATTERN = Pattern.compile("(?i)^(?:Fight |Lap |Challenge |Corrupted challenge )?duration: [0-9:]+\\. Personal best: ([0-9:]+)");
@@ -411,7 +411,8 @@ public class ChatCommandsPlugin extends Plugin
{
if (chatMessage.getType() != ChatMessageType.TRADE
&& chatMessage.getType() != ChatMessageType.GAMEMESSAGE
- && chatMessage.getType() != ChatMessageType.SPAM)
+ && chatMessage.getType() != ChatMessageType.SPAM
+ && chatMessage.getType() != ChatMessageType.FRIENDSCHATNOTIFICATION)
{
return;
}
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/clanchat/ClanChatPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/clanchat/ClanChatPlugin.java
index 7870aa3bfd..4ba6f7dc81 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/clanchat/ClanChatPlugin.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/clanchat/ClanChatPlugin.java
@@ -536,7 +536,9 @@ public class ClanChatPlugin extends Plugin
{
final int[] intStack = client.getIntStack();
final int size = client.getIntStackSize();
- intStack[size - 1] = config.clanTabChat() ? 1 : 0;
+ // If the user accidentally adds a / when the config and the clan chat tab is active, handle it like a normal message
+ boolean alterClanChatDispatch = config.clanTabChat() && !client.getVar(VarClientStr.CHATBOX_TYPED_TEXT).startsWith("/");
+ intStack[size - 1] = alterClanChatDispatch ? 1 : 0;
break;
}
case "confirmClanKick":
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CoordinateClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CoordinateClue.java
index e93e464370..da7a816e2f 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CoordinateClue.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CoordinateClue.java
@@ -87,7 +87,7 @@ public class CoordinateClue extends ClueScroll implements TextClueScroll, Locati
.put(new WorldPoint(3770, 3898, 0), "On the small island north-east of Fossil Island's mushroom forest.")
// Hard
.put(new WorldPoint(2209, 3161, 0), "North-east of Tyras Camp (BJS).")
- .put(new WorldPoint(2181, 3206, 0), "South of Elf Camp.")
+ .put(new WorldPoint(2181, 3206, 0), "South of Iorwerth Camp.")
.put(new WorldPoint(3081, 3209, 0), "Small Island (CLP).")
.put(new WorldPoint(3399, 3246, 0), "Behind the Duel Arena.")
.put(new WorldPoint(2699, 3251, 0), "Little island (AIR).")
@@ -142,7 +142,7 @@ public class CoordinateClue extends ClueScroll implements TextClueScroll, Locati
.put(new WorldPoint(3587, 3180, 0), "Meiyerditch.")
.put(new WorldPoint(2820, 3078, 0), "Tai Bwo Wannai. Hardwood Grove.")
.put(new WorldPoint(3811, 3060, 0), "Small island north-east of Mos Le'Harmless.")
- .put(new WorldPoint(2180, 3282, 0), "North of Elf Camp.")
+ .put(new WorldPoint(2180, 3282, 0), "North of Iorwerth Camp.")
.put(new WorldPoint(2870, 2997, 0), "North-east of Shilo Village.")
.put(new WorldPoint(3302, 2988, 0), "On top of a cliff to the west of Pollnivneach.")
.put(new WorldPoint(2511, 2980, 0), "Just south of Gu'Tanoth, west of gnome glider.")
@@ -171,7 +171,7 @@ public class CoordinateClue extends ClueScroll implements TextClueScroll, Locati
.put(new WorldPoint(2872, 3937, 0), "Weiss.")
.put(new WorldPoint(2484, 4016, 0), "Northeast corner of the Island of Stone.")
// Master
- .put(new WorldPoint(2178, 3209, 0), "South of Elf Camp.")
+ .put(new WorldPoint(2178, 3209, 0), "South of Iorwerth Camp.")
.put(new WorldPoint(2155, 3100, 0), "South of Port Tyras (BJS).")
.put(new WorldPoint(2217, 3092, 0), "Poison Waste island (DLR).")
.put(new WorldPoint(3830, 3060, 0), "Small island located north-east of Mos Le'Harmless.")
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/hotcold/HotColdLocation.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/hotcold/HotColdLocation.java
index 83290d4ca1..8a6975abfd 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/hotcold/HotColdLocation.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/hotcold/HotColdLocation.java
@@ -131,8 +131,8 @@ public enum HotColdLocation
WESTERN_PROVINCE_PISCATORIS(new WorldPoint(2337, 3689, 0), WESTERN_PROVINCE, "Piscatoris Fishing Colony"),
WESTERN_PROVINCE_PISCATORIS_HUNTER_AREA(new WorldPoint(2359, 3564, 0), WESTERN_PROVINCE, "Eastern part of Piscatoris Hunter area, south-west of the Falconry."),
WESTERN_PROVINCE_ARANDAR(new WorldPoint(2366, 3318, 0), WESTERN_PROVINCE, "South-west of the crystal gate to Arandar."),
- WESTERN_PROVINCE_ELF_CAMP_EAST(new WorldPoint(2270, 3244, 0), WESTERN_PROVINCE, "East of Elf Camp."),
- WESTERN_PROVINCE_ELF_CAMP_NW(new WorldPoint(2174, 3280, 0), WESTERN_PROVINCE, "North-west of Elf Camp."),
+ WESTERN_PROVINCE_ELF_CAMP_EAST(new WorldPoint(2270, 3244, 0), WESTERN_PROVINCE, "East of Iorwerth Camp."),
+ WESTERN_PROVINCE_ELF_CAMP_NW(new WorldPoint(2174, 3280, 0), WESTERN_PROVINCE, "North-west of Iorwerth Camp."),
WESTERN_PROVINCE_LLETYA(new WorldPoint(2335, 3166, 0), WESTERN_PROVINCE, "In Lletya."),
WESTERN_PROVINCE_TYRAS(new WorldPoint(2204, 3157, 0), WESTERN_PROVINCE, "Near Tyras Camp."),
WESTERN_PROVINCE_ZULANDRA(new WorldPoint(2196, 3057, 0), WESTERN_PROVINCE, "The northern house at Zul-Andra."),
diff --git a/runelite-client/src/main/java/net/runelite/client/task/ScheduledMethod.java b/runelite-client/src/main/java/net/runelite/client/task/ScheduledMethod.java
index e91a5a89ff..5e39b49f0e 100644
--- a/runelite-client/src/main/java/net/runelite/client/task/ScheduledMethod.java
+++ b/runelite-client/src/main/java/net/runelite/client/task/ScheduledMethod.java
@@ -26,49 +26,22 @@ package net.runelite.client.task;
import java.lang.reflect.Method;
import java.time.Instant;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+@RequiredArgsConstructor
+@ToString
+@Getter
public class ScheduledMethod
{
private final Schedule schedule;
private final Method method;
private final Object object;
+ @EqualsAndHashCode.Exclude
+ private final Runnable lambda;
+ @Setter
private Instant last = Instant.now();
-
- public ScheduledMethod(Schedule schedule, Method method, Object object)
- {
- this.schedule = schedule;
- this.method = method;
- this.object = object;
- }
-
- @Override
- public String toString()
- {
- return "ScheduledMethod{" + "schedule=" + schedule + ", method=" + method + ", object=" + object + '}';
- }
-
- public Schedule getSchedule()
- {
- return schedule;
- }
-
- public Method getMethod()
- {
- return method;
- }
-
- public Object getObject()
- {
- return object;
- }
-
- public Instant getLast()
- {
- return last;
- }
-
- public void setLast(Instant last)
- {
- this.last = last;
- }
}
diff --git a/runelite-client/src/main/java/net/runelite/client/task/Scheduler.java b/runelite-client/src/main/java/net/runelite/client/task/Scheduler.java
index 7cf6b0796f..8fcba6baf1 100644
--- a/runelite-client/src/main/java/net/runelite/client/task/Scheduler.java
+++ b/runelite-client/src/main/java/net/runelite/client/task/Scheduler.java
@@ -24,6 +24,11 @@
*/
package net.runelite.client.task;
+import java.lang.invoke.CallSite;
+import java.lang.invoke.LambdaMetafactory;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.time.Duration;
@@ -62,15 +67,41 @@ public class Scheduler
public void registerObject(Object obj)
{
- for (Method method : obj.getClass().getDeclaredMethods())
+ for (Method method : obj.getClass().getMethods())
{
Schedule schedule = method.getAnnotation(Schedule.class);
+
if (schedule == null)
{
continue;
}
- ScheduledMethod scheduledMethod = new ScheduledMethod(schedule, method, obj);
+ Runnable runnable = null;
+ try
+ {
+ final Class> clazz = method.getDeclaringClass();
+ final MethodHandles.Lookup caller = MethodHandles.privateLookupIn(clazz, MethodHandles.lookup());
+ final MethodType subscription = MethodType.methodType(method.getReturnType(), method.getParameterTypes());
+ final MethodHandle target = caller.findVirtual(clazz, method.getName(), subscription);
+ final CallSite site = LambdaMetafactory.metafactory(
+ caller,
+ "run",
+ MethodType.methodType(Runnable.class, clazz),
+ subscription,
+ target,
+ subscription);
+
+ final MethodHandle factory = site.getTarget();
+ runnable = (Runnable) factory.bindTo(obj).invokeExact();
+ }
+ catch (Throwable e)
+ {
+ log.warn("Unable to create lambda for method {}", method, e);
+ }
+
+ ScheduledMethod scheduledMethod = new ScheduledMethod(schedule, method, obj, runnable);
+ log.debug("Scheduled task {}", scheduledMethod);
+
addScheduledMethod(scheduledMethod);
}
}
@@ -120,11 +151,18 @@ public class Scheduler
private void run(ScheduledMethod scheduledMethod)
{
- Method method = scheduledMethod.getMethod();
-
try
{
- method.invoke(scheduledMethod.getObject());
+ Runnable lambda = scheduledMethod.getLambda();
+ if (lambda != null)
+ {
+ lambda.run();
+ }
+ else
+ {
+ Method method = scheduledMethod.getMethod();
+ method.invoke(scheduledMethod.getObject());
+ }
}
catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex)
{
diff --git a/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java b/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java
index 3a2704f30a..5ee14960bd 100644
--- a/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java
+++ b/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java
@@ -612,32 +612,6 @@ public class ClientUI
{
OSXUtil.requestFocus();
}
- // See https://stackoverflow.com/questions/309023/how-to-bring-a-window-to-the-front/7435722#7435722
- else if (OSType.getOSType() == OSType.Windows && !frame.isFocused())
- {
- SwingUtilities.invokeLater(() ->
- {
- if ((frame.getExtendedState() & JFrame.MAXIMIZED_BOTH) == JFrame.MAXIMIZED_BOTH)
- {
- frame.setExtendedState(JFrame.ICONIFIED);
- frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
- }
- else
- {
- // If the client is snapped to the top and bottom edges of the screen, setExtendedState will
- // will reset it so setSize and setLocation ensure that the client doesn't move or resize.
- // It is done this way because Windows does not support JFrame.MAXIMIZED_VERT
- int x = frame.getLocation().x;
- int y = frame.getLocation().y;
- int width = frame.getWidth();
- int height = frame.getHeight();
- frame.setExtendedState(JFrame.ICONIFIED);
- frame.setExtendedState(JFrame.NORMAL);
- frame.setLocation(x, y);
- frame.setSize(width, height);
- }
- });
- }
frame.requestFocus();
giveClientFocus();
diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/chatcommands/ChatCommandsPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/chatcommands/ChatCommandsPluginTest.java
index d3e5d0a562..375044d2b2 100644
--- a/runelite-client/src/test/java/net/runelite/client/plugins/chatcommands/ChatCommandsPluginTest.java
+++ b/runelite-client/src/test/java/net/runelite/client/plugins/chatcommands/ChatCommandsPluginTest.java
@@ -29,6 +29,7 @@ import com.google.inject.testing.fieldbinder.Bind;
import com.google.inject.testing.fieldbinder.BoundFieldModule;
import java.util.concurrent.ScheduledExecutorService;
import javax.inject.Inject;
+import static net.runelite.api.ChatMessageType.FRIENDSCHATNOTIFICATION;
import static net.runelite.api.ChatMessageType.GAMEMESSAGE;
import static net.runelite.api.ChatMessageType.TRADE;
import net.runelite.api.Client;
@@ -371,7 +372,7 @@ public class ChatCommandsPluginTest
{
when(client.getUsername()).thenReturn("Adam");
- ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Congratulations - your raid is complete! Duration 37:04", null, 0);
+ ChatMessage chatMessage = new ChatMessage(null, FRIENDSCHATNOTIFICATION, "", "Congratulations - your raid is complete! Duration: 37:04", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your completed Chambers of Xeric count is: 51.", null, 0);
@@ -387,7 +388,7 @@ public class ChatCommandsPluginTest
when(client.getUsername()).thenReturn("Adam");
when(configManager.getConfiguration(anyString(), anyString(), any())).thenReturn(2224);
- ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Congratulations - your raid is complete! Duration 1:45:04", null, 0);
+ ChatMessage chatMessage = new ChatMessage(null, FRIENDSCHATNOTIFICATION, "", "Congratulations - your raid is complete! Duration: 1:45:04", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your completed Chambers of Xeric count is: 52.", null, 0);
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 4ba47a93fd..faa87bf2d1 100644
--- a/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java
+++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java
@@ -1529,7 +1529,7 @@ public abstract class RSClientMixin implements RSClient
{
if (renderX >= minX && renderX <= maxX && renderY >= minY && renderY <= maxY)
{
- WidgetItem widgetItem = new WidgetItem(widget.getItemId(), widget.getItemQuantity(), -1, widget.getBounds(), widget);
+ WidgetItem widgetItem = new WidgetItem(widget.getItemId(), widget.getItemQuantity(), -1, widget.getBounds(), widget, false);
callbacks.drawItem(widget.getItemId(), widgetItem);
}
}
diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSWidgetMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSWidgetMixin.java
index 466baf67d1..f10da765f4 100644
--- a/runelite-mixins/src/main/java/net/runelite/mixins/RSWidgetMixin.java
+++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSWidgetMixin.java
@@ -24,11 +24,6 @@
*/
package net.runelite.mixins;
-import java.awt.Rectangle;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
import net.runelite.api.HashTable;
import net.runelite.api.Node;
import net.runelite.api.Point;
@@ -42,8 +37,6 @@ import net.runelite.api.mixins.Mixin;
import net.runelite.api.mixins.Replace;
import net.runelite.api.mixins.Shadow;
import net.runelite.api.widgets.Widget;
-import static net.runelite.api.widgets.WidgetInfo.TO_CHILD;
-import static net.runelite.api.widgets.WidgetInfo.TO_GROUP;
import net.runelite.api.widgets.WidgetItem;
import net.runelite.rs.api.RSClient;
import net.runelite.rs.api.RSModel;
@@ -52,24 +45,26 @@ import net.runelite.rs.api.RSNodeHashTable;
import net.runelite.rs.api.RSPlayerAppearance;
import net.runelite.rs.api.RSSequenceDefinition;
import net.runelite.rs.api.RSWidget;
+import java.awt.Rectangle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import static net.runelite.api.widgets.WidgetInfo.TO_CHILD;
+import static net.runelite.api.widgets.WidgetInfo.TO_GROUP;
@Mixin(RSWidget.class)
public abstract class RSWidgetMixin implements RSWidget
{
private static final int ITEM_SLOT_SIZE = 32;
-
@Shadow("client")
private static RSClient client;
-
@Inject
private static int rl$widgetLastPosChanged;
-
@Inject
private int rl$parentId;
-
@Inject
private int rl$x;
-
@Inject
private int rl$y;
@@ -295,8 +290,19 @@ public abstract class RSWidgetMixin implements RSWidget
int itemX = rl$x + ((ITEM_SLOT_SIZE + xPitch) * col);
int itemY = rl$y + ((ITEM_SLOT_SIZE + yPitch) * row);
- Rectangle bounds = new Rectangle(itemX, itemY, ITEM_SLOT_SIZE, ITEM_SLOT_SIZE);
- return new WidgetItem(itemId - 1, itemQuantity, index, bounds, this);
+ boolean isDragged = isWidgetItemDragged(index);
+ int dragOffsetX = 0;
+ int dragOffsetY = 0;
+
+ if (isDragged)
+ {
+ Point p = getWidgetItemDragOffsets();
+ dragOffsetX = p.getX();
+ dragOffsetY = p.getY();
+ }
+
+ Rectangle bounds = new Rectangle(itemX + dragOffsetX, itemY + dragOffsetY, ITEM_SLOT_SIZE, ITEM_SLOT_SIZE);
+ return new WidgetItem(itemId - 1, itemQuantity, index, bounds, this, isDragged);
}
@Inject
@@ -587,4 +593,31 @@ public abstract class RSWidgetMixin implements RSWidget
}
return rs$getModel(sequence, frame, alternate, playerComposition);
}
+
+ @Inject
+ @Override
+ public boolean isWidgetItemDragged(int index)
+ {
+ return client.getIf1DraggedWidget() == this && client.getItemPressedDuration() >= 5 &&
+ client.getIf1DraggedItemIndex() == index;
+ }
+
+ @Inject
+ public Point getWidgetItemDragOffsets()
+ {
+ int dragOffsetX = client.getMouseX() - client.getDraggedWidgetX();
+ int dragOffsetY = client.getMouseY() - client.getDraggedWidgetY();
+
+ if (dragOffsetX < 5 && dragOffsetX > -5)
+ {
+ dragOffsetX = 0;
+ }
+
+ if (dragOffsetY < 5 && dragOffsetY > -5)
+ {
+ dragOffsetY = 0;
+ }
+
+ return new Point(dragOffsetX, dragOffsetY);
+ }
}
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 9c10487a47..3d30a06166 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
@@ -1146,4 +1146,10 @@ public interface RSClient extends RSGameShell, Client
@Import("showMouseCross")
@Override
void setShowMouseCross(boolean show);
+
+ @Import("draggedWidgetX")
+ int getDraggedWidgetX(); // these should probably have if1 in their names somewhere
+
+ @Import("draggedWidgetY")
+ int getDraggedWidgetY();
}
diff --git a/runescape-client/src/main/java/Client.java b/runescape-client/src/main/java/Client.java
index 7eeccb4ce8..a1a6af5193 100644
--- a/runescape-client/src/main/java/Client.java
+++ b/runescape-client/src/main/java/Client.java
@@ -1049,12 +1049,14 @@ public final class Client extends GameShell implements Usernamed {
@ObfuscatedGetter(
intValue = 1858822219
)
- static int field863;
+ @Export("draggedWidgetX")
+ static int draggedWidgetX;
@ObfuscatedName("jd")
@ObfuscatedGetter(
intValue = 1449162079
)
- static int field738;
+ @Export("draggedWidgetY")
+ static int draggedWidgetY;
@ObfuscatedName("jy")
@ObfuscatedGetter(
intValue = -1787846911
@@ -1372,8 +1374,8 @@ public final class Client extends GameShell implements Usernamed {
field764 = 0;
field735 = 0;
dragItemSlotSource = 0;
- field863 = 0;
- field738 = 0;
+ draggedWidgetX = 0;
+ draggedWidgetY = 0;
dragItemSlotDestination = 0;
field768 = false;
itemDragDuration = 0;
@@ -3765,10 +3767,10 @@ public final class Client extends GameShell implements Usernamed {
packetWriter.addNode(var27);
}
} else if (this.shouldLeftClickOpenMenu()) {
- this.openMenu(field863, field738);
+ this.openMenu(draggedWidgetX, draggedWidgetY);
} else if (menuOptionsCount > 0) {
- var4 = field863;
- var5 = field738;
+ var4 = draggedWidgetX;
+ var5 = draggedWidgetY;
Messages.method2231(LoginType.tempMenuAction, var4, var5);
LoginType.tempMenuAction = null;
}
@@ -3776,7 +3778,7 @@ public final class Client extends GameShell implements Usernamed {
field764 = 10;
MouseHandler.MouseHandler_lastButton = 0;
ClientPreferences.dragInventoryWidget = null;
- } else if (itemDragDuration >= 5 && (MouseHandler.MouseHandler_x > field863 + 5 || MouseHandler.MouseHandler_x < field863 - 5 || MouseHandler.MouseHandler_y > field738 + 5 || MouseHandler.MouseHandler_y < field738 - 5)) {
+ } else if (itemDragDuration >= 5 && (MouseHandler.MouseHandler_x > draggedWidgetX + 5 || MouseHandler.MouseHandler_x < draggedWidgetX - 5 || MouseHandler.MouseHandler_y > draggedWidgetY + 5 || MouseHandler.MouseHandler_y < draggedWidgetY - 5)) {
field768 = true;
}
}
@@ -5795,8 +5797,8 @@ public final class Client extends GameShell implements Usernamed {
}
if (ClientPreferences.dragInventoryWidget != null && !field768 && menuOptionsCount > 0 && !this.shouldLeftClickOpenMenu()) {
- var13 = field863;
- var10 = field738;
+ var13 = draggedWidgetX;
+ var10 = draggedWidgetY;
Messages.method2231(LoginType.tempMenuAction, var13, var10);
LoginType.tempMenuAction = null;
}
@@ -5809,8 +5811,8 @@ public final class Client extends GameShell implements Usernamed {
ClientPreferences.dragInventoryWidget = Tile.getWidget(var5);
dragItemSlotSource = var4;
- field863 = MouseHandler.MouseHandler_lastPressedX;
- field738 = MouseHandler.MouseHandler_lastPressedY;
+ draggedWidgetX = MouseHandler.MouseHandler_lastPressedX;
+ draggedWidgetY = MouseHandler.MouseHandler_lastPressedY;
if (var2 >= 0) {
BuddyRankComparator.method3361(var2);
}
diff --git a/runescape-client/src/main/java/UserComparator7.java b/runescape-client/src/main/java/UserComparator7.java
index 92842c9f5d..639faa4ff2 100644
--- a/runescape-client/src/main/java/UserComparator7.java
+++ b/runescape-client/src/main/java/UserComparator7.java
@@ -400,8 +400,8 @@ public class UserComparator7 extends AbstractUserComparator {
if (var27 != null) {
if (var10 == ClientPreferences.dragInventoryWidget && var30 == Client.dragItemSlotSource) {
- var24 = MouseHandler.MouseHandler_x - Client.field863;
- var25 = MouseHandler.MouseHandler_y - Client.field738;
+ var24 = MouseHandler.MouseHandler_x - Client.draggedWidgetX;
+ var25 = MouseHandler.MouseHandler_y - Client.draggedWidgetY;
if (var24 < 5 && var24 > -5) {
var24 = 0;
}
@@ -430,7 +430,7 @@ public class UserComparator7 extends AbstractUserComparator {
}
var28.scrollY -= var29;
- Client.field738 += var29;
+ Client.draggedWidgetY += var29;
LoginPacket.invalidateWidget(var28);
}
@@ -445,7 +445,7 @@ public class UserComparator7 extends AbstractUserComparator {
}
var28.scrollY += var29;
- Client.field738 -= var29;
+ Client.draggedWidgetY -= var29;
LoginPacket.invalidateWidget(var28);
}
}