Merge branch 'master' into maven-plugin-upgrades

This commit is contained in:
William Collishaw
2019-05-16 22:22:24 -06:00
168 changed files with 2311 additions and 390 deletions

View File

@@ -29,7 +29,7 @@
<parent>
<groupId>net.runelite</groupId>
<artifactId>runelite-parent</artifactId>
<version>1.5.23-SNAPSHOT</version>
<version>1.5.24-SNAPSHOT</version>
</parent>
<artifactId>client</artifactId>

View File

@@ -150,6 +150,8 @@ public class Notifier
{
flashStart = Instant.now();
}
log.debug(message);
}
public void processFlash(final Graphics2D graphics)

View File

@@ -42,6 +42,7 @@ import javax.inject.Singleton;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.BufferProvider;
import net.runelite.api.Client;
import net.runelite.api.Constants;
import net.runelite.api.MainBufferProvider;
import net.runelite.api.NullItemID;
import net.runelite.api.RenderOverview;
@@ -79,7 +80,7 @@ import net.runelite.client.util.DeferredEventBus;
@Slf4j
public class Hooks implements Callbacks
{
private static final long CHECK = 600; // ms - how often to run checks
private static final long CHECK = Constants.GAME_TICK_LENGTH; // ms - how often to run checks
private static final Injector injector = RuneLite.getInjector();
private static final Client client = injector.getInstance(Client.class);

View File

@@ -548,8 +548,14 @@ public class ChatMessageManager
{
if (!queuedMessages.isEmpty())
{
queuedMessages.forEach(this::add);
queuedMessages.clear();
try
{
queuedMessages.forEach(this::add);
}
finally
{
queuedMessages.clear();
}
}
}

View File

@@ -26,12 +26,14 @@ package net.runelite.client.chat;
import lombok.Builder;
import lombok.Data;
import lombok.NonNull;
import net.runelite.api.ChatMessageType;
@Data
@Builder
public class QueuedMessage
{
@NonNull
private final ChatMessageType type;
private final String value;
private String name;

View File

@@ -165,7 +165,7 @@ public enum AgilityShortcut
YANILLE_DUNGEON_RUBBLE_CLIMB(67, "Pile of Rubble", null, PILE_OF_RUBBLE_23563, PILE_OF_RUBBLE_23564),
ELVEN_OVERPASS_MEDIUM_CLIFF(68, "Rocks", new WorldPoint(2337, 3288, 0), ROCKS_16514, ROCKS_16515),
WEISS_OBSTACLES(68, "Shortcut", null, LITTLE_BOULDER, ROCKSLIDE_33184, ROCKSLIDE_33185, NULL_33327, NULL_33328, LEDGE_33190, ROCKSLIDE_33191, FALLEN_TREE_33192),
ARCEUUS_ESSENSE_NORTH(69, "Rock Climb", new WorldPoint(1759, 3873, 0), ROCKS_27984, ROCKS_27985),
ARCEUUS_ESSENSE_NORTH(69, "Rock Climb", new WorldPoint(1761, 3873, 0), ROCKS_34741),
TAVERLEY_DUNGEON_PIPE_BLUE_DRAGON(70, "Pipe Squeeze", new WorldPoint(2886, 9798, 0), OBSTACLE_PIPE_16509),
TAVERLEY_DUNGEON_ROCKS_NORTH(70, "Rocks", new WorldPoint(2887, 9823, 0), ROCKS, ROCKS_14106),
TAVERLEY_DUNGEON_ROCKS_SOUTH(70, "Rocks", new WorldPoint(2887, 9631, 0), ROCKS, ROCKS_14106),

View File

@@ -30,10 +30,6 @@ import com.google.common.cache.LoadingCache;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DataBufferByte;
import java.awt.image.IndexColorModel;
import java.awt.image.WritableRaster;
import java.util.Arrays;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
@@ -152,8 +148,8 @@ public class ClanManager
for (int i = 0; i < CLANCHAT_IMAGES.length; i++, curPosition++)
{
final int resource = CLANCHAT_IMAGES[i];
clanChatImages[i] = rgbaToIndexedBufferedImage(clanChatImageFromSprite(spriteManager.getSprite(resource, 0)));
newModIcons[curPosition] = createIndexedSprite(client, clanChatImages[i]);
clanChatImages[i] = clanChatImageFromSprite(spriteManager.getSprite(resource, 0));
newModIcons[curPosition] = ImageUtil.getImageIndexedSprite(clanChatImages[i], client);
}
client.setModIcons(newModIcons);
@@ -166,54 +162,6 @@ public class ClanManager
return cleaned.replace('\u00A0', ' ');
}
private static IndexedSprite createIndexedSprite(final Client client, final BufferedImage bufferedImage)
{
final IndexColorModel indexedCM = (IndexColorModel) bufferedImage.getColorModel();
final int width = bufferedImage.getWidth();
final int height = bufferedImage.getHeight();
final byte[] pixels = ((DataBufferByte) bufferedImage.getRaster().getDataBuffer()).getData();
final int[] palette = new int[indexedCM.getMapSize()];
indexedCM.getRGBs(palette);
final IndexedSprite newIndexedSprite = client.createIndexedSprite();
newIndexedSprite.setPixels(pixels);
newIndexedSprite.setPalette(palette);
newIndexedSprite.setWidth(width);
newIndexedSprite.setHeight(height);
newIndexedSprite.setOriginalWidth(width);
newIndexedSprite.setOriginalHeight(height);
newIndexedSprite.setOffsetX(0);
newIndexedSprite.setOffsetY(0);
return newIndexedSprite;
}
private static BufferedImage rgbaToIndexedBufferedImage(final BufferedImage sourceBufferedImage)
{
final BufferedImage indexedImage = new BufferedImage(
sourceBufferedImage.getWidth(),
sourceBufferedImage.getHeight(),
BufferedImage.TYPE_BYTE_INDEXED);
final ColorModel cm = indexedImage.getColorModel();
final IndexColorModel icm = (IndexColorModel) cm;
final int size = icm.getMapSize();
final byte[] reds = new byte[size];
final byte[] greens = new byte[size];
final byte[] blues = new byte[size];
icm.getReds(reds);
icm.getGreens(greens);
icm.getBlues(blues);
final WritableRaster raster = indexedImage.getRaster();
final int pixel = raster.getSample(0, 0, 0);
final IndexColorModel resultIcm = new IndexColorModel(8, size, reds, greens, blues, pixel);
final BufferedImage resultIndexedImage = new BufferedImage(resultIcm, raster, sourceBufferedImage.isAlphaPremultiplied(), null);
resultIndexedImage.getGraphics().drawImage(sourceBufferedImage, 0, 0, null);
return resultIndexedImage;
}
private static BufferedImage clanChatImageFromSprite(final BufferedImage clanSprite)
{
final BufferedImage clanChatCanvas = ImageUtil.resizeCanvas(clanSprite, CLANCHAT_IMAGE_DIMENSION.width, CLANCHAT_IMAGE_DIMENSION.height);

View File

@@ -103,6 +103,8 @@ public enum ItemMapping
ITEM_OCCULT_ORNAMENT_KIT(OCCULT_ORNAMENT_KIT, OCCULT_NECKLACE_OR),
ITE_AMULET_OF_FURY(AMULET_OF_FURY, AMULET_OF_FURY_OR),
ITE_FURY_ORNAMENT_KIT(FURY_ORNAMENT_KIT, AMULET_OF_FURY_OR),
ITEM_TORMENTED_BRACELET(TORMENTED_BRACELET, TORMENTED_BRACELET_OR),
ITEM_TORMENTED_ORNAMENT_KIT(TORMENTED_ORNAMENT_KIT, TORMENTED_BRACELET_OR),
// Ensouled heads
ITEM_ENSOULED_GOBLIN_HEAD(ENSOULED_GOBLIN_HEAD_13448, ENSOULED_GOBLIN_HEAD),

View File

@@ -25,12 +25,12 @@
package net.runelite.client.game;
import com.google.common.collect.ImmutableMap;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
@@ -39,7 +39,7 @@ import java.util.Map;
*/
public class ItemVariationMapping
{
private static final Map<Integer, Integer> MAPPINGS = new HashMap<>();
private static final Map<Integer, Integer> MAPPINGS;
static
{
@@ -51,6 +51,7 @@ public class ItemVariationMapping
final InputStream geLimitData = ItemVariationMapping.class.getResourceAsStream("/item_variations.json");
final Map<String, Collection<Integer>> itemVariations = gson.fromJson(new InputStreamReader(geLimitData), typeToken.getType());
ImmutableMap.Builder<Integer, Integer> builder = new ImmutableMap.Builder<>();
for (Collection<Integer> value : itemVariations.values())
{
final Iterator<Integer> iterator = value.iterator();
@@ -58,9 +59,10 @@ public class ItemVariationMapping
while (iterator.hasNext())
{
MAPPINGS.put(iterator.next(), base);
builder.put(iterator.next(), base);
}
}
MAPPINGS = builder.build();
}
/**

View File

@@ -140,6 +140,6 @@ public class WesternDiaryRequirement extends GenericDiaryRequirement
new QuestRequirement(Quest.BIG_CHOMPY_BIRD_HUNTING));
add("Pickpocket an Elf.",
new SkillRequirement(Skill.THIEVING, 85),
new QuestRequirement(Quest.MOURNINGS_ENDS_PART_II));
new QuestRequirement(Quest.MOURNINGS_ENDS_PART_I, true));
}
}

View File

@@ -24,7 +24,7 @@
*/
package net.runelite.client.plugins.agility;
import java.util.HashMap;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
import lombok.Getter;
import net.runelite.api.coords.WorldPoint;
@@ -48,7 +48,7 @@ enum Courses
RELLEKA(780.0, 475, 10553),
ARDOUGNE(793.0, 529, 10547);
private final static Map<Integer, Courses> coursesByRegion = new HashMap<>();
private final static Map<Integer, Courses> coursesByRegion;
@Getter
private final double totalXp;
@@ -64,10 +64,14 @@ enum Courses
static
{
ImmutableMap.Builder<Integer, Courses> builder = new ImmutableMap.Builder<>();
for (Courses course : values())
{
coursesByRegion.put(course.regionId, course);
builder.put(course.regionId, course);
}
coursesByRegion = builder.build();
}
Courses(double totalXp, int lastObstacleXp, int regionId, WorldPoint... courseEndWorldPoints)

View File

@@ -24,6 +24,7 @@
*/
package net.runelite.client.plugins.antidrag;
import net.runelite.api.Constants;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@@ -39,6 +40,6 @@ public interface AntiDragConfig extends Config
)
default int dragDelay()
{
return 600 / 20; // one game tick
return Constants.GAME_TICK_LENGTH / Constants.CLIENT_TICK_LENGTH; // one game tick
}
}

View File

@@ -24,9 +24,17 @@
*/
package net.runelite.client.plugins.attackstyles;
import java.util.HashMap;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
import static net.runelite.client.plugins.attackstyles.AttackStyle.*;
import static net.runelite.client.plugins.attackstyles.AttackStyle.ACCURATE;
import static net.runelite.client.plugins.attackstyles.AttackStyle.AGGRESSIVE;
import static net.runelite.client.plugins.attackstyles.AttackStyle.CASTING;
import static net.runelite.client.plugins.attackstyles.AttackStyle.CONTROLLED;
import static net.runelite.client.plugins.attackstyles.AttackStyle.DEFENSIVE;
import static net.runelite.client.plugins.attackstyles.AttackStyle.DEFENSIVE_CASTING;
import static net.runelite.client.plugins.attackstyles.AttackStyle.LONGRANGE;
import static net.runelite.client.plugins.attackstyles.AttackStyle.OTHER;
import static net.runelite.client.plugins.attackstyles.AttackStyle.RANGING;
enum WeaponType
{
@@ -59,16 +67,20 @@ enum WeaponType
TYPE_26(AGGRESSIVE, AGGRESSIVE, null, AGGRESSIVE),
TYPE_27(ACCURATE, null, null, OTHER);
private static final Map<Integer, WeaponType> weaponTypes = new HashMap<>();
private final AttackStyle[] attackStyles;
private static final Map<Integer, WeaponType> weaponTypes;
static
{
ImmutableMap.Builder<Integer, WeaponType> builder = new ImmutableMap.Builder<>();
for (WeaponType weaponType : values())
{
weaponTypes.put(weaponType.ordinal(), weaponType);
builder.put(weaponType.ordinal(), weaponType);
}
weaponTypes = builder.build();
}
WeaponType(AttackStyle... attackStyles)

View File

@@ -31,13 +31,15 @@ import java.awt.Image;
import javax.inject.Inject;
import net.runelite.api.ChatMessageType;
import net.runelite.api.Client;
import net.runelite.api.EquipmentInventorySlot;
import net.runelite.api.InventoryID;
import net.runelite.api.Item;
import net.runelite.api.ItemID;
import net.runelite.api.Varbits;
import net.runelite.api.events.ChatMessage;
import net.runelite.api.events.GameTick;
import net.runelite.api.events.ItemContainerChanged;
import net.runelite.api.events.VarbitChanged;
import net.runelite.api.events.WidgetLoaded;
import net.runelite.api.kit.KitType;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetID;
import net.runelite.api.widgets.WidgetInfo;
@@ -145,14 +147,27 @@ public class BarbarianAssaultPlugin extends Plugin
}
@Subscribe
public void onGameTick(GameTick event)
public void onItemContainerChanged(final ItemContainerChanged event)
{
if (client.getVar(Varbits.IN_GAME_BA) == 0 || client.getLocalPlayer() == null || overlay.getCurrentRound() != null)
if (event.getItemContainer() != client.getItemContainer(InventoryID.EQUIPMENT))
{
return;
}
switch (client.getLocalPlayer().getPlayerComposition().getEquipmentId(KitType.CAPE))
if (overlay.getCurrentRound() != null)
{
return;
}
final Item[] items = event.getItemContainer().getItems();
// Check that the local player is wearing enough items to be wearing a cape.
if (items == null || items.length <= EquipmentInventorySlot.CAPE.getSlotIdx())
{
return;
}
switch (items[EquipmentInventorySlot.CAPE.getSlotIdx()].getId())
{
case ItemID.ATTACKER_ICON:
overlay.setCurrentRound(new Round(Role.ATTACKER));

View File

@@ -28,6 +28,7 @@ import java.time.Duration;
import java.time.Instant;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import net.runelite.api.Constants;
class GameTimer
{
@@ -45,7 +46,7 @@ class GameTimer
}
else
{
elapsed = Duration.between(startTime, now).minusMillis(600);
elapsed = Duration.between(startTime, now).minusMillis(Constants.GAME_TICK_LENGTH);
}
return formatTime(LocalTime.ofSecondOfDay(elapsed.getSeconds()));

View File

@@ -29,6 +29,7 @@ import java.time.Instant;
import javax.inject.Inject;
import lombok.Getter;
import lombok.Setter;
import net.runelite.api.Constants;
class Round
{
@@ -52,7 +53,7 @@ class Round
public Round(Role role)
{
this.roundRole = role;
this.roundStartTime = Instant.now().plusMillis(1200);
this.roundStartTime = Instant.now().plusMillis(2 * Constants.GAME_TICK_LENGTH);
}
public long getRoundTime()

View File

@@ -97,4 +97,15 @@ public interface BarrowsConfig extends Config
{
return true;
}
@ConfigItem(
keyName = "showPrayerDrainTimer",
name = "Show Prayer Drain Timer",
description = "Configure whether or not a countdown until the next prayer drain is displayed",
position = 6
)
default boolean showPrayerDrainTimer()
{
return true;
}
}

View File

@@ -27,6 +27,7 @@ package net.runelite.client.plugins.barrows;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets;
import com.google.inject.Provides;
import java.time.temporal.ChronoUnit;
import java.util.HashSet;
import java.util.Set;
import javax.inject.Inject;
@@ -41,7 +42,9 @@ import net.runelite.api.Item;
import net.runelite.api.ItemContainer;
import net.runelite.api.NullObjectID;
import net.runelite.api.ObjectID;
import net.runelite.api.SpriteID;
import net.runelite.api.WallObject;
import net.runelite.api.events.ConfigChanged;
import net.runelite.api.events.GameObjectChanged;
import net.runelite.api.events.GameObjectDespawned;
import net.runelite.api.events.GameObjectSpawned;
@@ -60,9 +63,13 @@ import net.runelite.client.chat.QueuedMessage;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.game.ItemManager;
import net.runelite.client.game.SpriteManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.OverlayManager;
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
import net.runelite.client.ui.overlay.infobox.InfoBoxPriority;
import net.runelite.client.ui.overlay.infobox.LoopTimer;
import net.runelite.client.util.StackFormatter;
@PluginDescriptor(
@@ -89,12 +96,18 @@ public class BarrowsPlugin extends Plugin
WidgetInfo.BARROWS_PUZZLE_ANSWER3
);
private static final long PRAYER_DRAIN_INTERVAL_MS = 18200;
private static final int CRYPT_REGION_ID = 14231;
@Getter(AccessLevel.PACKAGE)
private final Set<WallObject> walls = new HashSet<>();
@Getter(AccessLevel.PACKAGE)
private final Set<GameObject> ladders = new HashSet<>();
private LoopTimer barrowsPrayerDrainTimer;
private boolean wasInCrypt = false;
@Getter
private Widget puzzleAnswer;
@@ -113,6 +126,12 @@ public class BarrowsPlugin extends Plugin
@Inject
private ItemManager itemManager;
@Inject
private SpriteManager spriteManager;
@Inject
private InfoBoxManager infoBoxManager;
@Inject
private ChatMessageManager chatMessageManager;
@@ -140,6 +159,8 @@ public class BarrowsPlugin extends Plugin
walls.clear();
ladders.clear();
puzzleAnswer = null;
wasInCrypt = false;
stopPrayerDrainTimer();
// Restore widgets
final Widget potential = client.getWidget(WidgetInfo.BARROWS_POTENTIAL);
@@ -155,6 +176,15 @@ public class BarrowsPlugin extends Plugin
}
}
@Subscribe
public void onConfigChanged(ConfigChanged event)
{
if (event.getGroup().equals("barrows") && !config.showPrayerDrainTimer())
{
stopPrayerDrainTimer();
}
}
@Subscribe
public void onWallObjectSpawned(WallObjectSpawned event)
{
@@ -220,11 +250,24 @@ public class BarrowsPlugin extends Plugin
{
if (event.getGameState() == GameState.LOADING)
{
wasInCrypt = isInCrypt();
// on region changes the tiles get set to null
walls.clear();
ladders.clear();
puzzleAnswer = null;
}
else if (event.getGameState() == GameState.LOGGED_IN)
{
boolean isInCrypt = isInCrypt();
if (wasInCrypt && !isInCrypt)
{
stopPrayerDrainTimer();
}
else if (!wasInCrypt && isInCrypt)
{
startPrayerDrainTimer();
}
}
}
@Subscribe
@@ -271,4 +314,34 @@ public class BarrowsPlugin extends Plugin
}
}
}
private void startPrayerDrainTimer()
{
if (config.showPrayerDrainTimer())
{
final LoopTimer loopTimer = new LoopTimer(
PRAYER_DRAIN_INTERVAL_MS,
ChronoUnit.MILLIS,
spriteManager.getSprite(SpriteID.TAB_PRAYER, 0),
this,
true);
loopTimer.setPriority(InfoBoxPriority.MED);
loopTimer.setTooltip("Prayer Drain");
infoBoxManager.addInfoBox(loopTimer);
barrowsPrayerDrainTimer = loopTimer;
}
}
private void stopPrayerDrainTimer()
{
infoBoxManager.removeInfoBox(barrowsPrayerDrainTimer);
barrowsPrayerDrainTimer = null;
}
private boolean isInCrypt()
{
return client.getLocalPlayer().getWorldLocation().getRegionID() == CRYPT_REGION_ID;
}
}

View File

@@ -24,7 +24,7 @@
*/
package net.runelite.client.plugins.blastfurnace;
import java.util.HashMap;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
import lombok.Getter;
import net.runelite.api.ItemID;
@@ -50,14 +50,18 @@ public enum BarsOres
SILVER_BAR(Varbits.BLAST_FURNACE_SILVER_BAR, ItemID.SILVER_BAR),
GOLD_BAR(Varbits.BLAST_FURNACE_GOLD_BAR, ItemID.GOLD_BAR);
private static final Map<Varbits, BarsOres> VARBIT = new HashMap<>();
private static final Map<Varbits, BarsOres> VARBIT;
static
{
ImmutableMap.Builder<Varbits, BarsOres> builder = new ImmutableMap.Builder<>();
for (BarsOres s : values())
{
VARBIT.put(s.getVarbit(), s);
builder.put(s.getVarbit(), s);
}
VARBIT = builder.build();
}
@Getter

View File

@@ -35,6 +35,7 @@ import net.runelite.client.ui.overlay.Overlay;
import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE;
import net.runelite.client.ui.overlay.OverlayMenuEntry;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.components.ComponentOrientation;
import net.runelite.client.ui.overlay.components.ImageComponent;
import net.runelite.client.ui.overlay.components.PanelComponent;
@@ -54,7 +55,7 @@ class BlastFurnaceOverlay extends Overlay
this.plugin = plugin;
this.client = client;
setPosition(OverlayPosition.TOP_LEFT);
imagePanelComponent.setOrientation(PanelComponent.Orientation.HORIZONTAL);
imagePanelComponent.setOrientation(ComponentOrientation.HORIZONTAL);
getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "Blast furnace overlay"));
}

View File

@@ -1,5 +1,6 @@
/*
* Copyright (c) 2018, Seth <Sethtroll3@gmail.com>
* Copyright (c) 2019, Brandon White <bmwqg@live.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -25,21 +26,31 @@
package net.runelite.client.plugins.blastfurnace;
import com.google.inject.Provides;
import java.time.Duration;
import java.time.Instant;
import javax.inject.Inject;
import lombok.AccessLevel;
import lombok.Getter;
import net.runelite.api.Client;
import net.runelite.api.GameObject;
import net.runelite.api.GameState;
import static net.runelite.api.NullObjectID.NULL_9092;
import static net.runelite.api.ObjectID.CONVEYOR_BELT;
import net.runelite.api.Skill;
import net.runelite.api.events.GameObjectDespawned;
import net.runelite.api.events.GameObjectSpawned;
import net.runelite.api.events.GameStateChanged;
import net.runelite.api.events.GameTick;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetInfo;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.game.ItemManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.OverlayManager;
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
import net.runelite.client.util.Text;
@PluginDescriptor(
name = "Blast Furnace",
@@ -49,6 +60,7 @@ import net.runelite.client.ui.overlay.OverlayManager;
public class BlastFurnacePlugin extends Plugin
{
private static final int BAR_DISPENSER = NULL_9092;
private static final String FOREMAN_PERMISSION_TEXT = "Okay, you can use the furnace for ten minutes. Remember, you only need half as much coal as with a regular furnace.";
@Getter(AccessLevel.PACKAGE)
private GameObject conveyorBelt;
@@ -56,6 +68,8 @@ public class BlastFurnacePlugin extends Plugin
@Getter(AccessLevel.PACKAGE)
private GameObject barDispenser;
private ForemanTimer foremanTimer;
@Inject
private OverlayManager overlayManager;
@@ -68,6 +82,15 @@ public class BlastFurnacePlugin extends Plugin
@Inject
private BlastFurnaceClickBoxOverlay clickBoxOverlay;
@Inject
private Client client;
@Inject
private ItemManager itemManager;
@Inject
private InfoBoxManager infoBoxManager;
@Override
protected void startUp() throws Exception
{
@@ -79,11 +102,13 @@ public class BlastFurnacePlugin extends Plugin
@Override
protected void shutDown()
{
infoBoxManager.removeIf(ForemanTimer.class::isInstance);
overlayManager.remove(overlay);
overlayManager.remove(cofferOverlay);
overlayManager.remove(clickBoxOverlay);
conveyorBelt = null;
barDispenser = null;
foremanTimer = null;
}
@Provides
@@ -135,4 +160,31 @@ public class BlastFurnacePlugin extends Plugin
barDispenser = null;
}
}
@Subscribe
public void onGameTick(GameTick event)
{
Widget npcDialog = client.getWidget(WidgetInfo.DIALOG_NPC_TEXT);
if (npcDialog == null)
{
return;
}
// blocking dialog check until 5 minutes needed to avoid re-adding while dialog message still displayed
boolean shouldCheckForemanFee = client.getRealSkillLevel(Skill.SMITHING) < 60
&& (foremanTimer == null || Duration.between(Instant.now(), foremanTimer.getEndTime()).toMinutes() <= 5);
if (shouldCheckForemanFee)
{
String npcText = Text.sanitizeMultilineText(npcDialog.getText());
if (npcText.equals(FOREMAN_PERMISSION_TEXT))
{
infoBoxManager.removeIf(ForemanTimer.class::isInstance);
foremanTimer = new ForemanTimer(this, itemManager);
infoBoxManager.addInfoBox(foremanTimer);
}
}
}
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright (c) 2019, Brandon White <bmwqg@live.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.plugins.blastfurnace;
import java.time.temporal.ChronoUnit;
import net.runelite.api.ItemID;
import net.runelite.client.game.ItemManager;
import net.runelite.client.ui.overlay.infobox.Timer;
class ForemanTimer extends Timer
{
private static final String TOOLTIP_TEXT = "Foreman Fee";
ForemanTimer(BlastFurnacePlugin plugin, ItemManager itemManager)
{
super(10, ChronoUnit.MINUTES, itemManager.getImage(ItemID.COAL_BAG), plugin);
setTooltip(TOOLTIP_TEXT);
}
}

View File

@@ -39,6 +39,7 @@ import net.runelite.client.ui.overlay.Overlay;
import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE;
import net.runelite.client.ui.overlay.OverlayMenuEntry;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.components.ComponentOrientation;
import net.runelite.client.ui.overlay.components.ImageComponent;
import net.runelite.client.ui.overlay.components.PanelComponent;
@@ -57,7 +58,7 @@ class BlastMineOreCountOverlay extends Overlay
this.client = client;
this.config = config;
this.itemManager = itemManager;
panelComponent.setOrientation(PanelComponent.Orientation.HORIZONTAL);
panelComponent.setOrientation(ComponentOrientation.HORIZONTAL);
getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "Blast mine overlay"));
}

View File

@@ -24,7 +24,7 @@
*/
package net.runelite.client.plugins.blastmine;
import java.util.HashMap;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
import lombok.Getter;
import net.runelite.api.ObjectID;
@@ -37,17 +37,21 @@ public enum BlastMineRockType
LIT(ObjectID.POT_OF_DYNAMITE_28585, ObjectID.POT_OF_DYNAMITE_28586),
EXPLODED(ObjectID.SHATTERED_ROCKFACE, ObjectID.SHATTERED_ROCKFACE_28588);
private static final Map<Integer, BlastMineRockType> rockTypes = new HashMap<>();
private static final Map<Integer, BlastMineRockType> rockTypes;
static
{
ImmutableMap.Builder<Integer, BlastMineRockType> builder = new ImmutableMap.Builder<>();
for (BlastMineRockType type : values())
{
for (int spotId : type.getObjectIds())
{
rockTypes.put(spotId, type);
builder.put(spotId, type);
}
}
rockTypes = builder.build();
}
@Getter

View File

@@ -33,6 +33,7 @@ import javax.inject.Inject;
import javax.inject.Singleton;
import lombok.Getter;
import net.runelite.api.Client;
import net.runelite.api.Constants;
import net.runelite.api.Prayer;
import net.runelite.api.Skill;
import net.runelite.api.events.BoostedLevelChanged;
@@ -372,6 +373,6 @@ public class BoostsPlugin extends Plugin
int getChangeTime(final int time)
{
final long diff = System.currentTimeMillis() - lastTickMillis;
return time != -1 ? (int)(time * 0.6 - (diff / 1000d)) : time;
return time != -1 ? (int)((time * Constants.GAME_TICK_LENGTH - diff) / 1000d) : time;
}
}

View File

@@ -25,9 +25,9 @@
*/
package net.runelite.client.plugins.bosstimer;
import com.google.common.collect.ImmutableMap;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.HashMap;
import java.util.Map;
import net.runelite.api.ItemID;
import net.runelite.api.NpcID;
@@ -59,7 +59,7 @@ enum Boss
DUSK(NpcID.DUSK_7889, 2, ChronoUnit.MINUTES, ItemID.NOON),
ALCHEMICAL_HYDRA(NpcID.ALCHEMICAL_HYDRA_8622, 25200, ChronoUnit.MILLIS, ItemID.IKKLE_HYDRA);
private static final Map<Integer, Boss> bosses = new HashMap<>();
private static final Map<Integer, Boss> bosses;
private final int id;
private final Duration spawnTime;
@@ -67,10 +67,14 @@ enum Boss
static
{
ImmutableMap.Builder<Integer, Boss> builder = new ImmutableMap.Builder<>();
for (Boss boss : values())
{
bosses.put(boss.getId(), boss);
builder.put(boss.getId(), boss);
}
bosses = builder.build();
}
private Boss(int id, long period, ChronoUnit unit, int itemSpriteId)

View File

@@ -24,7 +24,7 @@
*/
package net.runelite.client.plugins.cerberus;
import java.util.HashMap;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
import java.util.Optional;
import lombok.Getter;
@@ -41,18 +41,21 @@ public enum CerberusGhost
MAGE(NpcID.SUMMONED_SOUL_5868, Skill.MAGIC),
MELEE(NpcID.SUMMONED_SOUL_5869, Skill.ATTACK);
private static final Map<Integer, CerberusGhost> MAP = new HashMap<>();
private final int npcId;
private final Skill type;
private static final Map<Integer, CerberusGhost> MAP;
static
{
final CerberusGhost[] values = CerberusGhost.values();
ImmutableMap.Builder<Integer, CerberusGhost> builder = new ImmutableMap.Builder<>();
for (final CerberusGhost ghost : values)
for (final CerberusGhost ghost : values())
{
MAP.put(ghost.getNpcId(), ghost);
builder.put(ghost.getNpcId(), ghost);
}
MAP = builder.build();
}
/**

View File

@@ -31,6 +31,7 @@ import javax.inject.Singleton;
import net.runelite.client.game.SkillIconManager;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.components.ComponentOrientation;
import net.runelite.client.ui.overlay.components.ImageComponent;
import net.runelite.client.ui.overlay.components.PanelComponent;
@@ -47,7 +48,7 @@ public class CerberusOverlay extends Overlay
this.plugin = plugin;
this.iconManager = iconManager;
setPosition(OverlayPosition.BOTTOM_RIGHT);
panelComponent.setOrientation(PanelComponent.Orientation.HORIZONTAL);
panelComponent.setOrientation(ComponentOrientation.HORIZONTAL);
}
@Override

View File

@@ -24,56 +24,58 @@
*/
package net.runelite.client.plugins.chatcommands;
import java.util.HashMap;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
import net.runelite.api.Skill;
class SkillAbbreviations
{
private static final Map<String, String> MAP = new HashMap<>();
private static final Map<String, String> MAP;
static
{
MAP.put("ATK", Skill.ATTACK.getName());
MAP.put("ATT", Skill.ATTACK.getName());
MAP.put("DEF", Skill.DEFENCE.getName());
MAP.put("STR", Skill.STRENGTH.getName());
MAP.put("HEALTH", Skill.HITPOINTS.getName());
MAP.put("HIT", Skill.HITPOINTS.getName());
MAP.put("HITPOINT", Skill.HITPOINTS.getName());
MAP.put("HP", Skill.HITPOINTS.getName());
MAP.put("RANGE", Skill.RANGED.getName());
MAP.put("RANGING", Skill.RANGED.getName());
MAP.put("RNG", Skill.RANGED.getName());
MAP.put("PRAY", Skill.PRAYER.getName());
MAP.put("MAG", Skill.MAGIC.getName());
MAP.put("MAGE", Skill.MAGIC.getName());
MAP.put("COOK", Skill.COOKING.getName());
MAP.put("WC", Skill.WOODCUTTING.getName());
MAP.put("WOOD", Skill.WOODCUTTING.getName());
MAP.put("WOODCUT", Skill.WOODCUTTING.getName());
MAP.put("FLETCH", Skill.FLETCHING.getName());
MAP.put("FISH", Skill.FISHING.getName());
MAP.put("FM", Skill.FIREMAKING.getName());
MAP.put("FIRE", Skill.FIREMAKING.getName());
MAP.put("CRAFT", Skill.CRAFTING.getName());
MAP.put("SMITH", Skill.SMITHING.getName());
MAP.put("MINE", Skill.MINING.getName());
MAP.put("HL", Skill.HERBLORE.getName());
MAP.put("HERB", Skill.HERBLORE.getName());
MAP.put("AGI", Skill.AGILITY.getName());
MAP.put("AGIL", Skill.AGILITY.getName());
MAP.put("THIEF", Skill.THIEVING.getName());
MAP.put("SLAY", Skill.SLAYER.getName());
MAP.put("FARM", Skill.FARMING.getName());
MAP.put("RC", Skill.RUNECRAFT.getName());
MAP.put("RUNE", Skill.RUNECRAFT.getName());
MAP.put("RUNECRAFTING", Skill.RUNECRAFT.getName());
MAP.put("HUNT", Skill.HUNTER.getName());
MAP.put("CON", Skill.CONSTRUCTION.getName());
MAP.put("CONSTRUCT", Skill.CONSTRUCTION.getName());
MAP.put("ALL", Skill.OVERALL.getName());
MAP.put("TOTAL", Skill.OVERALL.getName());
ImmutableMap.Builder<String, String> builder = new ImmutableMap.Builder<>();
builder.put("ATK", Skill.ATTACK.getName());
builder.put("ATT", Skill.ATTACK.getName());
builder.put("DEF", Skill.DEFENCE.getName());
builder.put("STR", Skill.STRENGTH.getName());
builder.put("HEALTH", Skill.HITPOINTS.getName());
builder.put("HIT", Skill.HITPOINTS.getName());
builder.put("HITPOINT", Skill.HITPOINTS.getName());
builder.put("HP", Skill.HITPOINTS.getName());
builder.put("RANGE", Skill.RANGED.getName());
builder.put("RANGING", Skill.RANGED.getName());
builder.put("RNG", Skill.RANGED.getName());
builder.put("PRAY", Skill.PRAYER.getName());
builder.put("MAG", Skill.MAGIC.getName());
builder.put("MAGE", Skill.MAGIC.getName());
builder.put("COOK", Skill.COOKING.getName());
builder.put("WC", Skill.WOODCUTTING.getName());
builder.put("WOOD", Skill.WOODCUTTING.getName());
builder.put("WOODCUT", Skill.WOODCUTTING.getName());
builder.put("FLETCH", Skill.FLETCHING.getName());
builder.put("FISH", Skill.FISHING.getName());
builder.put("FM", Skill.FIREMAKING.getName());
builder.put("FIRE", Skill.FIREMAKING.getName());
builder.put("CRAFT", Skill.CRAFTING.getName());
builder.put("SMITH", Skill.SMITHING.getName());
builder.put("MINE", Skill.MINING.getName());
builder.put("HL", Skill.HERBLORE.getName());
builder.put("HERB", Skill.HERBLORE.getName());
builder.put("AGI", Skill.AGILITY.getName());
builder.put("AGIL", Skill.AGILITY.getName());
builder.put("THIEF", Skill.THIEVING.getName());
builder.put("SLAY", Skill.SLAYER.getName());
builder.put("FARM", Skill.FARMING.getName());
builder.put("RC", Skill.RUNECRAFT.getName());
builder.put("RUNE", Skill.RUNECRAFT.getName());
builder.put("RUNECRAFTING", Skill.RUNECRAFT.getName());
builder.put("HUNT", Skill.HUNTER.getName());
builder.put("CON", Skill.CONSTRUCTION.getName());
builder.put("CONSTRUCT", Skill.CONSTRUCTION.getName());
builder.put("ALL", Skill.OVERALL.getName());
builder.put("TOTAL", Skill.OVERALL.getName());
MAP = builder.build();
}
/**

View File

@@ -24,20 +24,9 @@
*/
package net.runelite.client.plugins.chatfilter;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public enum ChatFilterType
{
CENSOR_WORDS("Censor words"),
CENSOR_MESSAGE("Censor message"),
REMOVE_MESSAGE("Remove message");
private final String name;
@Override
public String toString()
{
return name;
}
CENSOR_WORDS,
CENSOR_MESSAGE,
REMOVE_MESSAGE
}

View File

@@ -57,7 +57,7 @@ public class CipherClue extends ClueScroll implements TextClueScroll, NpcClueScr
new CipherClue("GBJSZ RVFFO", "Fairy Queen", new WorldPoint(2347, 4435, 0), "Fairy Resistance Hideout", "Puzzle"),
new CipherClue("QSPGFTTPS HSBDLMFCPOF", "Professor Gracklebone", new WorldPoint(1625, 3802, 0), "Ground floor of Arceuus Library", "9"),
new CipherClue("IWPPLQTP", "Gunnjorn", new WorldPoint(2541, 3548, 0), "Barbarian Outpost Agility course", "Puzzle"),
new CipherClue("BSOPME MZETQPS", "Arnold Lydspor", new WorldPoint(2329, 3689, 0), "Piscatorus Fishing Colony general store/bank", "Puzzle")
new CipherClue("BSOPME MZETQPS", "Arnold Lydspor", new WorldPoint(2329, 3689, 0), "Piscatoris Fishing Colony general store/bank", "Puzzle")
);
private String text;

View File

@@ -118,7 +118,7 @@ public enum HotColdLocation
MISTHALIN_VARROCK_STONE_CIRCLE(new WorldPoint(3225, 3355, 0), MISTHALIN, "South of the stone circle near Varrock's entrance."),
MISTHALIN_LUMBRIDGE(new WorldPoint(3238, 3169, 0), MISTHALIN, "Just north-west of the Lumbridge Fishing tutor."),
MISTHALIN_LUMBRIDGE_2(new WorldPoint(3170, 3278, 0), MISTHALIN, "North of the pond between Lumbridge and Draynor Village."),
MISTHALIN_GERTUDES(new WorldPoint(3158, 3421, 0), MISTHALIN, "Nort-east of Gertrude's house west of Varrock."),
MISTHALIN_GERTUDES(new WorldPoint(3158, 3421, 0), MISTHALIN, "North-east of Gertrude's house west of Varrock."),
MISTHALIN_DRAYNOR_BANK(new WorldPoint(3096, 3235, 0), MISTHALIN, "South of Draynor Village bank."),
MISTHALIN_LUMBER_YARD(new WorldPoint(3303, 3483, 0), MISTHALIN, "South of Lumber Yard, east of Assistant Serf."),
MORYTANIA_BURGH_DE_ROTT(new WorldPoint(3545, 3253, 0), MORYTANIA, "In the north-east area of Burgh de Rott, by the reverse-L-shaped ruins."),

View File

@@ -168,12 +168,18 @@ class CombatLevelOverlay extends Overlay
@VisibleForTesting
static int calcLevelsPray(double start, int end, int prayerLevel)
{
final int neededLevels = (int) Math.floor(calcMultipliedLevels(start, end, PRAY_MULT));
int neededLevels = (int) Math.ceil(calcMultipliedLevels(start, end, PRAY_MULT));
if (prayerLevel % 2 != 0)
{
neededLevels--;
}
if ((prayerLevel + neededLevels) % 2 != 0)
{
return neededLevels + 1;
}
return neededLevels;
}

View File

@@ -492,7 +492,7 @@ public class ConfigPanel extends PluginPanel
{
Enum selectedItem = Enum.valueOf(type, configManager.getConfiguration(cd.getGroup().value(), cid.getItem().keyName()));
box.setSelectedItem(selectedItem);
box.setToolTipText(selectedItem.toString());
box.setToolTipText(Text.titleCase(selectedItem));
}
catch (IllegalArgumentException ex)
{
@@ -503,7 +503,7 @@ public class ConfigPanel extends PluginPanel
if (e.getStateChange() == ItemEvent.SELECTED)
{
changeConfiguration(listItem, config, box, cd, cid);
box.setToolTipText(box.getSelectedItem().toString());
box.setToolTipText(Text.titleCase((Enum) box.getSelectedItem()));
}
});
item.add(box, BorderLayout.EAST);

View File

@@ -42,4 +42,15 @@ public interface CookingConfig extends Config
{
return 5;
}
@ConfigItem(
position = 2,
keyName = "fermentTimer",
name = "Show wine fermenting timer",
description = "Conifgures if the timer before wines are fermented is shown."
)
default boolean fermentTimer()
{
return true;
}
}

View File

@@ -29,8 +29,8 @@ import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.text.DecimalFormat;
import java.time.Instant;
import java.time.Duration;
import java.time.Instant;
import javax.inject.Inject;
import static net.runelite.api.AnimationID.COOKING_FIRE;
import static net.runelite.api.AnimationID.COOKING_RANGE;
@@ -72,7 +72,7 @@ class CookingOverlay extends Overlay
@Override
public Dimension render(Graphics2D graphics)
{
CookingSession session = plugin.getSession();
CookingSession session = plugin.getCookingSession();
if (session == null)
{
return null;

View File

@@ -50,17 +50,25 @@ import net.runelite.client.ui.overlay.OverlayManager;
@PluginDependency(XpTrackerPlugin.class)
public class CookingPlugin extends Plugin
{
private static final String WINE_MESSAGE = "You squeeze the grapes into the jug";
@Inject
private CookingConfig config;
@Inject
private CookingOverlay overlay;
private CookingOverlay cookingOverlay;
@Inject
private FermentTimerOverlay fermentTimerOverlay;
@Inject
private OverlayManager overlayManager;
@Getter(AccessLevel.PACKAGE)
private CookingSession session;
private CookingSession cookingSession;
@Getter(AccessLevel.PACKAGE)
private FermentTimerSession fermentTimerSession;
@Provides
CookingConfig getConfig(ConfigManager configManager)
@@ -71,31 +79,48 @@ public class CookingPlugin extends Plugin
@Override
protected void startUp() throws Exception
{
session = null;
overlayManager.add(overlay);
cookingSession = null;
fermentTimerSession = null;
overlayManager.add(cookingOverlay);
overlayManager.add(fermentTimerOverlay);
}
@Override
protected void shutDown() throws Exception
{
overlayManager.remove(overlay);
session = null;
overlayManager.remove(fermentTimerOverlay);
overlayManager.remove(cookingOverlay);
fermentTimerSession = null;
cookingSession = null;
}
@Subscribe
public void onGameTick(GameTick gameTick)
{
if (session == null || config.statTimeout() == 0)
if (config.statTimeout() == 0)
{
return;
}
Duration statTimeout = Duration.ofMinutes(config.statTimeout());
Duration sinceCut = Duration.between(session.getLastCookingAction(), Instant.now());
if (sinceCut.compareTo(statTimeout) >= 0)
if (cookingSession != null)
{
session = null;
Duration statTimeout = Duration.ofMinutes(config.statTimeout());
Duration sinceCut = Duration.between(cookingSession.getLastCookingAction(), Instant.now());
if (sinceCut.compareTo(statTimeout) >= 0)
{
cookingSession = null;
}
}
if (fermentTimerSession != null)
{
Duration statTimeout = Duration.ofMinutes(config.statTimeout());
Duration sinceCut = Duration.between(fermentTimerSession.getLastWineMakingAction(), Instant.now());
if (sinceCut.compareTo(statTimeout) >= 0)
{
fermentTimerSession = null;
}
}
}
@@ -109,31 +134,41 @@ public class CookingPlugin extends Plugin
final String message = event.getMessage();
if (message.startsWith(WINE_MESSAGE) && config.fermentTimer())
{
if (fermentTimerSession == null)
{
fermentTimerSession = new FermentTimerSession();
}
fermentTimerSession.updateLastWineMakingAction();
}
if (message.startsWith("You successfully cook")
|| message.startsWith("You successfully bake")
|| message.startsWith("You manage to cook")
|| message.startsWith("You roast a")
|| message.startsWith("You cook")
|| message.startsWith("You squeeze the grapes into the jug"))
|| message.startsWith(WINE_MESSAGE))
{
if (session == null)
if (cookingSession == null)
{
session = new CookingSession();
cookingSession = new CookingSession();
}
session.updateLastCookingAction();
session.increaseCookAmount();
cookingSession.updateLastCookingAction();
cookingSession.increaseCookAmount();
}
else if (message.startsWith("You accidentally burn"))
{
if (session == null)
if (cookingSession == null)
{
session = new CookingSession();
cookingSession = new CookingSession();
}
session.updateLastCookingAction();
session.increaseBurnAmount();
cookingSession.updateLastCookingAction();
cookingSession.increaseBurnAmount();
}
}
}

View File

@@ -0,0 +1,101 @@
/*
* Copyright (c) 2019, Lucas C <lucas1757@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.plugins.cooking;
import com.google.inject.Inject;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.time.Duration;
import java.time.Instant;
import lombok.extern.slf4j.Slf4j;
import static net.runelite.api.AnimationID.COOKING_WINE;
import net.runelite.api.Client;
import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG;
import net.runelite.client.ui.overlay.Overlay;
import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE;
import net.runelite.client.ui.overlay.OverlayMenuEntry;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.components.LineComponent;
import net.runelite.client.ui.overlay.components.PanelComponent;
import net.runelite.client.ui.overlay.components.TitleComponent;
@Slf4j
class FermentTimerOverlay extends Overlay
{
private static final int INITIAL_TIME = 12;
private final Client client;
private final CookingPlugin plugin;
private final PanelComponent panelComponent = new PanelComponent();
@Inject
private FermentTimerOverlay(final Client client, final CookingPlugin plugin)
{
super(plugin);
setPosition(OverlayPosition.TOP_LEFT);
this.client = client;
this.plugin = plugin;
getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "Fermenting Timer overlay"));
}
@Override
public Dimension render(Graphics2D graphics)
{
FermentTimerSession session = plugin.getFermentTimerSession();
if (session == null)
{
return null;
}
panelComponent.getChildren().clear();
if (isMakingWine() || Duration.between(session.getLastWineMakingAction(), Instant.now()).getSeconds() < INITIAL_TIME)
{
panelComponent.getChildren().add(TitleComponent.builder()
.text("Making Wine")
.color(Color.GREEN)
.build());
panelComponent.getChildren().add(LineComponent.builder()
.left("Ferments in: ")
.right(String.valueOf(INITIAL_TIME - Duration.between(session.getLastWineMakingAction(), Instant.now()).getSeconds()))
.build());
}
else
{
panelComponent.getChildren().add(TitleComponent.builder()
.text("Wine Fermented")
.color(Color.ORANGE)
.build());
}
return panelComponent.render(graphics);
}
private boolean isMakingWine()
{
return (client.getLocalPlayer().getAnimation() == COOKING_WINE);
}
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright (c) 2019, Lucas C <lucas1757@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.plugins.cooking;
import java.time.Instant;
import lombok.AccessLevel;
import lombok.Getter;
class FermentTimerSession
{
@Getter(AccessLevel.PACKAGE)
private Instant lastWineMakingAction;
void updateLastWineMakingAction()
{
this.lastWineMakingAction = Instant.now();
}
}

View File

@@ -25,8 +25,8 @@
*/
package net.runelite.client.plugins.discord;
import java.util.ArrayList;
import java.util.HashMap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import java.util.List;
import java.util.Map;
import lombok.AllArgsConstructor;
@@ -250,16 +250,18 @@ enum DiscordGameEventType
RAIDS_CHAMBERS_OF_XERIC("Chambers of Xeric", DiscordAreaType.RAIDS, Varbits.IN_RAID),
RAIDS_THEATRE_OF_BLOOD("Theatre of Blood", DiscordAreaType.RAIDS, Varbits.THEATRE_OF_BLOOD);
private static final Map<Integer, DiscordGameEventType> FROM_REGION = new HashMap<>();
private static final List<DiscordGameEventType> FROM_VARBITS = new ArrayList<>();
private static final Map<Integer, DiscordGameEventType> FROM_REGION;
private static final List<DiscordGameEventType> FROM_VARBITS;
static
{
ImmutableMap.Builder<Integer, DiscordGameEventType> regionMapBuilder = new ImmutableMap.Builder<>();
ImmutableList.Builder<DiscordGameEventType> fromVarbitsBuilder = ImmutableList.builder();
for (DiscordGameEventType discordGameEventType : DiscordGameEventType.values())
{
if (discordGameEventType.getVarbits() != null)
{
FROM_VARBITS.add(discordGameEventType);
fromVarbitsBuilder.add(discordGameEventType);
continue;
}
@@ -270,10 +272,11 @@ enum DiscordGameEventType
for (int region : discordGameEventType.getRegionIds())
{
assert !FROM_REGION.containsKey(region);
FROM_REGION.put(region, discordGameEventType);
regionMapBuilder.put(region, discordGameEventType);
}
}
FROM_REGION = regionMapBuilder.build();
FROM_VARBITS = fromVarbitsBuilder.build();
}
private String imageKey;

View File

@@ -0,0 +1,114 @@
/*
* Copyright (c) 2019, Lotto <https://github.com/devLotto>
* 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.emojis;
import com.google.common.collect.ImmutableMap;
import java.awt.image.BufferedImage;
import java.util.Map;
import net.runelite.client.util.ImageUtil;
enum Emoji
{
SLIGHT_SMILE(":)"),
JOY("=')"),
COWBOY("3:)"),
BLUSH("^_^"),
SMILE(":D"),
GRINNING("=D"),
WINK(";)"),
STUCK_OUT_TONGUE_CLOSED_EYES("X-P"),
STUCK_OUT_TONGUE(":P"),
YUM("=P~"),
HUGGING("<gt>:D<lt>"), // >:D<
TRIUMPH(":<gt>"), // :>
THINKING(":-?"),
CONFUSED(":/"),
NEUTRAL_FACE("=|"),
EXPRESSIONLESS(":|"),
UNAMUSED(":-|"),
SLIGHT_FROWN(":("),
FROWNING2("=("),
CRY(":'("),
SOB(":_("),
FLUSHED(":$"),
ZIPPER_MOUTH(":-#"),
PERSEVERE("<gt>_<lt>"), // >_<
SUNGLASSES("8-)"),
INNOCENT("O:)"),
SMILING_IMP("<gt>:)"), // >:)
RAGE("<gt>:("), // >:(
HUSHED(":-O"),
OPEN_MOUTH(":O"),
SCREAM(":-@"),
SEE_NO_EVIL("X_X"),
DANCER("\\:D/"),
OK_HAND("(Ok)"),
THUMBSUP("(Y)"),
THUMBSDOWN("(N)"),
HEARTS("<lt>3"), // <3
BROKEN_HEART("<lt>/3"), // </3
ZZZ("Zzz"),
FISH("<lt><gt><lt>"), // <><
CAT(":3"),
DOG("=3"),
CRAB("V(;,;)V"),
FORK_AND_KNIFE("--E"),
COOKING("--(o)"),
PARTY_POPPER("@@@"),
EYES("O.O"),
SWEAT(";;"),
PILE_OF_POO("~@~");
private static final Map<String, Emoji> emojiMap;
private final String trigger;
static
{
ImmutableMap.Builder<String, Emoji> builder = new ImmutableMap.Builder<>();
for (final Emoji emoji : values())
{
builder.put(emoji.trigger, emoji);
}
emojiMap = builder.build();
}
Emoji(String trigger)
{
this.trigger = trigger;
}
BufferedImage loadImage()
{
return ImageUtil.getResourceStreamFromClass(getClass(), this.name().toLowerCase() + ".png");
}
static Emoji getEmoji(String trigger)
{
return emojiMap.get(trigger);
}
}

View File

@@ -0,0 +1,193 @@
/*
* Copyright (c) 2019, Lotto <https://github.com/devLotto>
* 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.emojis;
import java.awt.image.BufferedImage;
import java.util.Arrays;
import javax.annotation.Nullable;
import javax.inject.Inject;
import joptsimple.internal.Strings;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client;
import net.runelite.api.GameState;
import net.runelite.api.IndexedSprite;
import net.runelite.api.MessageNode;
import net.runelite.api.Player;
import net.runelite.api.events.ChatMessage;
import net.runelite.api.events.GameStateChanged;
import net.runelite.api.events.OverheadTextChanged;
import net.runelite.client.chat.ChatMessageManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.util.ImageUtil;
@PluginDescriptor(
name = "Emojis",
description = "Replaces common emoticons such as :) with their corresponding emoji in the chat",
enabledByDefault = false
)
@Slf4j
public class EmojiPlugin extends Plugin
{
@Inject
private Client client;
@Inject
private ChatMessageManager chatMessageManager;
private int modIconsStart = -1;
@Override
protected void startUp()
{
loadEmojiIcons();
}
@Subscribe
public void onGameStateChanged(GameStateChanged gameStateChanged)
{
if (gameStateChanged.getGameState() == GameState.LOGGED_IN)
{
loadEmojiIcons();
}
}
private void loadEmojiIcons()
{
final IndexedSprite[] modIcons = client.getModIcons();
if (modIconsStart != -1 || modIcons == null)
{
return;
}
final Emoji[] emojis = Emoji.values();
final IndexedSprite[] newModIcons = Arrays.copyOf(modIcons, modIcons.length + emojis.length);
modIconsStart = modIcons.length;
for (int i = 0; i < emojis.length; i++)
{
final Emoji emoji = emojis[i];
try
{
final BufferedImage image = emoji.loadImage();
final IndexedSprite sprite = ImageUtil.getImageIndexedSprite(image, client);
newModIcons[modIconsStart + i] = sprite;
}
catch (Exception ex)
{
log.warn("Failed to load the sprite for emoji " + emoji, ex);
}
}
log.debug("Adding emoji icons");
client.setModIcons(newModIcons);
}
@Subscribe
public void onChatMessage(ChatMessage chatMessage)
{
if (client.getGameState() != GameState.LOGGED_IN || modIconsStart == -1)
{
return;
}
switch (chatMessage.getType())
{
case PUBLICCHAT:
case MODCHAT:
case FRIENDSCHAT:
case PRIVATECHAT:
case PRIVATECHATOUT:
case MODPRIVATECHAT:
break;
default:
return;
}
final String message = chatMessage.getMessage();
final String updatedMessage = updateMessage(message);
if (updatedMessage == null)
{
return;
}
final MessageNode messageNode = chatMessage.getMessageNode();
messageNode.setRuneLiteFormatMessage(updatedMessage);
chatMessageManager.update(messageNode);
client.refreshChat();
}
@Subscribe
public void onOverheadTextChanged(final OverheadTextChanged event)
{
if (!(event.getActor() instanceof Player))
{
return;
}
final String message = event.getOverheadText();
final String updatedMessage = updateMessage(message);
if (updatedMessage == null)
{
return;
}
event.getActor().setOverheadText(updatedMessage);
}
@Nullable
private String updateMessage(final String message)
{
final String[] messageWords = message.split(" ");
boolean editedMessage = false;
for (int i = 0; i < messageWords.length; i++)
{
final Emoji emoji = Emoji.getEmoji(messageWords[i]);
if (emoji == null)
{
continue;
}
final int emojiId = modIconsStart + emoji.ordinal();
messageWords[i] = "<img=" + emojiId + ">";
editedMessage = true;
}
// If we haven't edited the message any, don't update it.
if (!editedMessage)
{
return null;
}
return Strings.join(messageWords, " ");
}
}

View File

@@ -396,6 +396,11 @@ public class FishingPlugin extends Plugin
}
long timeLeft = TRAWLER_TIME_LIMIT_IN_SECONDS - Duration.between(trawlerStartTime, Instant.now()).getSeconds();
if (timeLeft < 0)
{
timeLeft = 0;
}
int minutes = (int) timeLeft / 60;
int seconds = (int) timeLeft % 60;

View File

@@ -24,7 +24,7 @@
*/
package net.runelite.client.plugins.fishing;
import java.util.HashMap;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
import lombok.Getter;
import net.runelite.api.ItemID;
@@ -160,7 +160,7 @@ enum FishingSpot
FISHING_SPOT_8523);
@Getter
private static final Map<Integer, FishingSpot> SPOTS = new HashMap<>();
private static final Map<Integer, FishingSpot> SPOTS;
private final String name;
private final int fishSpriteId;
@@ -168,15 +168,17 @@ enum FishingSpot
static
{
FishingSpot[] spots = values();
ImmutableMap.Builder<Integer, FishingSpot> builder = new ImmutableMap.Builder<>();
for (FishingSpot spot : spots)
for (FishingSpot spot : values())
{
for (int spotId : spot.getIds())
{
SPOTS.put(spotId, spot);
builder.put(spotId, spot);
}
}
SPOTS = builder.build();
}
FishingSpot(String spot, int fishSpriteId, int... ids)

View File

@@ -24,22 +24,9 @@
*/
package net.runelite.client.plugins.fps;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@Getter
@RequiredArgsConstructor
public enum FpsLimitMode
{
NEVER("Never"),
UNFOCUSED("Unfocused"),
ALWAYS("Always");
private final String name;
@Override
public String toString()
{
return name;
}
NEVER,
UNFOCUSED,
ALWAYS
}

View File

@@ -35,6 +35,7 @@ import net.runelite.api.Actor;
import net.runelite.api.AnimationID;
import static net.runelite.api.AnimationID.*;
import net.runelite.api.Client;
import net.runelite.api.Constants;
import net.runelite.api.GameState;
import net.runelite.api.GraphicID;
import net.runelite.api.Hitsplat;
@@ -64,9 +65,10 @@ import net.runelite.client.plugins.PluginDescriptor;
public class IdleNotifierPlugin extends Plugin
{
// This must be more than 500 client ticks (10 seconds) before you get AFK kicked
private static final int LOGOUT_WARNING_CLIENT_TICKS = ((4 * 60) + 40) * 50;// 4 minutes and 40 seconds
private static final int LOGOUT_WARNING_MILLIS = (4 * 60 + 40) * 1000; // 4 minutes and 40 seconds
private static final int COMBAT_WARNING_MILLIS = 19 * 60 * 1000; // 19 minutes
private static final int COMBAT_WARNING_CLIENT_TICKS = COMBAT_WARNING_MILLIS / 20;
private static final int LOGOUT_WARNING_CLIENT_TICKS = LOGOUT_WARNING_MILLIS / Constants.CLIENT_TICK_LENGTH;
private static final int COMBAT_WARNING_CLIENT_TICKS = COMBAT_WARNING_MILLIS / Constants.CLIENT_TICK_LENGTH;
private static final int HIGHEST_MONSTER_ATTACK_SPEED = 8; // Except Scarab Mage, but they are with other monsters
private static final Duration SIX_HOUR_LOGOUT_WARNING_AFTER_DURATION = Duration.ofMinutes(340);
@@ -204,6 +206,7 @@ public class IdleNotifierPlugin extends Plugin
case HERBLORE_MAKE_TAR:
/* Magic */
case MAGIC_CHARGING_ORBS:
case MAGIC_LUNAR_PLANK_MAKE:
case MAGIC_LUNAR_STRING_JEWELRY:
case MAGIC_MAKE_TABLET:
case MAGIC_ENCHANTING_JEWELRY:

View File

@@ -24,7 +24,7 @@
*/
package net.runelite.client.plugins.implings;
import java.util.HashMap;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
import lombok.AllArgsConstructor;
import lombok.Getter;
@@ -70,14 +70,18 @@ enum Impling
private ImplingType implingType;
private final int npcId;
private static final Map<Integer, Impling> IMPLINGS = new HashMap<>();
private static final Map<Integer, Impling> IMPLINGS;
static
{
ImmutableMap.Builder<Integer, Impling> builder = new ImmutableMap.Builder<>();
for (Impling impling : values())
{
IMPLINGS.put(impling.npcId, impling);
builder.put(impling.npcId, impling);
}
IMPLINGS = builder.build();
}
static Impling findImpling(int npcId)

View File

@@ -37,6 +37,7 @@ import net.runelite.api.ItemContainer;
import net.runelite.client.game.ItemManager;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.components.ComponentOrientation;
import net.runelite.client.ui.overlay.components.ImageComponent;
import net.runelite.client.ui.overlay.components.PanelComponent;
@@ -58,7 +59,7 @@ class InventoryViewerOverlay extends Overlay
setPosition(OverlayPosition.BOTTOM_RIGHT);
panelComponent.setWrapping(4);
panelComponent.setGap(new Point(6, 4));
panelComponent.setOrientation(PanelComponent.Orientation.HORIZONTAL);
panelComponent.setOrientation(ComponentOrientation.HORIZONTAL);
this.itemManager = itemManager;
this.client = client;
}

View File

@@ -24,13 +24,19 @@
*/
package net.runelite.client.plugins.itemcharges;
import java.util.HashMap;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
import javax.annotation.Nullable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import static net.runelite.api.ItemID.*;
import static net.runelite.client.plugins.itemcharges.ItemChargeType.*;
import static net.runelite.client.plugins.itemcharges.ItemChargeType.ABYSSAL_BRACELET;
import static net.runelite.client.plugins.itemcharges.ItemChargeType.BELLOWS;
import static net.runelite.client.plugins.itemcharges.ItemChargeType.FUNGICIDE_SPRAY;
import static net.runelite.client.plugins.itemcharges.ItemChargeType.IMPBOX;
import static net.runelite.client.plugins.itemcharges.ItemChargeType.TELEPORT;
import static net.runelite.client.plugins.itemcharges.ItemChargeType.WATERCAN;
import static net.runelite.client.plugins.itemcharges.ItemChargeType.WATERSKIN;
@AllArgsConstructor
@Getter
@@ -168,14 +174,18 @@ enum ItemWithCharge
private final int id;
private final int charges;
private static final Map<Integer, ItemWithCharge> ID_MAP = new HashMap<>();
private static final Map<Integer, ItemWithCharge> ID_MAP;
static
{
ImmutableMap.Builder<Integer, ItemWithCharge> builder = new ImmutableMap.Builder<>();
for (ItemWithCharge itemCharge : values())
{
ID_MAP.put(itemCharge.getId(), itemCharge);
builder.put(itemCharge.getId(), itemCharge);
}
ID_MAP = builder.build();
}
@Nullable

View File

@@ -24,7 +24,7 @@
*/
package net.runelite.client.plugins.itemidentification;
import java.util.HashMap;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
import net.runelite.api.ItemID;
@@ -100,17 +100,21 @@ enum ItemIdentification
this.itemIDs = ids;
}
private static final Map<Integer, ItemIdentification> itemIdentifications = new HashMap<>();
private static final Map<Integer, ItemIdentification> itemIdentifications;
static
{
ImmutableMap.Builder<Integer, ItemIdentification> builder = new ImmutableMap.Builder<>();
for (ItemIdentification i : values())
{
for (int id : i.itemIDs)
{
itemIdentifications.put(id, i);
builder.put(id, i);
}
}
itemIdentifications = builder.build();
}
static ItemIdentification get(int id)

View File

@@ -24,21 +24,8 @@
*/
package net.runelite.client.plugins.itemidentification;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@Getter
@RequiredArgsConstructor
public enum ItemIdentificationMode
{
SHORT("Short"),
MEDIUM("Medium");
private final String type;
@Override
public String toString()
{
return type;
}
SHORT,
MEDIUM
}

View File

@@ -59,22 +59,22 @@ public class ItemStatChanges
add(food(3), SHRIMPS, COOKED_MEAT, COOKED_CHICKEN, ROE, CHOCOLATE_BAR);
add(food(4), SARDINE, CAKE, _23_CAKE, SLICE_OF_CAKE, CHOCOLATEY_MILK, BAKED_POTATO, EDIBLE_SEAWEED, MOONLIGHT_MEAD);
add(food(5), BREAD, HERRING, CHOCOLATE_CAKE, _23_CHOCOLATE_CAKE, CHOCOLATE_SLICE, COOKED_RABBIT, CHILLI_CON_CARNE,
FRIED_MUSHROOMS, FRIED_ONIONS, REDBERRY_PIE, HALF_A_REDBERRY_PIE, CAVIAR);
FRIED_MUSHROOMS, FRIED_ONIONS, REDBERRY_PIE, HALF_A_REDBERRY_PIE, CAVIAR, PYSK_FISH_0);
add(food(6), CHOCICE, MACKEREL, MEAT_PIE, HALF_A_MEAT_PIE, GUANIC_BAT_0, ROAST_BIRD_MEAT,
SQUARE_SANDWICH, ROLL, BAGUETTE, TRIANGLE_SANDWICH, GIANT_CARP);
add(food(7), TROUT, COD, PLAIN_PIZZA, _12_PLAIN_PIZZA, APPLE_PIE, HALF_AN_APPLE_PIE, ROAST_RABBIT,
PREMADE_CH_CRUNCH, CHOCCHIP_CRUNCHIES, PREMADE_SY_CRUNCH, SPICY_CRUNCHIES);
add(food(8), PIKE, ROAST_BEAST_MEAT, MEAT_PIZZA, _12_MEAT_PIZZA, PREMADE_WM_CRUN, WORM_CRUNCHIES, PREMADE_TD_CRUNCH,
TOAD_CRUNCHIES, EGG_AND_TOMATO, LECKISH_FISH_2, PRAEL_BAT_1, PEACH);
TOAD_CRUNCHIES, EGG_AND_TOMATO, PRAEL_BAT_1, PEACH, SUPHI_FISH_1);
add(food(9), PREMADE_P_PUNCH, PINEAPPLE_PUNCH, PREMADE_FR_BLAST, FRUIT_BLAST, SALMON, ANCHOVY_PIZZA,
_12_ANCHOVY_PIZZA);
add(food(10), TUNA, COOKED_CRAB_MEAT, CHOPPED_TUNA, COOKED_CHOMPY, FIELD_RATION);
add(food(11), RAINBOW_FISH, STEW, PINEAPPLE_PIZZA, _12_PINEAPPLE_PIZZA, COOKED_FISHCAKE,
PREMADE_VEG_BATTA, VEGETABLE_BATTA, PREMADE_WM_BATTA, WORM_BATTA, PREMADE_TD_BATTA, TOAD_BATTA, PREMADE_CT_BATTA,
CHEESETOM_BATTA, PREMADE_FRT_BATTA, FRUIT_BATTA, MUSHROOM__ONION, GIRAL_BAT_2, LAVA_EEL);
CHEESETOM_BATTA, PREMADE_FRT_BATTA, FRUIT_BATTA, MUSHROOM__ONION, GIRAL_BAT_2, LAVA_EEL, LECKISH_FISH_2);
add(food(12), LOBSTER, PREMADE_WORM_HOLE, WORM_HOLE, PREMADE_VEG_BALL, VEG_BALL);
add(food(13), BASS, TUNA_AND_CORN);
add(food(14), POTATO_WITH_BUTTER, CHILLI_POTATO, SWORDFISH, PHLUXIA_BAT_3, PUMPKIN, EASTER_EGG);
add(food(14), POTATO_WITH_BUTTER, CHILLI_POTATO, SWORDFISH, PHLUXIA_BAT_3, PUMPKIN, EASTER_EGG, BRAWK_FISH_3);
add(food(15), PREMADE_TTL, TANGLED_TOADS_LEGS, PREMADE_CHOC_BOMB, CHOCOLATE_BOMB, COOKED_JUBBLY);
add(food(16), MONKFISH, POTATO_WITH_CHEESE, EGG_POTATO);
add(food(17), MYCIL_FISH_4, KRYKET_BAT_4);

View File

@@ -36,6 +36,7 @@ import java.time.Instant;
import java.util.Locale;
import javax.inject.Inject;
import net.runelite.api.Client;
import net.runelite.api.Constants;
import net.runelite.api.NPC;
import net.runelite.api.NPCComposition;
import net.runelite.api.Perspective;
@@ -54,9 +55,6 @@ public class NpcSceneOverlay extends Overlay
// a dark background
private static final Color TEXT_COLOR = Color.WHITE;
// Estimated time of a game tick in seconds
private static final double ESTIMATED_TICK_LENGTH = 0.6;
private static final NumberFormat TIME_LEFT_FORMATTER = DecimalFormat.getInstance(Locale.US);
static
@@ -123,7 +121,7 @@ public class NpcSceneOverlay extends Overlay
}
final Instant now = Instant.now();
final double baseTick = ((npc.getDiedOnTick() + npc.getRespawnTime()) - client.getTickCount()) * ESTIMATED_TICK_LENGTH;
final double baseTick = ((npc.getDiedOnTick() + npc.getRespawnTime()) - client.getTickCount()) * (Constants.GAME_TICK_LENGTH / 1000.0);
final double sinceLast = (now.toEpochMilli() - plugin.getLastTickUpdate().toEpochMilli()) / 1000.0;
final double timeLeft = Math.max(0.0, baseTick - sinceLast);
final String timeLeftStr = TIME_LEFT_FORMATTER.format(timeLeft);

View File

@@ -26,21 +26,8 @@ package net.runelite.client.plugins.npchighlight;
public enum RenderStyle
{
OFF("Off"),
TILE("Tile"),
HULL("Hull"),
SOUTH_WEST_TILE("South West Tile");
private final String name;
RenderStyle(String name)
{
this.name = name;
}
@Override
public String toString()
{
return name;
}
OFF,
TILE,
HULL,
SOUTH_WEST_TILE
}

View File

@@ -37,6 +37,7 @@ import java.util.Map;
import java.util.UUID;
import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.inject.Named;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.ChatMessageType;
@@ -48,6 +49,7 @@ import net.runelite.api.Skill;
import net.runelite.api.SoundEffectID;
import net.runelite.api.Tile;
import net.runelite.api.coords.WorldPoint;
import net.runelite.api.events.CommandExecuted;
import net.runelite.api.events.FocusChanged;
import net.runelite.api.events.GameTick;
import net.runelite.api.events.MenuOptionClicked;
@@ -120,6 +122,10 @@ public class PartyPlugin extends Plugin implements KeyListener
@Inject
private ChatMessageManager chatMessageManager;
@Inject
@Named("developerMode")
boolean developerMode;
@Getter
private final Map<UUID, PartyData> partyDataMap = Collections.synchronizedMap(new HashMap<>());
@@ -448,6 +454,23 @@ public class PartyPlugin extends Plugin implements KeyListener
worldMapManager.removeIf(PartyWorldMapPoint.class::isInstance);
}
@Subscribe
public void onCommandExecuted(CommandExecuted commandExecuted)
{
if (!developerMode || !commandExecuted.getCommand().equals("partyinfo"))
{
return;
}
chatMessageManager.queue(QueuedMessage.builder().type(ChatMessageType.GAMEMESSAGE).value("Party " + party.getPartyId()).build());
chatMessageManager.queue(QueuedMessage.builder().type(ChatMessageType.GAMEMESSAGE).value("Local Party " + party.getLocalPartyId()).build());
chatMessageManager.queue(QueuedMessage.builder().type(ChatMessageType.GAMEMESSAGE).value("Local ID " + party.getLocalMember().getMemberId()).build());
for (PartyMember partyMember : party.getMembers())
{
chatMessageManager.queue(QueuedMessage.builder().type(ChatMessageType.GAMEMESSAGE).value(" " + partyMember.getName() + " " + partyMember.getMemberId()).build());
}
}
@Nullable
PartyData getPartyData(final UUID uuid)
{

View File

@@ -24,12 +24,22 @@
*/
package net.runelite.client.plugins.poh;
import com.google.common.collect.ImmutableMap;
import java.awt.image.BufferedImage;
import java.util.HashMap;
import java.util.Map;
import lombok.Getter;
import static net.runelite.api.NullObjectID.NULL_13615;
import static net.runelite.api.NullObjectID.NULL_13618;
import static net.runelite.api.NullObjectID.NULL_13620;
import static net.runelite.api.NullObjectID.NULL_13622;
import static net.runelite.api.NullObjectID.NULL_13625;
import static net.runelite.api.NullObjectID.NULL_13627;
import static net.runelite.api.NullObjectID.NULL_13629;
import static net.runelite.api.NullObjectID.NULL_13632;
import static net.runelite.api.NullObjectID.NULL_13634;
import static net.runelite.api.NullObjectID.NULL_29228;
import static net.runelite.api.NullObjectID.NULL_29229;
import static net.runelite.api.ObjectID.*;
import static net.runelite.api.NullObjectID.*;
import net.runelite.client.util.ImageUtil;
public enum PohIcons
@@ -56,7 +66,7 @@ public enum PohIcons
ALTAR("altar",
ALTAR_13179, ALTAR_13180, ALTAR_13181, ALTAR_13182, ALTAR_13183, ALTAR_13184, ALTAR_13185, ALTAR_13186,
ALTAR_13187, ALTAR_13188, ALTAR_13189, ALTAR_13190, ALTAR_13191, ALTAR_13192, ALTAR_13193, ALTAR_13194,
ALTAR_13194, ALTAR_13196, ALTAR_13197, ALTAR_13198, ALTAR_13199
ALTAR_13196, ALTAR_13197, ALTAR_13198, ALTAR_13199
),
POOLS("pool", POOL_OF_RESTORATION, POOL_OF_REVITALISATION, POOL_OF_REJUVENATION, FANCY_REJUVENATION_POOL, ORNATE_REJUVENATION_POOL),
GLORY("glory", AMULET_OF_GLORY),
@@ -83,7 +93,7 @@ public enum PohIcons
DIGSITE_PENDANT, DIGSITE_PENDANT_33417, DIGSITE_PENDANT_33418, DIGSITE_PENDANT_33420
);
private static final Map<Integer, PohIcons> minimapIcons = new HashMap<>();
private static final Map<Integer, PohIcons> minimapIcons;
@Getter
private final String imageResource;
@@ -94,15 +104,17 @@ public enum PohIcons
static
{
PohIcons[] icons = values();
ImmutableMap.Builder<Integer, PohIcons> builder = new ImmutableMap.Builder<>();
for (PohIcons icon : icons)
for (PohIcons icon : values())
{
for (Integer spotId : icon.getIds())
{
minimapIcons.put(spotId, icon);
builder.put(spotId, icon);
}
}
minimapIcons = builder.build();
}
PohIcons(String imageResource, int... ids)

View File

@@ -39,6 +39,7 @@ import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Actor;
import net.runelite.api.AnimationID;
import net.runelite.api.Client;
import net.runelite.api.Constants;
import net.runelite.api.DecorativeObject;
import net.runelite.api.GameObject;
import net.runelite.api.GameState;
@@ -74,7 +75,6 @@ public class PohPlugin extends Plugin
{
static final Set<Integer> BURNER_UNLIT = Sets.newHashSet(ObjectID.INCENSE_BURNER, ObjectID.INCENSE_BURNER_13210, ObjectID.INCENSE_BURNER_13212);
static final Set<Integer> BURNER_LIT = Sets.newHashSet(ObjectID.INCENSE_BURNER_13209, ObjectID.INCENSE_BURNER_13211, ObjectID.INCENSE_BURNER_13213);
private static final double ESTIMATED_TICK_LENGTH = 0.6;
@Getter(AccessLevel.PACKAGE)
private final Map<TileObject, Tile> pohObjects = new HashMap<>();
@@ -243,7 +243,8 @@ public class PohPlugin extends Plugin
private static void updateBurner(IncenseBurner incenseBurner, int fmLevel)
{
incenseBurner.setCountdownTimer((200 + fmLevel) * ESTIMATED_TICK_LENGTH);
incenseBurner.setRandomTimer(fmLevel * ESTIMATED_TICK_LENGTH);
final double tickLengthSeconds = Constants.GAME_TICK_LENGTH / 1000.0;
incenseBurner.setCountdownTimer((200 + fmLevel) * tickLengthSeconds);
incenseBurner.setRandomTimer(fmLevel * tickLengthSeconds);
}
}

View File

@@ -35,6 +35,7 @@ import javax.inject.Inject;
import lombok.AccessLevel;
import lombok.Setter;
import net.runelite.api.Client;
import net.runelite.api.Constants;
import net.runelite.api.Point;
import net.runelite.api.Prayer;
import net.runelite.api.Skill;
@@ -50,7 +51,7 @@ import org.apache.commons.lang3.StringUtils;
class PrayerDoseOverlay extends Overlay
{
private static final float PULSE_TIME = 1200f;
private static final float PULSE_TIME = 2f * Constants.GAME_TICK_LENGTH;
private static final Color START_COLOR = new Color(0, 255, 255);
private static final Color END_COLOR = new Color(0, 92, 92);

View File

@@ -26,23 +26,10 @@
package net.runelite.client.plugins.prayer;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@Getter
@RequiredArgsConstructor
public enum PrayerFlickLocation
{
NONE("Off"),
PRAYER_ORB("Prayer Orb"),
PRAYER_BAR("Prayer Bar"),
BOTH("Both");
private final String name;
@Override
public String toString()
{
return name;
}
NONE,
PRAYER_ORB,
PRAYER_BAR,
BOTH
}

View File

@@ -24,7 +24,7 @@
*/
package net.runelite.client.plugins.prayer;
import java.util.HashMap;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
import lombok.AllArgsConstructor;
import lombok.Getter;
@@ -453,17 +453,19 @@ enum PrayerItems
DAMAGED_BOOK_3841(ItemID.DAMAGED_BOOK_3841, 5),
FALADOR_SHIELD_4(ItemID.FALADOR_SHIELD_4, 5);
private static final Map<Integer, Integer> prayerBonuses = new HashMap<>();
private static final Map<Integer, Integer> prayerBonuses;
private final int itemId;
private final int prayerBonus;
static
{
ImmutableMap.Builder<Integer, Integer> builder = new ImmutableMap.Builder<>();
for (PrayerItems item : values())
{
prayerBonuses.put(item.getItemId(), item.getPrayerBonus());
builder.put(item.getItemId(), item.getPrayerBonus());
}
prayerBonuses = builder.build();
}
static int getItemPrayerBonus(int itemId)

View File

@@ -32,6 +32,7 @@ import javax.inject.Inject;
import lombok.AccessLevel;
import lombok.Getter;
import net.runelite.api.Client;
import net.runelite.api.Constants;
import net.runelite.api.InventoryID;
import net.runelite.api.Item;
import net.runelite.api.ItemContainer;
@@ -268,7 +269,7 @@ public class PrayerPlugin extends Plugin
{
long timeSinceLastTick = Duration.between(startOfLastTick, Instant.now()).toMillis();
float tickProgress = (timeSinceLastTick % 600) / 600f;
float tickProgress = (timeSinceLastTick % Constants.GAME_TICK_LENGTH) / (float) Constants.GAME_TICK_LENGTH;
return tickProgress * Math.PI;
}

View File

@@ -24,7 +24,7 @@
*/
package net.runelite.client.plugins.prayer;
import java.util.HashMap;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
import net.runelite.api.ItemID;
@@ -36,7 +36,7 @@ enum PrayerRestoreType
HOLYWRENCH(ItemID.PRAYER_CAPE, ItemID.PRAYER_CAPET, ItemID.PRAYER_CAPE_10643, ItemID.MAX_CAPE, ItemID.MAX_CAPE_13282,
ItemID.MAX_CAPE_13342, ItemID.HOLY_WRENCH, ItemID.RING_OF_THE_GODS_I);
private static final Map<Integer, PrayerRestoreType> prayerRestores = new HashMap<>();
private static final Map<Integer, PrayerRestoreType> prayerRestores;
private final int[] items;
@@ -47,13 +47,15 @@ enum PrayerRestoreType
static
{
ImmutableMap.Builder<Integer, PrayerRestoreType> builder = new ImmutableMap.Builder<>();
for (PrayerRestoreType prayerRestoreType : values())
{
for (int itemId : prayerRestoreType.items)
{
prayerRestores.put(itemId, prayerRestoreType);
builder.put(itemId, prayerRestoreType);
}
}
prayerRestores = builder.build();
}
static PrayerRestoreType getType(final int itemId)

View File

@@ -25,7 +25,7 @@
*/
package net.runelite.client.plugins.puzzlesolver;
import java.util.HashMap;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@@ -135,14 +135,18 @@ enum VarrockMuseumAnswer
LEECH_5("What is special about Morytanian leeches?", "They attack by jumping."),
LEECH_6("How does a leech change when it feeds?", "It doubles in size.");
private static final Map<String, String> MATCHES = new HashMap<>();
private static final Map<String, String> MATCHES;
static
{
ImmutableMap.Builder<String, String> builder = new ImmutableMap.Builder<>();
for (VarrockMuseumAnswer varrockMuseumAnswer : VarrockMuseumAnswer.values())
{
MATCHES.put(varrockMuseumAnswer.question, varrockMuseumAnswer.answer);
builder.put(varrockMuseumAnswer.question, varrockMuseumAnswer.answer);
}
MATCHES = builder.build();
}
private final String question;

View File

@@ -57,4 +57,14 @@ public interface RegenMeterConfig extends Config
{
return false;
}
@ConfigItem(
keyName = "notifyBeforeHpRegenDuration",
name = "Hitpoint Regen Notification (seconds)",
description = "Notify approximately when your next hitpoint is about to regen. A value of 0 will disable notification."
)
default int getNotifyBeforeHpRegenSeconds()
{
return 0;
}
}

View File

@@ -1,5 +1,6 @@
/*
* Copyright (c) 2018 Abex
* Copyright (c) 2019, Sean Dewar <https://github.com/seandewar>
* Copyright (c) 2018, Abex
* Copyright (c) 2018, Zimaya <https://github.com/Zimaya>
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* All rights reserved.
@@ -30,6 +31,7 @@ import com.google.inject.Provides;
import javax.inject.Inject;
import lombok.Getter;
import net.runelite.api.Client;
import net.runelite.api.Constants;
import net.runelite.api.GameState;
import net.runelite.api.Prayer;
import net.runelite.api.Skill;
@@ -37,6 +39,7 @@ import net.runelite.api.VarPlayer;
import net.runelite.api.events.GameStateChanged;
import net.runelite.api.events.GameTick;
import net.runelite.api.events.VarbitChanged;
import net.runelite.client.Notifier;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.plugins.Plugin;
@@ -46,7 +49,7 @@ import net.runelite.client.ui.overlay.OverlayManager;
@PluginDescriptor(
name = "Regeneration Meter",
description = "Track and show the hitpoints and special attack regeneration timers",
tags = {"combat", "health", "hitpoints", "special", "attack", "overlay"}
tags = {"combat", "health", "hitpoints", "special", "attack", "overlay", "notifications"}
)
public class RegenMeterPlugin extends Plugin
{
@@ -59,6 +62,9 @@ public class RegenMeterPlugin extends Plugin
@Inject
private OverlayManager overlayManager;
@Inject
private Notifier notifier;
@Inject
private RegenMeterOverlay overlay;
@@ -149,5 +155,18 @@ public class RegenMeterPlugin extends Plugin
// Show it going down
hitpointsPercentage = 1 - hitpointsPercentage;
}
if (config.getNotifyBeforeHpRegenSeconds() > 0 && currentHP < maxHP && shouldNotifyHpRegenThisTick(ticksPerHPRegen))
{
notifier.notify("[" + client.getLocalPlayer().getName() + "] regenerates their next hitpoint soon!");
}
}
private boolean shouldNotifyHpRegenThisTick(int ticksPerHPRegen)
{
// if the configured duration lies between two ticks, choose the earlier tick
final int ticksBeforeHPRegen = ticksPerHPRegen - ticksSinceHPRegen;
final int notifyTick = (int) Math.ceil(config.getNotifyBeforeHpRegenSeconds() * 1000d / Constants.GAME_TICK_LENGTH);
return ticksBeforeHPRegen == notifyTick;
}
}

View File

@@ -24,7 +24,7 @@
*/
package net.runelite.client.plugins.runecraft;
import java.util.HashMap;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
import lombok.Getter;
import static net.runelite.api.ItemID.AIR_RUNE;
@@ -64,14 +64,18 @@ public enum AbyssRifts
@Getter
private final int itemId;
private static final Map<Integer, AbyssRifts> rifts = new HashMap<>();
private static final Map<Integer, AbyssRifts> rifts;
static
{
ImmutableMap.Builder<Integer, AbyssRifts> builder = new ImmutableMap.Builder<>();
for (AbyssRifts s : values())
{
rifts.put(s.getObjectId(), s);
builder.put(s.getObjectId(), s);
}
rifts = builder.build();
}
AbyssRifts(int objectId, int itemId)

View File

@@ -28,6 +28,7 @@ import com.google.common.collect.ImmutableSet;
import com.google.inject.Provides;
import javax.inject.Inject;
import net.runelite.api.Client;
import net.runelite.api.Constants;
import net.runelite.api.EquipmentInventorySlot;
import net.runelite.api.InventoryID;
import net.runelite.api.Item;
@@ -171,7 +172,7 @@ public class RunEnergyPlugin extends Plugin
String getEstimatedRunTimeRemaining(boolean inSeconds)
{
// Calculate the amount of energy lost every 2 ticks (0.6 seconds).
// Calculate the amount of energy lost every tick.
// Negative weight has the same depletion effect as 0 kg.
final int effectiveWeight = Math.max(client.getWeight(), 0);
double lossRate = (Math.min(effectiveWeight, 64) / 100.0) + 0.64;
@@ -182,7 +183,7 @@ public class RunEnergyPlugin extends Plugin
}
// Calculate the number of seconds left
final double secondsLeft = (client.getEnergy() * 0.6) / lossRate;
final double secondsLeft = (client.getEnergy() * Constants.GAME_TICK_LENGTH) / (lossRate * 1000.0);
// Return the text
if (inSeconds)

View File

@@ -25,8 +25,8 @@
package net.runelite.client.plugins.runepouch;
import com.google.common.collect.ImmutableMap;
import java.awt.image.BufferedImage;
import java.util.HashMap;
import java.util.Map;
import lombok.Getter;
import lombok.Setter;
@@ -85,14 +85,16 @@ public enum Runes
@Setter
private BufferedImage image;
private static final Map<Integer, Runes> runes = new HashMap<>();
private static final Map<Integer, Runes> runes;
static
{
ImmutableMap.Builder<Integer, Runes> builder = new ImmutableMap.Builder<>();
for (Runes rune : values())
{
runes.put(rune.getId(), rune);
builder.put(rune.getId(), rune);
}
runes = builder.build();
}
Runes(int id, int itemId)

View File

@@ -24,22 +24,9 @@
*/
package net.runelite.client.plugins.runepouch.config;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@Getter
@RequiredArgsConstructor
public enum RunePouchOverlayMode
{
INVENTORY("Inventory"),
MOUSE_HOVER("Mouse hover"),
BOTH("Both");
private final String name;
@Override
public String toString()
{
return name;
}
INVENTORY,
MOUSE_HOVER,
BOTH
}

View File

@@ -26,7 +26,7 @@
package net.runelite.client.plugins.slayer;
import com.google.common.base.Preconditions;
import java.util.HashMap;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
import lombok.Getter;
import net.runelite.api.ItemID;
@@ -174,7 +174,7 @@ enum Task
ZUK("TzKal-Zuk", ItemID.TZREKZUK);
//</editor-fold>
private static final Map<String, Task> tasks = new HashMap<>();
private static final Map<String, Task> tasks;
private final String name;
private final int itemSpriteId;
@@ -184,10 +184,14 @@ enum Task
static
{
ImmutableMap.Builder<String, Task> builder = new ImmutableMap.Builder<>();
for (Task task : values())
{
tasks.put(task.getName().toLowerCase(), task);
builder.put(task.getName().toLowerCase(), task);
}
tasks = builder.build();
}
Task(String name, int itemSpriteId, String... targetNames)

View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 2019, Stephen <stepzhu@umich.edu>
* 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.smelting;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup("smelting")
public interface SmeltingConfig extends Config
{
@ConfigItem(
position = 1,
keyName = "statTimeout",
name = "Reset stats (minutes)",
description = "The time it takes for the current smelting session to be reset"
)
default int statTimeout()
{
return 5;
}
}

View File

@@ -0,0 +1,135 @@
/*
* Copyright (c) 2019, Stephen <stepzhu@umich.edu>
* 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.smelting;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.time.Duration;
import java.time.Instant;
import javax.inject.Inject;
import static net.runelite.api.AnimationID.SMITHING_CANNONBALL;
import static net.runelite.api.AnimationID.SMITHING_SMELTING;
import net.runelite.api.Client;
import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG;
import net.runelite.api.Skill;
import net.runelite.client.plugins.xptracker.XpTrackerService;
import net.runelite.client.ui.overlay.Overlay;
import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE;
import net.runelite.client.ui.overlay.OverlayMenuEntry;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.components.LineComponent;
import net.runelite.client.ui.overlay.components.PanelComponent;
import net.runelite.client.ui.overlay.components.TitleComponent;
class SmeltingOverlay extends Overlay
{
private static final int SMELT_TIMEOUT = 5;
private final Client client;
private final SmeltingPlugin plugin;
private final XpTrackerService xpTrackerService;
private final PanelComponent panelComponent = new PanelComponent();
@Inject
SmeltingOverlay(Client client, SmeltingPlugin plugin, XpTrackerService xpTrackerService)
{
super(plugin);
this.client = client;
this.plugin = plugin;
this.xpTrackerService = xpTrackerService;
setPosition(OverlayPosition.TOP_LEFT);
getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "Smelting overlay"));
}
@Override
public Dimension render(Graphics2D graphics)
{
SmeltingSession session = plugin.getSession();
if (session == null)
{
return null;
}
panelComponent.getChildren().clear();
if (isSmelting() || Duration.between(session.getLastItemSmelted(), Instant.now()).getSeconds() < SMELT_TIMEOUT)
{
panelComponent.getChildren().add(TitleComponent.builder()
.text("Smelting")
.color(Color.GREEN)
.build());
}
else
{
panelComponent.getChildren().add(TitleComponent.builder()
.text("NOT smelting")
.color(Color.RED)
.build());
}
int actions = xpTrackerService.getActions(Skill.SMITHING);
if (actions > 0)
{
if (plugin.getSession().getBarsSmelted() > 0)
{
panelComponent.getChildren().add(LineComponent.builder()
.left("Bars:")
.right(Integer.toString(session.getBarsSmelted()))
.build());
}
if (plugin.getSession().getCannonBallsSmelted() > 0)
{
panelComponent.getChildren().add(LineComponent.builder()
.left("Cannonballs:")
.right(Integer.toString(session.getCannonBallsSmelted()))
.build());
}
if (actions > 2)
{
panelComponent.getChildren().add(LineComponent.builder()
.left("Actions/hr:")
.right(Integer.toString(xpTrackerService.getActionsHr(Skill.SMITHING)))
.build());
}
}
return panelComponent.render(graphics);
}
private boolean isSmelting()
{
switch (client.getLocalPlayer().getAnimation())
{
case SMITHING_SMELTING:
case SMITHING_CANNONBALL:
return true;
default:
return false;
}
}
}

View File

@@ -0,0 +1,125 @@
/*
* Copyright (c) 2019, Stephen <stepzhu@umich.edu>
* 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.smelting;
import com.google.inject.Provides;
import java.time.Duration;
import java.time.Instant;
import javax.inject.Inject;
import lombok.AccessLevel;
import lombok.Getter;
import net.runelite.api.ChatMessageType;
import net.runelite.api.events.ChatMessage;
import net.runelite.api.events.GameTick;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDependency;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.plugins.xptracker.XpTrackerPlugin;
import net.runelite.client.ui.overlay.OverlayManager;
@PluginDescriptor(
name = "Smelting",
description = "Show Smelting stats",
tags = {"overlay", "skilling"}
)
@PluginDependency(XpTrackerPlugin.class)
public class SmeltingPlugin extends Plugin
{
@Inject
private SmeltingConfig config;
@Inject
private SmeltingOverlay overlay;
@Inject
private OverlayManager overlayManager;
@Getter(AccessLevel.PACKAGE)
private SmeltingSession session;
@Provides
SmeltingConfig getConfig(ConfigManager configManager)
{
return configManager.getConfig(SmeltingConfig.class);
}
@Override
protected void startUp()
{
session = null;
overlayManager.add(overlay);
}
@Override
protected void shutDown()
{
overlayManager.remove(overlay);
session = null;
}
@Subscribe
public void onChatMessage(ChatMessage event)
{
if (event.getType() != ChatMessageType.SPAM)
{
return;
}
if (event.getMessage().startsWith("You retrieve a bar of"))
{
if (session == null)
{
session = new SmeltingSession();
}
session.increaseBarsSmelted();
}
else if (event.getMessage().startsWith("You remove the cannonballs from the mould"))
{
if (session == null)
{
session = new SmeltingSession();
}
session.increaseCannonBallsSmelted();
}
}
@Subscribe
public void onGameTick(GameTick event)
{
if (session != null)
{
final Duration statTimeout = Duration.ofMinutes(config.statTimeout());
final Duration sinceCaught = Duration.between(session.getLastItemSmelted(), Instant.now());
if (sinceCaught.compareTo(statTimeout) >= 0)
{
session = null;
}
}
}
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (c) 2019, Stephen <stepzhu@umich.edu>
* 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.smelting;
import java.time.Instant;
import lombok.AccessLevel;
import lombok.Getter;
class SmeltingSession
{
@Getter(AccessLevel.PACKAGE)
private int barsSmelted;
@Getter(AccessLevel.PACKAGE)
private int cannonBallsSmelted;
@Getter(AccessLevel.PACKAGE)
private Instant lastItemSmelted;
void increaseBarsSmelted()
{
barsSmelted++;
lastItemSmelted = Instant.now();
}
void increaseCannonBallsSmelted()
{
cannonBallsSmelted += 4;
lastItemSmelted = Instant.now();
}
}

View File

@@ -36,6 +36,7 @@ import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE;
import net.runelite.client.ui.overlay.OverlayMenuEntry;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.OverlayPriority;
import net.runelite.client.ui.overlay.components.ComponentOrientation;
import net.runelite.client.ui.overlay.components.ImageComponent;
import net.runelite.client.ui.overlay.components.PanelComponent;
@@ -55,7 +56,7 @@ public class TeamCapesOverlay extends Overlay
this.plugin = plugin;
this.config = config;
this.manager = manager;
panelComponent.setOrientation(PanelComponent.Orientation.HORIZONTAL);
panelComponent.setOrientation(ComponentOrientation.HORIZONTAL);
panelComponent.setWrapping(4);
getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "Teamcapes overlay"));
}

View File

@@ -48,7 +48,7 @@ enum GameTimer
HALFTB(SpriteID.SPELL_TELE_BLOCK, GameTimerImageType.SPRITE, "Half Teleblock", 150, ChronoUnit.SECONDS, true),
DMM_FULLTB(SpriteID.SPELL_TELE_BLOCK, GameTimerImageType.SPRITE, "Deadman Mode Full Teleblock", 150, ChronoUnit.SECONDS, true),
DMM_HALFTB(SpriteID.SPELL_TELE_BLOCK, GameTimerImageType.SPRITE, "Deadman Mode Half Teleblock", 75, ChronoUnit.SECONDS, true),
ANTIVENOMPLUS(ItemID.ANTIVENOM4_12913, GameTimerImageType.ITEM, "Anti-venom+", 3, ChronoUnit.MINUTES, true),
ANTIVENOMPLUS(ItemID.ANTIVENOM4_12913, GameTimerImageType.ITEM, "Anti-venom+", 3, ChronoUnit.MINUTES),
ANTIVENOMPLUS_ANTIPOSION(ItemID.SUPERANTIPOISON4, GameTimerImageType.ITEM, "Anti-venom+ Antipoison", 15, ChronoUnit.MINUTES, 3),
SUPERANTIFIRE(ItemID.SUPER_ANTIFIRE_POTION4, GameTimerImageType.ITEM, "Super antifire", 3, ChronoUnit.MINUTES),
ANTIDOTEPLUSPLUS(ItemID.ANTIDOTE4_5952, GameTimerImageType.ITEM, "Antidote++", 12, ChronoUnit.MINUTES),
@@ -65,10 +65,10 @@ enum GameTimer
IMBUEDHEART(ItemID.IMBUED_HEART, GameTimerImageType.ITEM, "Imbued heart", GraphicID.IMBUED_HEART, 420, ChronoUnit.SECONDS),
VENGEANCE(SpriteID.SPELL_VENGEANCE, GameTimerImageType.SPRITE, "Vengeance", 30, ChronoUnit.SECONDS),
ANTIDOTEPLUS(ItemID.ANTIDOTE4, GameTimerImageType.ITEM, "Antidote+", 518, ChronoUnit.SECONDS),
ANTIVENOM(ItemID.ANTIVENOM4, GameTimerImageType.ITEM, "Anti-venom", 1, ChronoUnit.MINUTES, true),
ANTIVENOM(ItemID.ANTIVENOM4, GameTimerImageType.ITEM, "Anti-venom", 1, ChronoUnit.MINUTES),
ANTIVENOM_ANTIPOISON(ItemID.ANTIPOISON4, GameTimerImageType.ITEM, "Anti-venom Antipoison", 12, ChronoUnit.MINUTES, 1),
EXSUPERANTIFIRE(ItemID.EXTENDED_SUPER_ANTIFIRE4, GameTimerImageType.ITEM, "Extended Super AntiFire", 6, ChronoUnit.MINUTES),
SANFEW(ItemID.SANFEW_SERUM4, GameTimerImageType.ITEM, "Sanfew serum", 6, ChronoUnit.MINUTES, true),
SANFEW(ItemID.SANFEW_SERUM4, GameTimerImageType.ITEM, "Sanfew serum", 6, ChronoUnit.MINUTES),
OVERLOAD_RAID(ItemID.OVERLOAD_4_20996, GameTimerImageType.ITEM, "Overload", 5, ChronoUnit.MINUTES, true),
PRAYER_ENHANCE(ItemID.PRAYER_ENHANCE_4, GameTimerImageType.ITEM, "Prayer enhance", 290, ChronoUnit.SECONDS, true),
GOD_WARS_ALTAR(SpriteID.SKILL_PRAYER, GameTimerImageType.SPRITE, "God wars altar", 10, ChronoUnit.MINUTES),

View File

@@ -24,7 +24,7 @@
*/
package net.runelite.client.plugins.tithefarm;
import java.util.HashMap;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
import lombok.Getter;
import net.runelite.api.ObjectID;
@@ -60,19 +60,21 @@ public enum TitheFarmPlantType
@Getter
private final int[] objectIds;
private static final Map<Integer, TitheFarmPlantType> plantTypes = new HashMap<>();
private static final Map<Integer, TitheFarmPlantType> plantTypes;
static
{
TitheFarmPlantType[] types = values();
ImmutableMap.Builder<Integer, TitheFarmPlantType> builder = new ImmutableMap.Builder<>();
for (TitheFarmPlantType type : types)
for (TitheFarmPlantType type : values())
{
for (int spotId : type.getObjectIds())
{
plantTypes.put(spotId, type);
builder.put(spotId, type);
}
}
plantTypes = builder.build();
}
TitheFarmPlantType(String name, int baseId, int... objectIds)

View File

@@ -24,7 +24,7 @@
*/
package net.runelite.client.plugins.woodcutting;
import java.util.HashMap;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
import lombok.AllArgsConstructor;
import lombok.Getter;
@@ -67,14 +67,18 @@ enum Axe
private final Integer animId;
private final Integer itemId;
private static final Map<Integer, Axe> AXE_ANIM_IDS = new HashMap<>();
private static final Map<Integer, Axe> AXE_ANIM_IDS;
static
{
ImmutableMap.Builder<Integer, Axe> builder = new ImmutableMap.Builder<>();
for (Axe axe : values())
{
AXE_ANIM_IDS.put(axe.animId, axe);
builder.put(axe.animId, axe);
}
AXE_ANIM_IDS = builder.build();
}
static Axe findAxeByAnimId(int animId)

View File

@@ -24,7 +24,7 @@
*/
package net.runelite.client.plugins.woodcutting;
import java.util.HashMap;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
import lombok.Getter;
import static net.runelite.api.ObjectID.REDWOOD;
@@ -42,17 +42,21 @@ enum Tree
this.treeIds = treeIds;
}
private static final Map<Integer, Tree> TREES = new HashMap<>();
private static final Map<Integer, Tree> TREES;
static
{
ImmutableMap.Builder<Integer, Tree> builder = new ImmutableMap.Builder<>();
for (Tree tree : values())
{
for (int treeId : tree.treeIds)
{
TREES.put(treeId, tree);
builder.put(treeId, tree);
}
}
TREES = builder.build();
}
static Tree findTree(int objectId)

View File

@@ -24,22 +24,9 @@
*/
package net.runelite.client.plugins.worldhopper;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@Getter
@RequiredArgsConstructor
public enum SubscriptionFilterMode
{
BOTH("Both"),
FREE("Free"),
MEMBERS("Member");
private final String name;
@Override
public String toString()
{
return name;
}
BOTH,
FREE,
MEMBERS
}

View File

@@ -67,6 +67,9 @@ class XpInfoBox extends JPanel
private static final String HTML_LABEL_TEMPLATE =
"<html><body style='color:%s'>%s<span style='color:white'>%s</span></body></html>";
private static final String REMOVE_STATE = "Remove from canvas";
private static final String ADD_STATE = "Add to canvas";
// Instance members
private final JPanel panel;
@@ -89,6 +92,7 @@ class XpInfoBox extends JPanel
private final JLabel expLeft = new JLabel();
private final JLabel actionsLeft = new JLabel();
private final JMenuItem pauseSkill = new JMenuItem("Pause");
private final JMenuItem canvasItem = new JMenuItem(ADD_STATE);
private final XpTrackerConfig xpTrackerConfig;
@@ -128,6 +132,21 @@ class XpInfoBox extends JPanel
popupMenu.add(reset);
popupMenu.add(resetOthers);
popupMenu.add(pauseSkill);
popupMenu.add(canvasItem);
canvasItem.addActionListener(e ->
{
if (canvasItem.getText().equals(REMOVE_STATE))
{
xpTrackerPlugin.removeOverlay(skill);
canvasItem.setText(ADD_STATE);
}
else
{
xpTrackerPlugin.addOverlay(skill);
canvasItem.setText(REMOVE_STATE);
}
});
JLabel skillIcon = new JLabel(new ImageIcon(iconManager.getSkillImage(skill)));
skillIcon.setHorizontalAlignment(SwingConstants.CENTER);
@@ -177,6 +196,7 @@ class XpInfoBox extends JPanel
void reset()
{
canvasItem.setText(ADD_STATE);
container.remove(statsPanel);
panel.remove(this);
panel.revalidate();
@@ -266,7 +286,7 @@ class XpInfoBox extends JPanel
static String htmlLabel(String key, int value)
{
String valueStr = StackFormatter.quantityToRSDecimalStack(value);
String valueStr = StackFormatter.quantityToRSDecimalStack(value, true);
return String.format(HTML_LABEL_TEMPLATE, ColorUtil.toHexColor(ColorScheme.LIGHT_GRAY_COLOR), key, valueStr);
}
}

View File

@@ -0,0 +1,172 @@
/*
* Copyright (c) 2018, Jasper Ketelaar <Jasper0781@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.plugins.xptracker;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import lombok.AccessLevel;
import lombok.Getter;
import net.runelite.api.Experience;
import net.runelite.api.Skill;
import net.runelite.client.ui.FontManager;
import net.runelite.client.ui.SkillColor;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayMenuEntry;
import net.runelite.client.ui.overlay.components.ComponentOrientation;
import net.runelite.client.ui.overlay.components.ImageComponent;
import net.runelite.client.ui.overlay.components.LineComponent;
import net.runelite.client.ui.overlay.components.PanelComponent;
import net.runelite.client.ui.overlay.components.ProgressBarComponent;
import net.runelite.client.ui.overlay.components.SplitComponent;
import net.runelite.client.util.StackFormatter;
import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG;
import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE;
class XpInfoBoxOverlay extends Overlay
{
private static final int PANEL_PREFERRED_WIDTH = 150;
private static final int BORDER_SIZE = 2;
private static final int XP_AND_PROGRESS_BAR_GAP = 2;
private static final int XP_AND_ICON_GAP = 4;
private static final Rectangle XP_AND_ICON_COMPONENT_BORDER = new Rectangle(2, 1, 4, 0);
private final PanelComponent panel = new PanelComponent();
private final PanelComponent iconXpSplitPanel = new PanelComponent();
private final XpTrackerPlugin plugin;
private final XpTrackerConfig config;
@Getter(AccessLevel.PACKAGE)
private final Skill skill;
private final BufferedImage icon;
XpInfoBoxOverlay(
XpTrackerPlugin plugin,
XpTrackerConfig config,
Skill skill,
BufferedImage icon)
{
super(plugin);
this.plugin = plugin;
this.config = config;
this.skill = skill;
this.icon = icon;
panel.setBorder(new Rectangle(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE));
panel.setGap(new Point(0, XP_AND_PROGRESS_BAR_GAP));
panel.setPreferredSize(new Dimension(PANEL_PREFERRED_WIDTH, 0));
iconXpSplitPanel.setBorder(XP_AND_ICON_COMPONENT_BORDER);
iconXpSplitPanel.setBackgroundColor(null);
iconXpSplitPanel.setPreferredSize(new Dimension(PANEL_PREFERRED_WIDTH, 0));
getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "XP Tracker overlay"));
}
@Override
public Dimension render(Graphics2D graphics)
{
panel.getChildren().clear();
iconXpSplitPanel.getChildren().clear();
//Setting the font to rs small font so that the overlay isn't huge
graphics.setFont(FontManager.getRunescapeSmallFont());
final XpSnapshotSingle snapshot = plugin.getSkillSnapshot(skill);
final String leftStr;
final int rightNum;
switch (config.onScreenDisplayMode())
{
case ACTIONS_DONE:
leftStr = snapshot.getActionType().getLabel() + " Done";
rightNum = snapshot.getActionsInSession();
break;
case ACTIONS_LEFT:
leftStr = snapshot.getActionType().getLabel() + " Left";
rightNum = snapshot.getActionsRemainingToGoal();
break;
case XP_LEFT:
leftStr = "XP Left";
rightNum = snapshot.getXpRemainingToGoal();
break;
case XP_GAINED:
default:
leftStr = "XP Gained";
rightNum = snapshot.getXpGainedInSession();
break;
}
final LineComponent xpLine = LineComponent.builder()
.left(leftStr + ":")
.right(StackFormatter.quantityToRSDecimalStack(rightNum, true))
.build();
final LineComponent xpHour = LineComponent.builder()
.left("XP/Hour:")
.right(StackFormatter.quantityToRSDecimalStack(snapshot.getXpPerHour(), true))
.build();
final SplitComponent xpSplit = SplitComponent.builder()
.first(xpLine)
.second(xpHour)
.orientation(ComponentOrientation.VERTICAL)
.build();
final ImageComponent imageComponent = new ImageComponent(icon);
final SplitComponent iconXpSplit = SplitComponent.builder()
.first(imageComponent)
.second(xpSplit)
.orientation(ComponentOrientation.HORIZONTAL)
.gap(new Point(XP_AND_ICON_GAP, 0))
.build();
iconXpSplitPanel.getChildren().add(iconXpSplit);
final ProgressBarComponent progressBarComponent = new ProgressBarComponent();
progressBarComponent.setBackgroundColor(new Color(61, 56, 49));
progressBarComponent.setForegroundColor(SkillColor.find(skill).getColor());
progressBarComponent.setLeftLabel(String.valueOf(snapshot.getStartLevel()));
progressBarComponent.setRightLabel(snapshot.getEndGoalXp() == Experience.MAX_SKILL_XP
? "200M"
: String.valueOf(snapshot.getEndLevel()));
progressBarComponent.setValue(snapshot.getSkillProgressToGoal());
panel.getChildren().add(iconXpSplitPanel);
panel.getChildren().add(progressBarComponent);
return panel.render(graphics);
}
@Override
public String getName()
{
return super.getName() + skill.getName();
}
}

View File

@@ -24,6 +24,7 @@
*/
package net.runelite.client.plugins.xptracker;
import lombok.AllArgsConstructor;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@@ -31,6 +32,15 @@ import net.runelite.client.config.ConfigItem;
@ConfigGroup("xpTracker")
public interface XpTrackerConfig extends Config
{
@AllArgsConstructor
enum OnScreenDisplayMode
{
XP_GAINED,
XP_LEFT,
ACTIONS_DONE,
ACTIONS_LEFT
}
@ConfigItem(
position = 0,
keyName = "hideMaxed",
@@ -74,4 +84,15 @@ public interface XpTrackerConfig extends Config
{
return 0;
}
@ConfigItem(
position = 4,
keyName = "onScreenDisplayMode",
name = "On-screen tracker display mode",
description = "Configures the information displayed in the first line of on-screen XP overlays"
)
default OnScreenDisplayMode onScreenDisplayMode()
{
return OnScreenDisplayMode.XP_GAINED;
}
}

View File

@@ -59,6 +59,7 @@ import static net.runelite.client.plugins.xptracker.XpWorldType.NORMAL;
import net.runelite.client.task.Schedule;
import net.runelite.client.ui.ClientToolbar;
import net.runelite.client.ui.NavigationButton;
import net.runelite.client.ui.overlay.OverlayManager;
import net.runelite.client.util.ImageUtil;
import net.runelite.http.api.xp.XpClient;
@@ -98,6 +99,9 @@ public class XpTrackerPlugin extends Plugin
@Inject
private NPCManager npcManager;
@Inject
private OverlayManager overlayManager;
private NavigationButton navButton;
private XpPanel xpPanel;
private XpWorldType lastWorldType;
@@ -142,6 +146,7 @@ public class XpTrackerPlugin extends Plugin
@Override
protected void shutDown() throws Exception
{
overlayManager.removeIf(e -> e instanceof XpInfoBoxOverlay);
xpState.reset();
clientToolbar.removeNavigation(navButton);
}
@@ -208,6 +213,27 @@ public class XpTrackerPlugin extends Plugin
return xpType;
}
/**
* Adds an overlay to the canvas for tracking a specific skill.
*
* @param skill the skill for which the overlay should be added
*/
void addOverlay(Skill skill)
{
removeOverlay(skill);
overlayManager.add(new XpInfoBoxOverlay(this, xpTrackerConfig, skill, skillIconManager.getSkillImage(skill)));
}
/**
* Removes an overlay from the overlayManager if it's present.
*
* @param skill the skill for which the overlay should be removed.
*/
void removeOverlay(Skill skill)
{
overlayManager.removeIf(e -> e instanceof XpInfoBoxOverlay && ((XpInfoBoxOverlay) e).getSkill() == skill);
}
/**
* Reset internal state and re-initialize all skills with XP currently cached by the RS client
* This is called by the user manually clicking resetSkillState in the UI.
@@ -230,6 +256,7 @@ public class XpTrackerPlugin extends Plugin
}
xpState.initializeSkill(skill, currentXp);
removeOverlay(skill);
}
}
@@ -242,6 +269,7 @@ public class XpTrackerPlugin extends Plugin
xpState.reset();
xpPanel.resetAllInfoBoxes();
xpPanel.updateTotal(new XpSnapshotSingle.XpSnapshotSingleBuilder().build());
overlayManager.removeIf(e -> e instanceof XpInfoBoxOverlay);
}
/**
@@ -254,6 +282,7 @@ public class XpTrackerPlugin extends Plugin
int currentXp = client.getSkillExperience(skill);
xpState.resetSkill(skill, currentXp);
xpPanel.resetSkill(skill);
removeOverlay(skill);
}
/**
@@ -272,7 +301,6 @@ public class XpTrackerPlugin extends Plugin
}
}
@Subscribe
public void onExperienceChanged(ExperienceChanged event)
{

View File

@@ -31,6 +31,7 @@ import javax.swing.JList;
import javax.swing.ListCellRenderer;
import javax.swing.border.EmptyBorder;
import net.runelite.client.ui.ColorScheme;
import net.runelite.client.util.Text;
/**
* A custom list renderer to avoid substance's weird coloring.
@@ -57,7 +58,16 @@ public final class ComboBoxListRenderer extends JLabel implements ListCellRender
setBorder(new EmptyBorder(5, 5, 5, 0));
String text = o.toString();
String text;
if (o instanceof Enum)
{
text = Text.titleCase((Enum) o);
}
else
{
text = o.toString();
}
setText(text);
return this;

View File

@@ -41,6 +41,7 @@ import static net.runelite.api.widgets.WidgetID.EQUIPMENT_INVENTORY_GROUP_ID;
import static net.runelite.api.widgets.WidgetID.GRAND_EXCHANGE_INVENTORY_GROUP_ID;
import static net.runelite.api.widgets.WidgetID.GUIDE_PRICES_INVENTORY_GROUP_ID;
import static net.runelite.api.widgets.WidgetID.INVENTORY_GROUP_ID;
import static net.runelite.api.widgets.WidgetID.SEED_VAULT_INVENTORY_GROUP_ID;
import static net.runelite.api.widgets.WidgetID.SHOP_INVENTORY_GROUP_ID;
import static net.runelite.api.widgets.WidgetInfo.TO_GROUP;
import net.runelite.api.widgets.WidgetItem;
@@ -92,7 +93,8 @@ public abstract class WidgetItemOverlay extends Overlay
GRAND_EXCHANGE_INVENTORY_GROUP_ID,
GUIDE_PRICES_INVENTORY_GROUP_ID,
EQUIPMENT_INVENTORY_GROUP_ID,
INVENTORY_GROUP_ID);
INVENTORY_GROUP_ID,
SEED_VAULT_INVENTORY_GROUP_ID);
}
protected void showOnBank()

View File

@@ -0,0 +1,31 @@
/*
* Copyright (c) 2018, Jasper Ketelaar <Jasper0781@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.ui.overlay.components;
public enum ComponentOrientation
{
HORIZONTAL,
VERTICAL
}

View File

@@ -37,12 +37,6 @@ import lombok.Setter;
public class PanelComponent implements LayoutableRenderableEntity
{
public enum Orientation
{
HORIZONTAL,
VERTICAL;
}
@Getter
private final Rectangle bounds = new Rectangle();
@@ -60,7 +54,7 @@ public class PanelComponent implements LayoutableRenderableEntity
private final List<LayoutableRenderableEntity> children = new ArrayList<>();
@Setter
private Orientation orientation = Orientation.VERTICAL;
private ComponentOrientation orientation = ComponentOrientation.VERTICAL;
@Setter
private int wrapping = -1;

View File

@@ -46,10 +46,14 @@ public class ProgressBarComponent implements LayoutableRenderableEntity
private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("0.0");
private static final DecimalFormat DECIMAL_FORMAT_ABS = new DecimalFormat("#0");
private static final int SIDE_LABEL_OFFSET = 4;
private long minimum;
private long maximum = 100;
private double value;
private LabelDisplayMode labelDisplayMode = LabelDisplayMode.PERCENTAGE;
private String leftLabel;
private String rightLabel;
private Color foregroundColor = new Color(82, 161, 82);
private Color backgroundColor = new Color(255, 255, 255, 127);
private Color fontColor = Color.WHITE;
@@ -99,6 +103,24 @@ public class ProgressBarComponent implements LayoutableRenderableEntity
textComponent.setText(textToWrite);
textComponent.render(graphics);
if (leftLabel != null)
{
final TextComponent leftTextComponent = new TextComponent();
leftTextComponent.setPosition(new Point(barX + SIDE_LABEL_OFFSET, progressTextY));
leftTextComponent.setColor(fontColor);
leftTextComponent.setText(leftLabel);
leftTextComponent.render(graphics);
}
if (rightLabel != null)
{
final TextComponent leftTextComponent = new TextComponent();
leftTextComponent.setPosition(new Point(barX + width - metrics.stringWidth(rightLabel) - SIDE_LABEL_OFFSET, progressTextY));
leftTextComponent.setColor(fontColor);
leftTextComponent.setText(rightLabel);
leftTextComponent.render(graphics);
}
final Dimension dimension = new Dimension(width, height);
bounds.setLocation(preferredLocation);
bounds.setSize(dimension);

View File

@@ -0,0 +1,102 @@
/*
* Copyright (c) 2018, Jasper Ketelaar <jasper0781@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.ui.overlay.components;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@Setter
@Builder
public class SplitComponent implements LayoutableRenderableEntity
{
private LayoutableRenderableEntity first;
private LayoutableRenderableEntity second;
@Builder.Default
private Point preferredLocation = new Point();
@Builder.Default
private Dimension preferredSize = new Dimension(ComponentConstants.STANDARD_WIDTH, 0);
@Builder.Default
private ComponentOrientation orientation = ComponentOrientation.VERTICAL;
@Builder.Default
private Point gap = new Point(0, 0);
@Builder.Default
@Getter
private final Rectangle bounds = new Rectangle();
@Override
public Dimension render(Graphics2D graphics)
{
first.setPreferredLocation(preferredLocation);
first.setPreferredSize(preferredSize);
final Dimension firstDimension = first.render(graphics);
int x = 0, y = 0;
if (orientation == ComponentOrientation.VERTICAL)
{
y = firstDimension.height + gap.y;
}
else
{
x = firstDimension.width + gap.x;
}
second.setPreferredLocation(new Point(x + preferredLocation.x, y + preferredLocation.y));
// Make the second component fit to whatever size is left after the first component is rendered
second.setPreferredSize(new Dimension(preferredSize.width - x, preferredSize.height - y));
// The total width/height need to be determined as they are now always the same as the
// individual width/height (for example image width/height will just be the height of the image
// and not the height of the area the image is in
final Dimension secondDimension = second.render(graphics);
int totalWidth, totalHeight;
if (orientation == ComponentOrientation.VERTICAL)
{
totalWidth = Math.max(firstDimension.width, secondDimension.width);
totalHeight = y + secondDimension.height;
}
else
{
totalHeight = Math.max(firstDimension.height, secondDimension.height);
totalWidth = x + secondDimension.width;
}
final Dimension dimension = new Dimension(totalWidth, totalHeight);
bounds.setLocation(preferredLocation);
bounds.setSize(dimension);
return dimension;
}
}

View File

@@ -38,6 +38,7 @@ import net.runelite.api.Client;
import net.runelite.client.config.RuneLiteConfig;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.components.ComponentOrientation;
import net.runelite.client.ui.overlay.components.InfoBoxComponent;
import net.runelite.client.ui.overlay.components.LayoutableRenderableEntity;
import net.runelite.client.ui.overlay.components.PanelComponent;
@@ -84,8 +85,8 @@ public class InfoBoxOverlay extends Overlay
panelComponent.getChildren().clear();
panelComponent.setWrapping(config.infoBoxWrap());
panelComponent.setOrientation(config.infoBoxVertical()
? PanelComponent.Orientation.VERTICAL
: PanelComponent.Orientation.HORIZONTAL);
? ComponentOrientation.VERTICAL
: ComponentOrientation.HORIZONTAL);
panelComponent.setPreferredSize(new Dimension(config.infoBoxSize(), config.infoBoxSize()));
for (InfoBox box : infoBoxes)

View File

@@ -0,0 +1,96 @@
/*
* Copyright (c) 2019, Tomas Slusny <slusnucky@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.ui.overlay.infobox;
import com.google.common.base.Preconditions;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.time.Duration;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import lombok.Getter;
import lombok.ToString;
import net.runelite.client.plugins.Plugin;
@Getter
@ToString
public class LoopTimer extends InfoBox
{
private final Instant startTime;
private final Duration duration;
private final boolean reverse;
public LoopTimer(long period, ChronoUnit unit, BufferedImage image, Plugin plugin, boolean reverse)
{
super(image, plugin);
Preconditions.checkArgument(period > 0, "negative period!");
startTime = Instant.now();
duration = Duration.of(period, unit);
this.reverse = reverse;
}
public LoopTimer(long period, ChronoUnit unit, BufferedImage image, Plugin plugin)
{
this(period, unit, image, plugin, false);
}
@Override
public String getText()
{
final Duration progress = getProgress();
final int seconds = (int) (progress.toMillis() / 1000L);
final int minutes = (seconds % 3600) / 60;
final int secs = seconds % 60;
return String.format("%d:%02d", minutes, secs);
}
@Override
public Color getTextColor()
{
final Duration progress = getProgress();
// check if timer has 10% of time left
if (progress.getSeconds() < (duration.getSeconds() * .10))
{
return Color.RED.brighter();
}
return Color.WHITE;
}
private Duration getProgress()
{
final Duration passed = Duration.between(startTime, Instant.now());
final long passedMillis = passed.toMillis();
final long durationMillis = duration.toMillis();
final long progress = passedMillis % durationMillis;
return Duration.ofMillis(reverse
? durationMillis - progress
: progress);
}
}

View File

@@ -24,6 +24,7 @@
*/
package net.runelite.client.util;
import com.google.common.primitives.Ints;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
@@ -34,12 +35,15 @@ import java.awt.image.DirectColorModel;
import java.awt.image.PixelGrabber;
import java.awt.image.RescaleOp;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.GrayFilter;
import java.util.function.Predicate;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client;
import net.runelite.api.IndexedSprite;
import net.runelite.api.SpritePixels;
/**
@@ -448,4 +452,74 @@ public class ImageUtil
return client.createSpritePixels(pixels, image.getWidth(), image.getHeight());
}
/**
* Converts an image into an {@code IndexedSprite} instance.
*
* The passed in image can only have at max 255 different colors.
*
* @param image The image to be converted
* @param client Current client instance
* @return The image as an {@code IndexedSprite}
*/
public static IndexedSprite getImageIndexedSprite(BufferedImage image, Client client)
{
final byte[] pixels = new byte[image.getWidth() * image.getHeight()];
final List<Integer> palette = new ArrayList<>();
/*
When drawing the indexed sprite, palette idx 0 is seen as fully transparent,
so pad the palette out so that our colors start at idx 1.
*/
palette.add(0);
final int[] sourcePixels = image.getRGB(0, 0,
image.getWidth(), image.getHeight(),
null, 0, image.getWidth());
/*
Build a color palette and assign the pixels to positions in the palette.
*/
for (int j = 0; j < sourcePixels.length; j++)
{
final int argb = sourcePixels[j];
final int a = (argb >> 24) & 0xFF;
final int rgb = argb & 0xFF_FF_FF;
// Default to not drawing the pixel.
int paletteIdx = 0;
// If the pixel is fully opaque, draw it.
if (a == 0xFF)
{
paletteIdx = palette.indexOf(rgb);
if (paletteIdx == -1)
{
paletteIdx = palette.size();
palette.add(rgb);
}
}
pixels[j] = (byte) paletteIdx;
}
if (palette.size() > 256)
{
throw new RuntimeException("Passed in image had " + (palette.size() - 1)
+ " different colors, exceeding the max of 255.");
}
final IndexedSprite sprite = client.createIndexedSprite();
sprite.setPixels(pixels);
sprite.setPalette(Ints.toArray(palette));
sprite.setWidth(image.getWidth());
sprite.setHeight(image.getHeight());
sprite.setOriginalWidth(image.getWidth());
sprite.setOriginalHeight(image.getHeight());
sprite.setOffsetX(0);
sprite.setOffsetY(0);
return sprite;
}
}

View File

@@ -61,6 +61,14 @@ public class StackFormatter
DecimalFormatSymbols.getInstance(Locale.ENGLISH)
);
/**
* A more precise decimal number formatter, outputting thousandths
*/
private static final NumberFormat PRECISE_DECIMAL_FORMATTER = new DecimalFormat(
"#,###.###",
DecimalFormatSymbols.getInstance(Locale.ENGLISH)
);
/**
* Convert a quantity to a nicely formatted stack size.
* See the StackFormatterTest to see expected output.
@@ -152,6 +160,24 @@ public class StackFormatter
* with K after 100,000 and M after 10,000,000
*/
public static String quantityToRSDecimalStack(int quantity)
{
return quantityToRSDecimalStack(quantity, false);
}
/**
* Convert a quantity to stack size as it would
* appear in RuneScape. (with decimals)
* <p>
* This differs from quantityToRSStack in that it displays
* decimals. Ex: 27100 is 27.1k (not 27k)
* <p>
*
* @param quantity The quantity to convert.
* @param precise If true, the returned string will have thousandths precision if quantity is larger than 1 million.
* @return The stack size as it would appear in RS, with decimals,
* with K after 100,000 and M after 10,000,000
*/
public static String quantityToRSDecimalStack(int quantity, boolean precise)
{
String quantityStr = String.valueOf(quantity);
if (quantityStr.length() <= 4)
@@ -160,7 +186,13 @@ public class StackFormatter
}
int power = (int) Math.log10(quantity);
return DECIMAL_FORMATTER.format(quantity / (Math.pow(10, (power / 3) * 3))) + SUFFIXES[power / 3];
// Output thousandths for values above a million
NumberFormat format = precise && power >= 6
? PRECISE_DECIMAL_FORMATTER
: DECIMAL_FORMATTER;
return format.format(quantity / (Math.pow(10, (power / 3) * 3))) + SUFFIXES[power / 3];
}
/**

View File

@@ -31,6 +31,7 @@ import com.google.common.base.Splitter;
import java.util.Collection;
import java.util.List;
import java.util.regex.Pattern;
import org.apache.commons.text.WordUtils;
/**
* A set of utilities to use when dealing with text.
@@ -159,4 +160,28 @@ public class Text
String cleaned = name.contains("<img") ? name.substring(name.lastIndexOf('>') + 1) : name;
return cleaned.replace('\u00A0', ' ');
}
/**
* If passed in enum doesn't implement its own toString,
* converts enum name format from THIS_FORMAT to This Format.
*
* @param o an enum
* @return the enum's name in title case,
* or if it overrides toString,
* the value returned by toString
*/
public static String titleCase(Enum o)
{
String toString = o.toString();
// .toString() returns the value of .name() if not overridden
if (o.name().equals(toString))
{
return WordUtils
.capitalize(toString.toLowerCase(), '_')
.replace("_", " ");
}
return toString;
}
}

View File

@@ -114,6 +114,13 @@ public class PartyService
@Subscribe
public void onUserJoin(final UserJoin message)
{
if (!partyId.equals(message.getPartyId()))
{
// This can happen when a session is resumed server side after the client party
// changes when disconnected.
return;
}
final PartyMember partyMember = new PartyMember(message.getMemberId(), message.getName());
members.add(partyMember);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 570 B

After

Width:  |  Height:  |  Size: 343 B

View File

@@ -0,0 +1 @@
The images in this folder are derivatives of "twemoji" (https://github.com/twitter/twemoji) by "Twitter, Inc", used under CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/). The derivatives are licensed under the same license.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Some files were not shown because too many files have changed in this diff Show More