Merge remote-tracking branch 'runelite/master'

This commit is contained in:
Owain van Brakel
2019-12-17 10:21:02 +01:00
22 changed files with 509 additions and 87 deletions

View File

@@ -23,13 +23,11 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
const val kotlinVersion = "1.3.50"
object ProjectVersions {
const val launcherVersion = "2.0.4"
const val rlVersion = "1.5.44-SNAPSHOT"
const val rlVersion = "1.5.43"
const val openosrsVersion = "2.1.18-SNAPSHOT"
const val openosrsVersion = "2.1.18"
const val rsversion = 187
const val cacheversion = 165
@@ -64,13 +62,8 @@ object Libraries {
const val guice = "4.2.2"
const val h2 = "1.4.200"
const val hamcrest = "2.2"
const val httpcore = "4.4.12"
const val httpmime = "4.5.10"
const val javassist = "3.26.0-GA"
const val javax = "1.3.2"
const val javaxInject = "1"
const val jbsdiff = "1.0"
const val jclCore = "2.8"
const val jedis = "3.1.0"
const val jna = "5.5.0"
const val jogamp = "2.3.2"
@@ -114,7 +107,6 @@ object Libraries {
const val apacheCommonsText = "org.apache.commons:commons-text:${Versions.apacheCommonsText}"
const val asmAll = "org.ow2.asm:asm:${Versions.asm}"
const val asmUtil = "org.ow2.asm:asm-util:${Versions.asm}"
const val asmTree = "org.ow2.asm:asm-tree:${Versions.asm}"
const val commonsCli = "commons-cli:commons-cli:${Versions.commonsCli}"
const val discord = "net.runelite:discord:${Versions.discord}"
const val fernflower = "net.runelite:fernflower:${Versions.fernflower}"
@@ -126,13 +118,8 @@ object Libraries {
const val guiceTestlib = "com.google.inject.extensions:guice-testlib:${Versions.guice}"
const val h2 = "com.h2database:h2:${Versions.h2}"
const val hamcrest = "org.hamcrest:hamcrest-library:${Versions.hamcrest}"
const val httpcore = "org.apache.httpcomponents:httpcore:${Versions.httpcore}"
const val httpmime = "org.apache.httpcomponents:httpmime:${Versions.httpmime}"
const val javassist = "org.javassist:javassist:${Versions.javassist}"
const val javax = "javax.annotation:javax.annotation-api:${Versions.javax}"
const val javaxInject = "javax.inject:javax.inject:${Versions.javaxInject}"
const val jbsdiff = "io.sigpipe:jbsdiff:${Versions.jbsdiff}"
const val jclCore = "org.xeustechnologies:jcl-core:${Versions.jclCore}"
const val jedis = "redis.clients:jedis:${Versions.jedis}"
const val jna = "net.java.dev.jna:jna:${Versions.jna}"
const val jnaPlatform = "net.java.dev.jna:jna-platform:${Versions.jna}"

View File

@@ -65,6 +65,49 @@ public class HiscoreResult
private Skill clueScrollElite;
private Skill clueScrollMaster;
private Skill lastManStanding;
private Skill abyssalSire;
private Skill alchemicalHydra;
private Skill barrowsChests;
private Skill bryophyta;
private Skill callisto;
private Skill cerberus;
private Skill chambersOfXeric;
private Skill chambersOfXericChallengeMode;
private Skill chaosElemental;
private Skill chaosFanatic;
private Skill commanderZilyana;
private Skill corporealBeast;
private Skill crazyArchaeologist;
private Skill dagannothPrime;
private Skill dagannothRex;
private Skill dagannothSupreme;
private Skill derangedArchaeologist;
private Skill generalGraardor;
private Skill giantMole;
private Skill grotesqueGuardians;
private Skill hespori;
private Skill kalphiteQueen;
private Skill kingBlackDragon;
private Skill kraken;
private Skill kreearra;
private Skill krilTsutsaroth;
private Skill mimic;
private Skill obor;
private Skill sarachnis;
private Skill scorpia;
private Skill skotizo;
private Skill gauntlet;
private Skill corruptedGauntlet;
private Skill theatreOfBlood;
private Skill thermonuclearSmokeDevil;
private Skill tzKalZuk;
private Skill tzTokJad;
private Skill venenatis;
private Skill vetion;
private Skill vorkath;
private Skill wintertodt;
private Skill zalcano;
private Skill zulrah;
public Skill getSkill(HiscoreSkill skill)
{
@@ -140,8 +183,94 @@ public class HiscoreResult
return getClueScrollMaster();
case LAST_MAN_STANDING:
return getLastManStanding();
case ABYSSAL_SIRE:
return abyssalSire;
case ALCHEMICAL_HYDRA:
return alchemicalHydra;
case BARROWS_CHESTS:
return barrowsChests;
case BRYOPHYTA:
return bryophyta;
case CALLISTO:
return callisto;
case CERBERUS:
return cerberus;
case CHAMBERS_OF_XERIC:
return chambersOfXeric;
case CHAMBERS_OF_XERIC_CHALLENGE_MODE:
return chambersOfXericChallengeMode;
case CHAOS_ELEMENTAL:
return chaosElemental;
case CHAOS_FANATIC:
return chaosFanatic;
case COMMMANDER_ZILYANA:
return commanderZilyana;
case CORPOREAL_BEAST:
return corporealBeast;
case CRAZY_ARCHAEOLOGIST:
return crazyArchaeologist;
case DAGANNOTH_PRIME:
return dagannothPrime;
case DAGANNOTH_REX:
return dagannothRex;
case DAGANNOTH_SUPREME:
return dagannothSupreme;
case DERANGED_ARCHAEOLOGIST:
return derangedArchaeologist;
case GENERAL_GRAARDOR:
return generalGraardor;
case GIANT_MOLE:
return giantMole;
case GROTESQUE_GUARDIANS:
return grotesqueGuardians;
case HESPORI:
return hespori;
case KALPHITE_QUEEN:
return kalphiteQueen;
case KING_BLACK_DRAGON:
return kingBlackDragon;
case KRAKEN:
return kraken;
case KREEARRA:
return kreearra;
case KRIL_TSUTSAROTH:
return krilTsutsaroth;
case MIMIC:
return mimic;
case OBOR:
return obor;
case SARACHNIS:
return sarachnis;
case SCORPIA:
return scorpia;
case SKOTIZO:
return skotizo;
case THE_GAUNTLET:
return gauntlet;
case THE_CORRUPTED_GAUNTLET:
return corruptedGauntlet;
case THEATRE_OF_BLOOD:
return theatreOfBlood;
case THERMONUCLEAR_SMOKE_DEVIL:
return thermonuclearSmokeDevil;
case TZKAL_ZUK:
return tzKalZuk;
case TZTOK_JAD:
return tzTokJad;
case VENENATIS:
return venenatis;
case VETION:
return vetion;
case VORKATH:
return vorkath;
case WINTERTODT:
return wintertodt;
case ZALCANO:
return zalcano;
case ZULRAH:
return zulrah;
default:
throw new IllegalArgumentException("Invalid hiscore skill");
}
throw new IllegalArgumentException("Invalid hiscore item");
}
}

View File

@@ -27,7 +27,7 @@ package net.runelite.http.api.hiscore;
import java.util.ArrayList;
import java.util.List;
public class HiscoreResultBuilder
class HiscoreResultBuilder
{
private String player;
private final List<Skill> skills = new ArrayList<>();
@@ -37,7 +37,7 @@ public class HiscoreResultBuilder
this.player = player;
}
public void setNextSkill(Skill skill)
void setNextSkill(Skill skill)
{
skills.add(skill);
}
@@ -51,41 +51,89 @@ public class HiscoreResultBuilder
{
HiscoreResult hiscoreResult = new HiscoreResult();
hiscoreResult.setPlayer(player);
hiscoreResult.setOverall(skills.get(0));
hiscoreResult.setAttack(skills.get(1));
hiscoreResult.setDefence(skills.get(2));
hiscoreResult.setStrength(skills.get(3));
hiscoreResult.setHitpoints(skills.get(4));
hiscoreResult.setRanged(skills.get(5));
hiscoreResult.setPrayer(skills.get(6));
hiscoreResult.setMagic(skills.get(7));
hiscoreResult.setCooking(skills.get(8));
hiscoreResult.setWoodcutting(skills.get(9));
hiscoreResult.setFletching(skills.get(10));
hiscoreResult.setFishing(skills.get(11));
hiscoreResult.setFiremaking(skills.get(12));
hiscoreResult.setCrafting(skills.get(13));
hiscoreResult.setSmithing(skills.get(14));
hiscoreResult.setMining(skills.get(15));
hiscoreResult.setHerblore(skills.get(16));
hiscoreResult.setAgility(skills.get(17));
hiscoreResult.setThieving(skills.get(18));
hiscoreResult.setSlayer(skills.get(19));
hiscoreResult.setFarming(skills.get(20));
hiscoreResult.setRunecraft(skills.get(21));
hiscoreResult.setHunter(skills.get(22));
hiscoreResult.setConstruction(skills.get(23));
hiscoreResult.setLeaguePoints(skills.get(24));
hiscoreResult.setBountyHunterHunter(skills.get(25));
hiscoreResult.setBountyHunterRogue(skills.get(26));
hiscoreResult.setClueScrollAll(skills.get(27));
hiscoreResult.setClueScrollBeginner(skills.get(28));
hiscoreResult.setClueScrollEasy(skills.get(29));
hiscoreResult.setClueScrollMedium(skills.get(30));
hiscoreResult.setClueScrollHard(skills.get(31));
hiscoreResult.setClueScrollElite(skills.get(32));
hiscoreResult.setClueScrollMaster(skills.get(33));
hiscoreResult.setLastManStanding(skills.get(34));
int index = 0;
hiscoreResult.setOverall(skills.get(index++));
hiscoreResult.setAttack(skills.get(index++));
hiscoreResult.setDefence(skills.get(index++));
hiscoreResult.setStrength(skills.get(index++));
hiscoreResult.setHitpoints(skills.get(index++));
hiscoreResult.setRanged(skills.get(index++));
hiscoreResult.setPrayer(skills.get(index++));
hiscoreResult.setMagic(skills.get(index++));
hiscoreResult.setCooking(skills.get(index++));
hiscoreResult.setWoodcutting(skills.get(index++));
hiscoreResult.setFletching(skills.get(index++));
hiscoreResult.setFishing(skills.get(index++));
hiscoreResult.setFiremaking(skills.get(index++));
hiscoreResult.setCrafting(skills.get(index++));
hiscoreResult.setSmithing(skills.get(index++));
hiscoreResult.setMining(skills.get(index++));
hiscoreResult.setHerblore(skills.get(index++));
hiscoreResult.setAgility(skills.get(index++));
hiscoreResult.setThieving(skills.get(index++));
hiscoreResult.setSlayer(skills.get(index++));
hiscoreResult.setFarming(skills.get(index++));
hiscoreResult.setRunecraft(skills.get(index++));
hiscoreResult.setHunter(skills.get(index++));
hiscoreResult.setConstruction(skills.get(index++));
hiscoreResult.setLeaguePoints(skills.get(index++));
hiscoreResult.setBountyHunterHunter(skills.get(index++));
hiscoreResult.setBountyHunterRogue(skills.get(index++));
hiscoreResult.setClueScrollAll(skills.get(index++));
hiscoreResult.setClueScrollBeginner(skills.get(index++));
hiscoreResult.setClueScrollEasy(skills.get(index++));
hiscoreResult.setClueScrollMedium(skills.get(index++));
hiscoreResult.setClueScrollHard(skills.get(index++));
hiscoreResult.setClueScrollElite(skills.get(index++));
hiscoreResult.setClueScrollMaster(skills.get(index++));
hiscoreResult.setLastManStanding(skills.get(index++));
// seasonal doesn't have boss hiscores
if (index < skills.size())
{
hiscoreResult.setAbyssalSire(skills.get(index++));
hiscoreResult.setAlchemicalHydra(skills.get(index++));
hiscoreResult.setBarrowsChests(skills.get(index++));
hiscoreResult.setBryophyta(skills.get(index++));
// hiscoreResult.setCallisto(skills.get(index++));
// hiscoreResult.setCerberus(skills.get(index++));
hiscoreResult.setChambersOfXeric(skills.get(index++));
hiscoreResult.setChambersOfXericChallengeMode(skills.get(index++));
hiscoreResult.setChaosElemental(skills.get(index++));
hiscoreResult.setChaosFanatic(skills.get(index++));
hiscoreResult.setCommanderZilyana(skills.get(index++));
hiscoreResult.setCorporealBeast(skills.get(index++));
hiscoreResult.setCrazyArchaeologist(skills.get(index++));
hiscoreResult.setDagannothPrime(skills.get(index++));
hiscoreResult.setDagannothRex(skills.get(index++));
hiscoreResult.setDagannothSupreme(skills.get(index++));
hiscoreResult.setDerangedArchaeologist(skills.get(index++));
hiscoreResult.setGeneralGraardor(skills.get(index++));
hiscoreResult.setGiantMole(skills.get(index++));
hiscoreResult.setGrotesqueGuardians(skills.get(index++));
hiscoreResult.setHespori(skills.get(index++));
hiscoreResult.setKalphiteQueen(skills.get(index++));
hiscoreResult.setKingBlackDragon(skills.get(index++));
hiscoreResult.setKraken(skills.get(index++));
hiscoreResult.setKreearra(skills.get(index++));
hiscoreResult.setKrilTsutsaroth(skills.get(index++));
hiscoreResult.setMimic(skills.get(index++));
hiscoreResult.setObor(skills.get(index++));
hiscoreResult.setSarachnis(skills.get(index++));
hiscoreResult.setScorpia(skills.get(index++));
hiscoreResult.setSkotizo(skills.get(index++));
hiscoreResult.setGauntlet(skills.get(index++));
hiscoreResult.setCorruptedGauntlet(skills.get(index++));
hiscoreResult.setTheatreOfBlood(skills.get(index++));
hiscoreResult.setThermonuclearSmokeDevil(skills.get(index++));
hiscoreResult.setTzKalZuk(skills.get(index++));
hiscoreResult.setTzTokJad(skills.get(index++));
hiscoreResult.setVenenatis(skills.get(index++));
hiscoreResult.setVetion(skills.get(index++));
hiscoreResult.setVorkath(skills.get(index++));
hiscoreResult.setWintertodt(skills.get(index++));
hiscoreResult.setZalcano(skills.get(index++));
hiscoreResult.setZulrah(skills.get(index++));
}
return hiscoreResult;
}
}

View File

@@ -24,6 +24,11 @@
*/
package net.runelite.http.api.hiscore;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
@Getter
public enum HiscoreSkill
{
OVERALL("Overall"),
@@ -60,17 +65,50 @@ public enum HiscoreSkill
CLUE_SCROLL_HARD("Clue Scrolls (hard)"),
CLUE_SCROLL_ELITE("Clue Scrolls (elite)"),
CLUE_SCROLL_MASTER("Clue Scrolls (master)"),
LAST_MAN_STANDING("Last Man Standing");
LAST_MAN_STANDING("Last Man Standing"),
ABYSSAL_SIRE("Abyssal Sire"),
ALCHEMICAL_HYDRA("Alchemical Hydra"),
BARROWS_CHESTS("Barrows Chests"),
BRYOPHYTA("Bryophyta"),
CALLISTO("Callisto"),
CERBERUS("Cerberus"),
CHAMBERS_OF_XERIC("Chambers of Xeric"),
CHAMBERS_OF_XERIC_CHALLENGE_MODE("Chambers of Xeric: Challenge Mode"),
CHAOS_ELEMENTAL("Chaos Elemental"),
CHAOS_FANATIC("Chaos Fanatic"),
COMMMANDER_ZILYANA("Commander Zilyana"),
CORPOREAL_BEAST("Corporeal Beast"),
CRAZY_ARCHAEOLOGIST("Crazy Archaeologist"),
DAGANNOTH_PRIME("Dagannoth Prime"),
DAGANNOTH_REX("Dagannoth Rex"),
DAGANNOTH_SUPREME("Dagannoth Supreme"),
DERANGED_ARCHAEOLOGIST("Deranged Archaeologist"),
GENERAL_GRAARDOR("General Graardor"),
GIANT_MOLE("Giant Mole"),
GROTESQUE_GUARDIANS("Grotesque Guardians"),
HESPORI("Hespori"),
KALPHITE_QUEEN("Kalphite Queen"),
KING_BLACK_DRAGON("King Black Dragon"),
KRAKEN("Kraken"),
KREEARRA("Kree'Arra"),
KRIL_TSUTSAROTH("K'ril Tsutsaroth"),
MIMIC("Mimic"),
OBOR("Obor"),
SARACHNIS("Sarachnis"),
SCORPIA("Scorpia"),
SKOTIZO("Skotizo"),
THE_GAUNTLET("The Gauntlet"),
THE_CORRUPTED_GAUNTLET("The Corrupted Gauntlet"),
THEATRE_OF_BLOOD("Theatre of Blood"),
THERMONUCLEAR_SMOKE_DEVIL("Thermonuclear Smoke Devil"),
TZKAL_ZUK("TzKal-Zuk"),
TZTOK_JAD("TzTok-Jad"),
VENENATIS("Venenatis"),
VETION("Vet'ion"),
VORKATH("Vorkath"),
WINTERTODT("Wintertodt"),
ZALCANO("Zalcano"),
ZULRAH("Zulrah");
private final String name;
HiscoreSkill(String name)
{
this.name = name;
}
public String getName()
{
return name;
}
}

View File

@@ -217,5 +217,15 @@ public final class ScriptID
*/
@ScriptArguments(string = 1)
public static final int PUBLICMSG = 13337;
/**
* Attempts to kick the specified player from the Clan Chat
* <ul>
* <li>String Players in-game name</li>
* </ul>
*/
@ScriptArguments(string = 1)
public static final int CLAN_SEND_KICK = 215;
}

View File

@@ -466,7 +466,7 @@ public enum WidgetInfo
FISHING_TRAWLER_TIMER(WidgetID.FISHING_TRAWLER_GROUP_ID, 14),
TITHE_FARM(WidgetID.TITHE_FARM_GROUP_ID, 1),
TITHE_FARM(WidgetID.TITHE_FARM_GROUP_ID, 3),
BARROWS_INFO(WidgetID.BARROWS_GROUP_ID, 0),
BARROWS_BROTHERS(WidgetID.BARROWS_GROUP_ID, WidgetID.Barrows.BARROWS_BROTHERS),

View File

@@ -32,6 +32,9 @@ import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
@@ -42,6 +45,13 @@ import java.util.List;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javax.inject.Singleton;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.ChatMessageType;
import net.runelite.api.Client;
@@ -60,6 +70,23 @@ import net.runelite.client.util.OSType;
@Slf4j
public class Notifier
{
@Getter
@RequiredArgsConstructor
public enum NativeCustomOff
{
NATIVE("Native"),
CUSTOM("Custom"),
OFF("Off");
private final String name;
@Override
public String toString()
{
return name;
}
}
// Default timeout of notification in milliseconds
private static final int DEFAULT_TIMEOUT = 10000;
private static final String DOUBLE_QUOTE = "\"";
@@ -127,9 +154,13 @@ public class Notifier
sendNotification(appName, message, type);
}
if (runeLiteConfig.enableNotificationSound())
switch (runeLiteConfig.notificationSound())
{
Toolkit.getDefaultToolkit().beep();
case NATIVE:
Toolkit.getDefaultToolkit().beep();
break;
case CUSTOM:
executorService.submit(this::playCustomSound);
}
if (runeLiteConfig.enableGameMessageNotification() && client.getGameState() == GameState.LOGGED_IN)
@@ -366,4 +397,48 @@ public class Notifier
return "normal";
}
}
private void playCustomSound()
{
Clip clip = null;
// Try to load the user sound from ~/.runelite/notification.wav
File file = new File(RuneLite.RUNELITE_DIR, "notification.wav");
if (file.exists())
{
try
{
InputStream fileStream = new BufferedInputStream(new FileInputStream(file));
try (AudioInputStream sound = AudioSystem.getAudioInputStream(fileStream))
{
clip = AudioSystem.getClip();
clip.open(sound);
}
}
catch (UnsupportedAudioFileException | IOException | LineUnavailableException e)
{
clip = null;
log.warn("Unable to play notification sound", e);
}
}
if (clip == null)
{
// Otherwise load from the classpath
InputStream fileStream = new BufferedInputStream(Notifier.class.getResourceAsStream("notification.wav"));
try (AudioInputStream sound = AudioSystem.getAudioInputStream(fileStream))
{
clip = AudioSystem.getClip();
clip.open(sound);
}
catch (UnsupportedAudioFileException | IOException | LineUnavailableException e)
{
log.warn("Unable to play builtin notification sound", e);
Toolkit.getDefaultToolkit().beep();
return;
}
}
clip.start();
}
}

View File

@@ -26,6 +26,7 @@ package net.runelite.client.config;
import java.awt.Dimension;
import net.runelite.api.Constants;
import net.runelite.client.Notifier;
import net.runelite.client.ui.ContainableFrame;
@ConfigGroup("runelite")
@@ -213,14 +214,14 @@ public interface RuneLiteConfig extends Config
@ConfigItem(
keyName = "notificationSound",
name = "Enable sound on notifications",
name = "Notification sound",
description = "Enables the playing of a beep sound when notifications are displayed",
position = 16,
titleSection = "notificationsTitle"
)
default boolean enableNotificationSound()
default Notifier.NativeCustomOff notificationSound()
{
return true;
return Notifier.NativeCustomOff.NATIVE;
}
@ConfigItem(

View File

@@ -148,4 +148,15 @@ public interface ClanChatConfig extends Config
{
return "";
}
@ConfigItem(
keyName = "confirmKicks",
name = "Confirm Kicks",
description = "Shows a chat prompt to confirm kicks",
position = 10
)
default boolean confirmKicks()
{
return false;
}
}

View File

@@ -28,6 +28,7 @@ package net.runelite.client.plugins.clanchat;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.Runnables;
import com.google.inject.Provides;
import java.awt.Color;
import java.awt.image.BufferedImage;
@@ -74,6 +75,7 @@ import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.events.ConfigChanged;
import net.runelite.client.game.ClanManager;
import net.runelite.client.game.SpriteManager;
import net.runelite.client.game.chatbox.ChatboxPanelManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import static net.runelite.client.ui.JagexColors.CHAT_CLAN_NAME_OPAQUE_BACKGROUND;
@@ -120,6 +122,9 @@ public class ClanChatPlugin extends Plugin
@Inject
private ClientThread clientThread;
@Inject
private ChatboxPanelManager chatboxPanelManager;
private List<String> chats = new ArrayList<>();
private ClanChatIndicator clanMemberCounter;
private int clanJoinedTick;
@@ -134,6 +139,8 @@ public class ClanChatPlugin extends Plugin
private boolean clanTabChat;
private String clanname;
private boolean kickConfirmed = false;
@SuppressWarnings("unchecked")
public static CopyOnWriteArrayList<Player> getClanMembers()
{
@@ -521,14 +528,37 @@ public class ClanChatPlugin extends Plugin
@Subscribe
private void onScriptCallbackEvent(ScriptCallbackEvent scriptCallbackEvent)
{
if (!scriptCallbackEvent.getEventName().equalsIgnoreCase("clanchatInput"))
switch (scriptCallbackEvent.getEventName())
{
return;
}
case "clanchatInput":
{
final int[] intStack = client.getIntStack();
final int size = client.getIntStackSize();
intStack[size - 1] = config.clanTabChat() ? 1 : 0;
break;
}
case "confirmClanKick":
{
if (!config.confirmKicks() || kickConfirmed)
{
break;
}
final int[] intStack = client.getIntStack();
final int size = client.getIntStackSize();
intStack[size - 1] = this.clanTabChat ? 1 : 0;
// Set a flag so the script doesn't instantly kick them
final int[] intStack = client.getIntStack();
final int size = client.getIntStackSize();
intStack[size - 1] = 1;
// Get name of player we are trying to kick
final String[] stringStack = client.getStringStack();
final int stringSize = client.getStringStackSize();
final String kickPlayerName = stringStack[stringSize - 1];
// Show a chatbox panel confirming the kick
clientThread.invokeLater(() -> confirmKickPlayer(kickPlayerName));
break;
}
}
}
int getClanAmount()
@@ -642,6 +672,21 @@ public class ClanChatPlugin extends Plugin
clanMemberCounter = null;
}
private void confirmKickPlayer(final String kickPlayerName)
{
chatboxPanelManager.openTextMenuInput("Attempting to kick: " + kickPlayerName)
.option("1. Confirm kick", () ->
clientThread.invoke(() ->
{
kickConfirmed = true;
client.runScript(ScriptID.CLAN_SEND_KICK, kickPlayerName);
kickConfirmed = false;
})
)
.option("2. Cancel", Runnables::doNothing)
.build();
}
private void addClanCounter()
{
if (!this.showClanCounter || clanMemberCounter != null || clanMembers.isEmpty())

View File

@@ -26,28 +26,33 @@
package net.runelite.client.plugins.devtools;
import java.awt.GridLayout;
import java.awt.TrayIcon;
import javax.inject.Inject;
import javax.swing.JButton;
import javax.swing.JPanel;
import net.runelite.api.Client;
import net.runelite.client.Notifier;
import net.runelite.client.ui.ColorScheme;
import net.runelite.client.ui.PluginPanel;
class DevToolsPanel extends PluginPanel
{
private final Client client;
private final Notifier notifier;
private final DevToolsPlugin plugin;
private final WidgetInspector widgetInspector;
private final VarInspector varInspector;
@Inject
private DevToolsPanel(Client client, DevToolsPlugin plugin, WidgetInspector widgetInspector, VarInspector varInspector)
private DevToolsPanel(Client client, DevToolsPlugin plugin, WidgetInspector widgetInspector, VarInspector varInspector, Notifier notifier)
{
super();
this.client = client;
this.plugin = plugin;
this.widgetInspector = widgetInspector;
this.varInspector = varInspector;
this.notifier = notifier;
setBackground(ColorScheme.DARK_GRAY_COLOR);
@@ -135,6 +140,13 @@ class DevToolsPanel extends PluginPanel
container.add(plugin.getSoundEffects());
final JButton notificationBtn = new JButton("Notification");
notificationBtn.addActionListener(e ->
{
notifier.notify("Wow!", TrayIcon.MessageType.ERROR);
});
container.add(notificationBtn);
return container;
}
}

View File

@@ -38,7 +38,7 @@ enum ItemIdentification
RANARR_SEED(Type.SEED, "Ranarr", "R", ItemID.RANARR_SEED),
TOADFLAX_SEED(Type.SEED, "Toad", "TOA", ItemID.TOADFLAX_SEED),
IRIT_SEED(Type.SEED, "Irit", "I", ItemID.IRIT_SEED),
AVANTOE_SEED(Type.SEED, "Avantoe", "A", ItemID.AVANTOE_SEED),
AVANTOE_SEED(Type.SEED, "Avan", "A", ItemID.AVANTOE_SEED),
KWUARM_SEED(Type.SEED, "Kwuarm", "K", ItemID.KWUARM_SEED),
SNAPDRAGON_SEED(Type.SEED, "Snap", "S", ItemID.SNAPDRAGON_SEED),
CADANTINE_SEED(Type.SEED, "Cadan", "C", ItemID.CADANTINE_SEED),
@@ -56,7 +56,7 @@ enum ItemIdentification
RANARR(Type.HERB, "Ranarr", "R", ItemID.RANARR_WEED, ItemID.GRIMY_RANARR_WEED),
TOADFLAX(Type.HERB, "Toad", "TOA", ItemID.TOADFLAX, ItemID.GRIMY_TOADFLAX),
IRIT(Type.HERB, "Irit", "I", ItemID.IRIT_LEAF, ItemID.GRIMY_IRIT_LEAF),
AVANTOE(Type.HERB, "Avantoe", "A", ItemID.AVANTOE, ItemID.GRIMY_AVANTOE),
AVANTOE(Type.HERB, "Avan", "A", ItemID.AVANTOE, ItemID.GRIMY_AVANTOE),
KWUARM(Type.HERB, "Kwuarm", "K", ItemID.KWUARM, ItemID.GRIMY_KWUARM),
SNAPDRAGON(Type.HERB, "Snap", "S", ItemID.SNAPDRAGON, ItemID.GRIMY_SNAPDRAGON),
CADANTINE(Type.HERB, "Cadan", "C", ItemID.CADANTINE, ItemID.GRIMY_CADANTINE),

View File

@@ -129,7 +129,7 @@ public class SlayerPlugin extends Plugin
//NPC messages
private static final Pattern NPC_ASSIGN_MESSAGE = Pattern.compile(".*(?:Your new task is to kill|You are to bring balance to)\\s*(?<amount>\\d+) (?<name>.+?)(?: (?:in|on|south of) (?:the )?(?<location>.+))?\\.");
private static final Pattern NPC_ASSIGN_BOSS_MESSAGE = Pattern.compile("^Excellent. You're now assigned to kill (?:the )?(.*) (\\d+) times.*Your reward point tally is (.*)\\.$");
private static final Pattern NPC_ASSIGN_FIRST_MESSAGE = Pattern.compile("^We'll start you off hunting (.*), you'll need to kill (\\d*) of them.");
private static final Pattern NPC_ASSIGN_FIRST_MESSAGE = Pattern.compile("^We'll start you off (?:hunting|bringing balance to) (.*), you'll need to kill (\\d*) of them\\.$");
private static final Pattern NPC_CURRENT_MESSAGE = Pattern.compile("^You're still (?:hunting|bringing balance to) (?<name>.+)(?: (?:in|on|south of) (?:the )?(?<location>.+), with|; you have) (?<amount>\\d+) to go\\..*");
private static final int GROTESQUE_GUARDIANS_REGION = 6727;

View File

@@ -172,6 +172,7 @@ public class TwitchPlugin extends Plugin implements TwitchListener, ChatboxInput
.sender("Twitch")
.name(sender)
.runeLiteFormattedMessage(chatMessage)
.timestamp((int) (System.currentTimeMillis() / 1000))
.build());
}

View File

@@ -28,14 +28,16 @@ package net.runelite.client.plugins.woodcutting;
import java.time.Instant;
import lombok.AllArgsConstructor;
import lombok.Getter;
import net.runelite.api.coords.LocalPoint;
import net.runelite.api.coords.WorldPoint;
@AllArgsConstructor
@Getter
class TreeRespawn
{
private final Tree tree;
private final LocalPoint location;
private final int lenX;
private final int lenY;
private final WorldPoint worldLocation;
private final Instant startTime;
private final int respawnTime;

View File

@@ -42,6 +42,8 @@ import net.runelite.api.GameObject;
import net.runelite.api.ItemID;
import net.runelite.api.MenuOpcode;
import net.runelite.api.Player;
import net.runelite.api.Point;
import net.runelite.api.coords.WorldPoint;
import net.runelite.api.events.AnimationChanged;
import net.runelite.api.events.ChatMessage;
import net.runelite.api.events.GameObjectChanged;
@@ -217,8 +219,12 @@ public class WoodcuttingPlugin extends Plugin
{
if (tree.getRespawnTime() != null && !recentlyLoggedIn)
{
Point max = object.getSceneMaxLocation();
Point min = object.getSceneMinLocation();
int lenX = max.getX() - min.getX();
int lenY = max.getY() - min.getY();
log.debug("Adding respawn timer for {} tree at {}", tree, object.getLocalLocation());
TreeRespawn treeRespawn = new TreeRespawn(tree, object.getLocalLocation(), Instant.now(), (int) tree.getRespawnTime().toMillis());
TreeRespawn treeRespawn = new TreeRespawn(tree, lenX, lenY, WorldPoint.fromScene(client, min.getX(), min.getY(), client.getPlane()), Instant.now(), (int) tree.getRespawnTime().toMillis());
respawns.add(treeRespawn);
}
@@ -240,9 +246,9 @@ public class WoodcuttingPlugin extends Plugin
{
switch (event.getGameState())
{
case LOADING:
case HOPPING:
respawns.clear();
case LOADING:
treeObjects.clear();
break;
case LOGGED_IN:

View File

@@ -103,10 +103,17 @@ class WoodcuttingTreesOverlay extends Overlay
Instant now = Instant.now();
for (TreeRespawn treeRespawn : respawns)
{
LocalPoint loc = treeRespawn.getLocation();
LocalPoint minLocation = LocalPoint.fromWorld(client, treeRespawn.getWorldLocation());
if (minLocation == null)
{
continue;
}
LocalPoint centeredLocation = new LocalPoint(
minLocation.getX() + treeRespawn.getLenX() * Perspective.LOCAL_HALF_TILE_SIZE,
minLocation.getY() + treeRespawn.getLenY() * Perspective.LOCAL_HALF_TILE_SIZE);
float percent = (now.toEpochMilli() - treeRespawn.getStartTime().toEpochMilli()) / (float) treeRespawn.getRespawnTime();
Point point = Perspective.localToCanvas(client, loc, client.getPlane());
Point point = Perspective.localToCanvas(client, centeredLocation, client.getPlane());
if (point == null || percent > 1.0f)
{
continue;

View File

@@ -0,0 +1,2 @@
Notification is cloud from
https://github.com/akx/Notifications

View File

@@ -0,0 +1 @@
9B3B448D76D57F6D63C9CDA06E58695F6DEBE91F9EDF2D2C4876E064D1067FD6

View File

@@ -0,0 +1,34 @@
.id 215
.int_stack_count 0
.string_stack_count 1
.int_var_count 0
.string_var_count 1
; callback "confirmClanKick"
; Used by the ClanChat plugin to show a chatbox panel confirming the requested kick
; Also requires the "confirmKicks" option of ClanChatConfig to be enabled
invoke 1942
iconst 1
if_icmpeq LABEL4
jump CONFIRM_KICK ; Jump to our new label instead
LABEL4:
sconst "You can't kick players from your team during Wilderness Wars."
mes
return
LABEL7:
sconst "-Attempting to kick player from friends chat..."
iconst 2
invoke 96
sload 0
clan_kickuser
jump LABEL73
LABEL73:
return
CONFIRM_KICK:
sload 0 ; Username we are trying to kick
iconst 0 ; Modified if we are confirming the kick inside the plugin
sconst "confirmClanKick"
runelite_callback
pop_string ; Pop username
iconst 0 ; Compare against zero
if_icmpgt LABEL73 ; Early return for chatbox panel confirmation
jump LABEL7

View File

@@ -76,6 +76,7 @@ public class SlayerPluginTest
private static final String TASK_NEW_KONAR_2 = "You are to bring balance to 142 Hellhounds in Witchhaven Dungeon.";
private static final String TASK_NEW_KONAR_3 = "You are to bring balance to 135 Trolls south of Mount Quidamortem.";
private static final String TASK_NEW_FIRST = "We'll start you off hunting goblins, you'll need to kill 17 of them.";
private static final String TASK_NEW_FIRST_KONAR = "We'll start you off bringing balance to cows, you'll need to kill 44 of them.";
private static final String TASK_NEW_NPC_CONTACT = "Excellent, you're doing great. Your new task is to kill<br>211 Suqahs.";
private static final String TASK_NEW_FROM_PARTNER = "You have received a new Slayer assignment from breaklulz: Dust Devils (377)";
private static final String TASK_CHECKSLAYERGEM = "You're assigned to kill Suqahs; only 211 more to go.";
@@ -223,6 +224,18 @@ public class SlayerPluginTest
assertEquals(17, slayerPlugin.getCurrentTask().getAmount());
}
@Test
public void testFirstTaskKonar()
{
Widget npcDialog = mock(Widget.class);
when(npcDialog.getText()).thenReturn(TASK_NEW_FIRST_KONAR);
when(client.getWidget(WidgetInfo.DIALOG_NPC_TEXT)).thenReturn(npcDialog);
slayerPlugin.onGameTick(GameTick.INSTANCE);
assertEquals("cows", slayerPlugin.getCurrentTask().getTaskName());
assertEquals(44, slayerPlugin.getCurrentTask().getAmount());
}
@Test
public void testNewNpcContactTask()
{