This commit is contained in:
ThatGamerBlue
2021-02-04 07:16:17 +00:00
parent 58e1150d51
commit 4023066b5d
29 changed files with 329 additions and 555 deletions

View File

@@ -24,10 +24,8 @@
*/
package net.runelite.api.events;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import net.runelite.api.MenuEntry;
import lombok.Data;
import net.runelite.api.MenuAction;
/**
* An event where a menu option has been clicked.
@@ -40,22 +38,35 @@ import net.runelite.api.MenuEntry;
* By default, when there is no action performed when left-clicking,
* it seems that this event still triggers with the "Cancel" action.
*/
@Getter
public class MenuOptionClicked extends MenuEntry
@Data
public class MenuOptionClicked
{
public MenuOptionClicked(String option, String target, int identifier, int opcode, int param0, int param1, boolean forceLeftClick)
{
super(option, target, identifier, opcode, param0, param1, forceLeftClick);
authentic = true;
}
public MenuOptionClicked(String option, String target, int identifier, int opcode, int param0, int param1, boolean forceLeftClick, boolean authentic, int mouseButton)
{
super(option, target, identifier, opcode, param0, param1, forceLeftClick);
this.authentic = authentic;
this.mouseButton = mouseButton;
}
/**
* The action parameter used in the click.
*/
private int actionParam;
/**
* The option text added to the menu.
*/
private String menuOption;
/**
* The target of the action.
*/
private String menuTarget;
/**
* The action performed.
*/
private MenuAction menuAction;
/**
* The ID of the object, actor, or item that the interaction targets.
*/
private int id;
/**
* The ID of the widget where the menu was clicked.
*
* @see net.runelite.api.widgets.WidgetID
*/
private int widgetId;
/**
* The selected item index at the time of the option click.
*/
@@ -65,11 +76,6 @@ public class MenuOptionClicked extends MenuEntry
*/
private boolean consumed;
/**
* The mouse button will be 1 if a non draggable widget was clicked,
*/
private int mouseButton;
/**
* Marks the event as having been consumed.
* <p>
@@ -81,36 +87,4 @@ public class MenuOptionClicked extends MenuEntry
{
this.consumed = true;
}
/**
* Whether or not the event is authentic.
*/
@Setter(AccessLevel.NONE)
private final boolean authentic;
public void setMenuEntry(MenuEntry e)
{
setOption(e.getOption());
setTarget(e.getTarget());
setIdentifier(e.getIdentifier());
setOpcode(e.getOpcode());
setActionParam(e.getActionParam());
setActionParam1(e.getActionParam1());
setForceLeftClick(e.isForceLeftClick());
}
public int getWidgetId()
{
return getActionParam1();
}
public String getMenuTarget()
{
return getTarget();
}
public String getMenuOption()
{
return getOption();
}
}

View File

@@ -28,11 +28,10 @@ public class SoundManager
this.runeliteConfig = runeLiteConfig;
}
public void playSound(final Sound sound)
public void play(final Sound sound)
{
new Thread(new Runnable()
{
@Override
public void run()
{

View File

@@ -1,13 +1,28 @@
/*******************************************************************************
* Copyright (c) 2019 openosrs
* Redistributions and modifications of this software are permitted as long as this notice remains in its original unmodified state at the top of this file.
* If there are any questions comments, or feedback about this software, please direct all inquiries directly to the file authors:
* ST0NEWALL#9112
* Macweese#1169 UID 159941566994186240, macweese@pm.me
* openosrs Discord: https://discord.gg/Q7wFtCe
* openosrs website: https://openosrs.com
******************************************************************************/
/*
* Copyright (c) 2019, ST0NEWALL
* Copyright (c) 2020, Macweese <Macweese#1169 159941566994186240, macweese@pm.me>
* 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 com.openosrs.client.game;
import com.google.common.collect.ImmutableMap;

View File

@@ -47,7 +47,7 @@ import net.runelite.client.ui.ColorScheme;
import net.runelite.client.ui.FontManager;
import com.openosrs.client.ui.OpenOSRSSplashScreen;
import net.runelite.client.util.ImageUtil;
import com.openosrs.client.util.LinkBrowser;
import net.runelite.client.util.LinkBrowser;
@Slf4j
public class InfoPanel extends JPanel

View File

@@ -1,83 +0,0 @@
package com.openosrs.client.util;
import java.awt.Desktop;
import java.awt.Toolkit;
import java.awt.datatransfer.StringSelection;
import java.io.File;
import java.io.IOException;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class LinkBrowser extends net.runelite.client.util.LinkBrowser
{
/**
* Tries to open the specified {@code File} with the systems default text editor. If operation fails
* an error message is displayed with the option to copy the absolute file path to clipboard.
*
* @param file the File instance of the log file
* @return did the file open successfully?
*/
public static boolean openLocalFile(final File file)
{
if (file == null || !file.exists())
{
return false;
}
if (attemptOpenLocalFile(file))
{
log.debug("Opened log file through Desktop#edit to {}", file);
return true;
}
showMessageBox("Unable to open log file. Press 'OK' and the file path will be copied to your clipboard", file.getAbsolutePath());
return false;
}
private static boolean attemptOpenLocalFile(final File file)
{
if (!Desktop.isDesktopSupported())
{
return false;
}
final Desktop desktop = Desktop.getDesktop();
if (!desktop.isSupported(Desktop.Action.OPEN))
{
return false;
}
try
{
desktop.open(file);
return true;
}
catch (IOException ex)
{
log.warn("Failed to open Desktop#edit {}", file, ex);
return false;
}
}
/**
* Open swing message box with specified message and copy data to clipboard
* @param message message to show
*/
private static void showMessageBox(final String message, final String data)
{
SwingUtilities.invokeLater(() ->
{
final int result = JOptionPane.showConfirmDialog(null, message, "Message",
JOptionPane.OK_CANCEL_OPTION);
if (result == JOptionPane.OK_OPTION)
{
final StringSelection stringSelection = new StringSelection(data);
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(stringSelection, null);
}
});
}
}

View File

@@ -1,202 +0,0 @@
package com.openosrs.client.util;
import java.awt.Polygon;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import net.runelite.api.Client;
import net.runelite.api.Player;
import net.runelite.api.WorldType;
import net.runelite.api.coords.WorldPoint;
public class MiscUtils
{
private static final int[] abovePointsX = {2944, 3392, 3392, 2944};
private static final int[] abovePointsY = {3523, 3523, 3971, 3971};
private static final int[] belowPointsX = {2944, 2944, 3264, 3264};
private static final int[] belowPointsY = {9918, 10360, 10360, 9918};
private static final Polygon abovePoly = new Polygon(abovePointsX, abovePointsY, abovePointsX.length);
private static final Polygon belowPoly = new Polygon(belowPointsX, belowPointsY, belowPointsX.length);
private static final ChronoUnit[] ORDERED_CHRONOS = new ChronoUnit[]
{
ChronoUnit.YEARS,
ChronoUnit.MONTHS,
ChronoUnit.WEEKS,
ChronoUnit.DAYS,
ChronoUnit.HOURS,
ChronoUnit.MINUTES,
ChronoUnit.SECONDS
};
//test replacement so private for now
private static boolean inWildy(WorldPoint point)
{
if (point == null)
{
return false;
}
return abovePoly.contains(point.getX(), point.getY()) || belowPoly.contains(point.getX(), point.getY());
}
public static int getWildernessLevelFrom(Client client, WorldPoint point)
{
if (client == null)
{
return 0;
}
if (point == null)
{
return 0;
}
int x = point.getX();
if (point.getPlane() == 0 && (x < 2940 || x > 3391))
{
return 0;
}
int y = point.getY();
//v underground //v above ground
int wildernessLevel = clamp(y > 6400 ? ((y - 9920) / 8) + 1 : ((y - 3520) / 8) + 1, 0, 56);
if (point.getPlane() > 0 && y < 9920)
{
wildernessLevel = 0;
}
if (client.getWorldType().stream().anyMatch(worldType -> worldType == WorldType.PVP || worldType == WorldType.HIGH_RISK))
{
wildernessLevel += 15;
}
return Math.max(0, wildernessLevel);
}
public static int clamp(int val, int min, int max)
{
return Math.max(min, Math.min(max, val));
}
public static float clamp(float val, float min, float max)
{
return Math.max(min, Math.min(max, val));
}
public static boolean inWilderness(Client client)
{
Player localPlayer = client.getLocalPlayer();
if (localPlayer == null)
{
return false;
}
return inWildy(localPlayer.getWorldLocation());
//return getWildernessLevelFrom(client, localPlayer.getWorldLocation()) > 0;
}
public static String formatTimeAgo(Duration dur)
{
long dA = 0, dB = 0, rm;
ChronoUnit cA = null, cB = null;
for (int i = 0; i < ORDERED_CHRONOS.length; i++)
{
cA = ORDERED_CHRONOS[i];
dA = dur.getSeconds() / cA.getDuration().getSeconds();
rm = dur.getSeconds() % cA.getDuration().getSeconds();
if (dA <= 0)
{
cA = null;
continue;
}
if (i + 1 < ORDERED_CHRONOS.length)
{
cB = ORDERED_CHRONOS[i + 1];
dB = rm / cB.getDuration().getSeconds();
if (dB <= 0)
{
cB = null;
}
}
break;
}
if (cA == null)
{
return "just now.";
}
String str = formatUnit(cA, dA);
if (cB != null)
{
str += " and " + formatUnit(cB, dB);
}
return str + " ago.";
}
private static String formatUnit(ChronoUnit chrono, long val)
{
boolean multiple = val != 1;
String str;
if (multiple)
{
str = val + " ";
}
else
{
str = "a" + (chrono == ChronoUnit.HOURS ? "n " : " ");
}
str += chrono.name().toLowerCase();
if (!multiple)
{
if (str.charAt(str.length() - 1) == 's')
{
str = str.substring(0, str.length() - 1);
}
}
else if (str.charAt(str.length() - 1) != 's')
{
str += "s";
}
return str;
}
/**
* Mostly stolen from {@link java.net.URLStreamHandler#toExternalForm(URL)}
*
* @param url URL to encode
* @return URL, with path, query and ref encoded
*/
public static String urlToStringEncoded(URL url)
{
String s;
String path = url.getPath() != null ? Stream.of(url.getPath().split("/"))
.map(s2 -> URLEncoder.encode(s2, StandardCharsets.UTF_8)).collect(Collectors.joining("/")) : "";
return url.getProtocol()
+ ':'
+ (((s = url.getAuthority()) != null && s.length() > 0) ? "//" + s : "")
+ (path)
+ (((s = url.getQuery()) != null) ? '?' + urlEncode(s) : "")
+ (((s = url.getRef()) != null) ? '#' + urlEncode(s) : "");
}
private static String urlEncode(String s)
{
return URLEncoder.encode(s, StandardCharsets.UTF_8);
}
}

View File

@@ -1,135 +0,0 @@
/*
* Copyright (c) 2019. PKLite - All Rights Reserved
* Unauthorized modification, distribution, or possession of this source file, via any medium is strictly prohibited.
* Proprietary and confidential. Refer to PKLite License file for more information on
* full terms of this copyright and to determine what constitutes authorized use.
* Written by PKLite(ST0NEWALL, others) <stonewall@thots.cc.usa>, 2019
*
*/
package com.openosrs.client.util;
import net.runelite.api.Client;
import net.runelite.api.InventoryID;
import net.runelite.api.Item;
import net.runelite.api.ItemComposition;
import net.runelite.api.Player;
import net.runelite.api.Varbits;
import net.runelite.api.WorldType;
import net.runelite.api.coords.WorldPoint;
import net.runelite.api.geometry.Cuboid;
import net.runelite.client.game.ItemManager;
import net.runelite.client.util.QuantityFormatter;
import org.apache.commons.lang3.ArrayUtils;
import java.awt.Polygon;
import java.util.Comparator;
import java.util.Objects;
import java.util.TreeMap;
public class PvPUtil
{
private static final Polygon NOT_WILDERNESS_BLACK_KNIGHTS = new Polygon( // this is black knights castle
new int[]{2994, 2995, 2996, 2996, 2994, 2994, 2997, 2998, 2998, 2999, 3000, 3001, 3002, 3003, 3004, 3005, 3005,
3005, 3019, 3020, 3022, 3023, 3024, 3025, 3026, 3026, 3027, 3027, 3028, 3028, 3029, 3029, 3030, 3030, 3031,
3031, 3032, 3033, 3034, 3035, 3036, 3037, 3037},
new int[]{3525, 3526, 3527, 3529, 3529, 3534, 3534, 3535, 3536, 3537, 3538, 3539, 3540, 3541, 3542, 3543, 3544,
3545, 3545, 3546, 3546, 3545, 3544, 3543, 3543, 3542, 3541, 3540, 3539, 3537, 3536, 3535, 3534, 3533, 3532,
3531, 3530, 3529, 3528, 3527, 3526, 3526, 3525},
43
);
private static final Cuboid MAIN_WILDERNESS_CUBOID = new Cuboid(2944, 3525, 0, 3391, 4351, 3);
private static final Cuboid GOD_WARS_WILDERNESS_CUBOID = new Cuboid(3008, 10112, 0, 3071, 10175, 3);
private static final Cuboid WILDERNESS_UNDERGROUND_CUBOID = new Cuboid(2944, 9920, 0, 3391, 10879, 3);
/**
* Gets the wilderness level based on a world point
* Java reimplementation of clientscript 384 [proc,wilderness_level]
*
* @param point the point in the world to get the wilderness level for
* @return the int representing the wilderness level
*/
public static int getWildernessLevelFrom(WorldPoint point)
{
if (MAIN_WILDERNESS_CUBOID.contains(point))
{
if (NOT_WILDERNESS_BLACK_KNIGHTS.contains(point.getX(), point.getY()))
{
return 0;
}
return ((point.getY() - 3520) / 8) + 1; // calc(((coordz(coord) - (55 * 64)) / 8) + 1)
}
else if (GOD_WARS_WILDERNESS_CUBOID.contains(point))
{
return ((point.getY() - 9920) / 8) - 1; // calc(((coordz(coord) - (155 * 64)) / 8) - 1)
}
else if (WILDERNESS_UNDERGROUND_CUBOID.contains(point))
{
return ((point.getY() - 9920) / 8) + 1; // calc(((coordz(coord) - (155 * 64)) / 8) + 1)
}
return 0;
}
/**
* Determines if another player is attackable based off of wilderness level and combat levels
*
* @param client The client of the local player
* @param player the player to determine attackability
* @return returns true if the player is attackable, false otherwise
*/
public static boolean isAttackable(Client client, Player player)
{
int wildernessLevel = 0;
if (WorldType.isDeadmanWorld(client.getWorldType()))
{
return true;
}
if (WorldType.isPvpWorld(client.getWorldType()))
{
wildernessLevel += 15;
}
if (client.getVar(Varbits.IN_WILDERNESS) == 1)
{
wildernessLevel += getWildernessLevelFrom(client.getLocalPlayer().getWorldLocation());
}
return wildernessLevel != 0 && Math.abs(client.getLocalPlayer().getCombatLevel() - player.getCombatLevel()) <= wildernessLevel;
}
public static int calculateRisk(Client client, ItemManager itemManager)
{
if (client.getItemContainer(InventoryID.EQUIPMENT) == null)
{
return 0;
}
if (client.getItemContainer(InventoryID.INVENTORY).getItems() == null)
{
return 0;
}
Item[] items = ArrayUtils.addAll(Objects.requireNonNull(client.getItemContainer(InventoryID.EQUIPMENT)).getItems(),
Objects.requireNonNull(client.getItemContainer(InventoryID.INVENTORY)).getItems());
TreeMap<Integer, Item> priceMap = new TreeMap<>(Comparator.comparingInt(Integer::intValue));
int wealth = 0;
for (Item i : items)
{
int value = (itemManager.getItemPrice(i.getId()) * i.getQuantity());
final ItemComposition itemComposition = itemManager.getItemComposition(i.getId());
if (!itemComposition.isTradeable() && value == 0)
{
value = itemComposition.getPrice() * i.getQuantity();
priceMap.put(value, i);
}
else
{
value = itemManager.getItemPrice(i.getId()) * i.getQuantity();
if (i.getId() > 0 && value > 0)
{
priceMap.put(value, i);
}
}
wealth += value;
}
return Integer.parseInt(QuantityFormatter.quantityToRSDecimalStack(priceMap.keySet().stream().mapToInt(Integer::intValue).sum()));
}
}

View File

@@ -1,19 +0,0 @@
package com.openosrs.client.util;
import java.awt.EventQueue;
import java.lang.reflect.InvocationTargetException;
public class SwingUtil extends net.runelite.client.util.SwingUtil
{
public static void syncExec(final Runnable r) throws InvocationTargetException, InterruptedException
{
if (EventQueue.isDispatchThread())
{
r.run();
}
else
{
EventQueue.invokeAndWait(r);
}
}
}

View File

@@ -1,4 +1,29 @@
package com.openosrs.client.util;
/*
* Copyright (c) 2021, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.client;
import java.util.Collection;
import java.util.List;

View File

@@ -30,7 +30,6 @@ import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.inject.name.Names;
import com.openosrs.client.config.OpenOSRSConfig;
import com.openosrs.client.util.NonScheduledExecutorServiceExceptionLogger;
import java.applet.Applet;
import java.io.File;
import java.util.Properties;

View File

@@ -40,11 +40,11 @@ import com.openosrs.client.events.ExternalPluginChanged;
import com.openosrs.client.events.ExternalRepositoryChanged;
import com.openosrs.client.ui.OpenOSRSSplashScreen;
import com.openosrs.client.util.Groups;
import com.openosrs.client.util.MiscUtils;
import com.openosrs.client.util.SwingUtil;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
@@ -76,6 +76,7 @@ import net.runelite.client.config.RuneLiteConfig;
import net.runelite.client.eventbus.EventBus;
import net.runelite.client.events.ConfigChanged;
import net.runelite.client.ui.ClientUI;
import net.runelite.client.util.SwingUtil;
import org.jgroups.Message;
import org.pf4j.DefaultPluginManager;
import org.pf4j.DependencyResolver;
@@ -343,7 +344,7 @@ public class OPRSExternalPluginManager
{
config.append(repository.getId());
config.append("|");
config.append(MiscUtils.urlToStringEncoded(repository.getUrl()));
config.append(urlToStringEncoded(repository.getUrl()));
config.append(";");
}
config.deleteCharAt(config.lastIndexOf(";"));
@@ -1066,4 +1067,27 @@ public class OPRSExternalPluginManager
}
}
/**
* Mostly stolen from {@link java.net.URLStreamHandler#toExternalForm(URL)}
*
* @param url URL to encode
* @return URL, with path, query and ref encoded
*/
private static String urlToStringEncoded(URL url)
{
String s;
String path = url.getPath() != null ? Stream.of(url.getPath().split("/"))
.map(s2 -> URLEncoder.encode(s2, StandardCharsets.UTF_8)).collect(Collectors.joining("/")) : "";
return url.getProtocol()
+ ':'
+ (((s = url.getAuthority()) != null && s.length() > 0) ? "//" + s : "")
+ (path)
+ (((s = url.getQuery()) != null) ? '?' + urlEncode(s) : "")
+ (((s = url.getRef()) != null) ? '#' + urlEncode(s) : "");
}
private static String urlEncode(String s)
{
return URLEncoder.encode(s, StandardCharsets.UTF_8);
}
}

View File

@@ -87,7 +87,6 @@ public class PluginManager
* Base package where the core plugins are
*/
private static final String PLUGIN_PACKAGE = "net.runelite.client.plugins";
private static final String OPENOSRS_PACKAGE = "com.openosrs.client.plugins";
private final boolean developerMode;
private final boolean safeMode;
@@ -291,10 +290,6 @@ public class PluginManager
.map(ClassInfo::load)
.collect(Collectors.toList());
plugins.addAll(classPath.getTopLevelClassesRecursive(OPENOSRS_PACKAGE).stream()
.map(ClassInfo::load)
.collect(Collectors.toList()));
loadPlugins(plugins, (loaded, total) ->
SplashScreen.stage(.60, .70, null, "Loading Plugins", loaded, total, false));
}

View File

@@ -24,17 +24,16 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.openosrs.client.plugins.openosrs;
package net.runelite.client.plugins.openosrs;
import ch.qos.logback.classic.Logger;
import com.openosrs.client.config.OpenOSRSConfig;
import com.openosrs.client.plugins.openosrs.externals.ExternalPluginManagerPanel;
import net.runelite.client.plugins.openosrs.externals.ExternalPluginManagerPanel;
import java.awt.image.BufferedImage;
import javax.inject.Inject;
import javax.inject.Singleton;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client;
import net.runelite.client.callback.ClientThread;
import net.runelite.client.config.Keybind;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.events.ConfigChanged;
@@ -65,9 +64,6 @@ public class OpenOSRSPlugin extends Plugin
@Inject
private Client client;
@Inject
private ClientThread clientThread;
@Inject
private ClientToolbar clientToolbar;

View File

@@ -1,4 +1,4 @@
package com.openosrs.client.plugins.openosrs.externals;
package net.runelite.client.plugins.openosrs.externals;
import java.awt.BorderLayout;
import java.awt.Color;

View File

@@ -1,4 +1,4 @@
package com.openosrs.client.plugins.openosrs.externals;
package net.runelite.client.plugins.openosrs.externals;
import net.runelite.client.plugins.OPRSExternalPluginManager;
import java.awt.BorderLayout;

View File

@@ -1,4 +1,4 @@
package com.openosrs.client.plugins.openosrs.externals;
package net.runelite.client.plugins.openosrs.externals;
import net.runelite.client.plugins.OPRSExternalPluginManager;
import com.google.gson.JsonSyntaxException;

View File

@@ -1,4 +1,4 @@
package com.openosrs.client.plugins.openosrs.externals;
package net.runelite.client.plugins.openosrs.externals;
import net.runelite.client.plugins.OPRSExternalPluginManager;
import com.openosrs.client.ui.JMultilineLabel;

View File

@@ -1,4 +1,4 @@
package com.openosrs.client.plugins.openosrs.externals;
package net.runelite.client.plugins.openosrs.externals;
import net.runelite.client.plugins.OPRSExternalPluginManager;
import com.openosrs.client.events.ExternalRepositoryChanged;

View File

@@ -577,4 +577,134 @@ public class ImageUtil
}
return image;
}
/**
* Draw fg centered on top of bg
*/
public static SpritePixels mergeSprites(final Client client, final SpritePixels bg, final SpritePixels fg)
{
assert fg.getHeight() <= bg.getHeight() && fg.getWidth() <= bg.getWidth() : "Background has to be larger than foreground";
final int[] canvas = Arrays.copyOf(bg.getPixels(), bg.getWidth() * bg.getHeight());
final SpritePixels result = client.createSpritePixels(canvas, bg.getWidth(), bg.getHeight());
final int bgWid = bg.getWidth();
final int fgHgt = fg.getHeight();
final int fgWid = fg.getWidth();
final int xOffset = (bgWid - fgWid) / 2;
final int yOffset = (bg.getHeight() - fgHgt) / 2;
final int[] fgPixels = fg.getPixels();
for (int y1 = yOffset, y2 = 0; y2 < fgHgt; y1++, y2++)
{
int i1 = y1 * bgWid + xOffset;
int i2 = y2 * fgWid;
for (int x = 0; x < fgWid; x++, i1++, i2++)
{
if (fgPixels[i2] > 0)
{
canvas[i1] = fgPixels[i2];
}
}
}
return result;
}
/**
* Resize Sprite sprite to given width (newW) and height (newH)
*/
public static SpritePixels resizeSprite(final Client client, final SpritePixels sprite, int newW, int newH)
{
assert newW > 0 && newH > 0;
final int oldW = sprite.getWidth();
final int oldH = sprite.getHeight();
if (oldW == newW && oldH == newH)
{
return sprite;
}
final int[] canvas = new int[newW * newH];
final int[] pixels = sprite.getPixels();
final SpritePixels result = client.createSpritePixels(canvas, newW, newH);
int pixelX = 0;
int pixelY = 0;
final int oldMaxW = sprite.getMaxWidth();
final int oldMaxH = sprite.getMaxHeight();
final int pixelW = (oldMaxW << 16) / newW;
final int pixelH = (oldMaxH << 16) / newH;
int xOffset = 0;
int yOffset = 0;
int canvasIdx;
if (sprite.getOffsetX() > 0)
{
canvasIdx = (pixelW + (sprite.getOffsetX() << 16) - 1) / pixelW;
xOffset += canvasIdx;
pixelX += canvasIdx * pixelW - (sprite.getOffsetX() << 16);
}
if (sprite.getOffsetY() > 0)
{
canvasIdx = (pixelH + (sprite.getOffsetY() << 16) - 1) / pixelH;
yOffset += canvasIdx;
pixelY += canvasIdx * pixelH - (sprite.getOffsetY() << 16);
}
if (oldW < oldMaxW)
{
newW = (pixelW + ((oldW << 16) - pixelX) - 1) / pixelW;
}
if (oldH < oldMaxH)
{
newH = (pixelH + ((oldH << 16) - pixelY) - 1) / pixelH;
}
canvasIdx = xOffset + yOffset * newW;
int canvasOffset = 0;
if (yOffset + newH > newH)
{
newH -= yOffset + newH - newH;
}
int tmp;
if (yOffset < 0)
{
tmp = -yOffset;
newH -= tmp;
canvasIdx += tmp * newW;
pixelY += pixelH * tmp;
}
if (newW + xOffset > newW)
{
tmp = newW + xOffset - newW;
newW -= tmp;
canvasOffset += tmp;
}
if (xOffset < 0)
{
tmp = -xOffset;
newW -= tmp;
canvasIdx += tmp;
pixelX += pixelW * tmp;
canvasOffset += tmp;
}
client.scaleSprite(canvas, pixels, 0, pixelX, pixelY, canvasIdx, canvasOffset, newW, newH, pixelW, pixelH, oldW);
return result;
}
}

View File

@@ -207,4 +207,54 @@ public class LinkBrowser
}
});
}
/**
* Tries to open the specified {@code File} with the systems default text editor. If operation fails
* an error message is displayed with the option to copy the absolute file path to clipboard.
*
* @param file the File instance of the log file
* @return did the file open successfully?
*/
public static boolean openLocalFile(final File file)
{
if (file == null || !file.exists())
{
return false;
}
if (attemptOpenLocalFile(file))
{
log.debug("Opened log file through Desktop#open to {}", file);
return true;
}
showMessageBox("Unable to open file. Press 'OK' and the file path will be copied to your clipboard", file.getAbsolutePath());
return false;
}
private static boolean attemptOpenLocalFile(final File file)
{
if (!Desktop.isDesktopSupported())
{
return false;
}
final Desktop desktop = Desktop.getDesktop();
if (!desktop.isSupported(Desktop.Action.OPEN))
{
return false;
}
try
{
desktop.open(file);
return true;
}
catch (IOException ex)
{
log.warn("Failed to open Desktop#open {}", file, ex);
return false;
}
}
}

View File

@@ -1,5 +1,6 @@
/*
* Copyright (c) 2021, ThatGamerBlue <thatgamerblue@gmail.com>
* Copyright (c) 2019, PKLite
* Copyright (c) 2020, ThatGamerBlue <thatgamerblue@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@@ -40,6 +40,7 @@ import java.awt.TrayIcon;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.lang.reflect.InvocationTargetException;
import java.util.Enumeration;
import java.util.function.BiConsumer;
import javax.annotation.Nonnull;
@@ -302,4 +303,19 @@ public class SwingUtil
l.enter();
}
}
/**
* Executes a runnable on the EDT, blocking until it finishes.
*/
public static void syncExec(final Runnable r) throws InvocationTargetException, InterruptedException
{
if (EventQueue.isDispatchThread())
{
r.run();
}
else
{
EventQueue.invokeAndWait(r);
}
}
}

View File

@@ -1388,13 +1388,6 @@ 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)
{
boolean authentic = true;
if (target != null && target.startsWith("!AUTHENTIC"))
{
authentic = false;
target = target.substring(10);
}
/* Along the way, the RuneScape client may change a menuAction by incrementing it with 2000.
* I have no idea why, but it does. Their code contains the same conditional statement.
*/
@@ -1403,17 +1396,13 @@ public abstract class RSClientMixin implements RSClient
opcode -= 2000;
}
final MenuOptionClicked menuOptionClicked = new MenuOptionClicked(
option,
target,
id,
opcode,
param0,
param1,
false,
authentic,
client.getMouseCurrentButton()
);
final MenuOptionClicked menuOptionClicked = new MenuOptionClicked();
menuOptionClicked.setActionParam(param0);
menuOptionClicked.setMenuOption(option);
menuOptionClicked.setMenuTarget(target);
menuOptionClicked.setMenuAction(MenuAction.of(opcode));
menuOptionClicked.setId(id);
menuOptionClicked.setWidgetId(param1);
client.getCallbacks().post(menuOptionClicked);
@@ -1425,15 +1414,15 @@ public abstract class RSClientMixin implements RSClient
if (printMenuActions)
{
client.getLogger().info(
"|MenuAction|: MenuOption={} MenuTarget={} Id={} Opcode={} Param0={} Param1={} CanvasX={} CanvasY={} Authentic={}",
menuOptionClicked.getOption(), menuOptionClicked.getTarget(), menuOptionClicked.getIdentifier(),
menuOptionClicked.getOpcode(), menuOptionClicked.getActionParam(), menuOptionClicked.getActionParam1(),
canvasX, canvasY, authentic
"|MenuAction|: MenuOption={} MenuTarget={} Id={} Opcode={} Param0={} Param1={} CanvasX={} CanvasY={}",
menuOptionClicked.getMenuOption(), menuOptionClicked.getMenuTarget(), menuOptionClicked.getId(),
menuOptionClicked.getMenuAction(), menuOptionClicked.getActionParam(), menuOptionClicked.getWidgetId(),
canvasX, canvasY
);
}
copy$menuAction(menuOptionClicked.getActionParam(), menuOptionClicked.getActionParam1(), menuOptionClicked.getOpcode(),
menuOptionClicked.getIdentifier(), menuOptionClicked.getOption(), menuOptionClicked.getTarget(), canvasX, canvasY);
copy$menuAction(menuOptionClicked.getActionParam(), menuOptionClicked.getWidgetId(), menuOptionClicked.getMenuAction().getId(),
menuOptionClicked.getId(), menuOptionClicked.getMenuOption(), menuOptionClicked.getMenuTarget(), canvasX, canvasY);
}
@Override
@@ -1442,7 +1431,7 @@ public abstract class RSClientMixin implements RSClient
{
assert isClientThread();
client.sendMenuAction(param0, param1, opcode, identifier, option, "!AUTHENTIC" + target, 658, 384);
client.sendMenuAction(param0, param1, opcode, identifier, option, target, 658, 384);
}
@FieldHook("Login_username")