Merge pull request #83 from Kyleeld/master
Hydra plugin & Add encryption to account data - thx ThatGamerBlue
This commit is contained in:
62
alchemicalhydra/Hydra.java
Normal file
62
alchemicalhydra/Hydra.java
Normal file
@@ -0,0 +1,62 @@
|
||||
package net.runelite.client.plugins.alchemicalhydra;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.runelite.api.Prayer;
|
||||
import net.runelite.api.ProjectileID;
|
||||
|
||||
@Singleton
|
||||
class Hydra
|
||||
{
|
||||
enum AttackStyle
|
||||
{
|
||||
MAGIC(ProjectileID.HYDRA_MAGIC, Prayer.PROTECT_FROM_MAGIC),
|
||||
RANGED(ProjectileID.HYDRA_RANGED, Prayer.PROTECT_FROM_MISSILES);
|
||||
|
||||
@Getter
|
||||
private int projId;
|
||||
|
||||
@Getter
|
||||
private Prayer prayer;
|
||||
|
||||
AttackStyle(int projId, Prayer prayer)
|
||||
{
|
||||
this.projId = projId;
|
||||
this.prayer = prayer;
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private HydraPhase phase;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private int attackCount;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private int nextSwitch;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private int nextSpecial;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private AttackStyle nextAttack;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private AttackStyle lastAttack;
|
||||
|
||||
Hydra()
|
||||
{
|
||||
this.phase = HydraPhase.ONE;
|
||||
this.nextAttack = AttackStyle.MAGIC;
|
||||
this.nextSpecial = 3;
|
||||
this.nextSwitch = phase.getAttacksPerSwitch();
|
||||
this.attackCount = 0;
|
||||
}
|
||||
}
|
||||
132
alchemicalhydra/HydraOverlay.java
Normal file
132
alchemicalhydra/HydraOverlay.java
Normal file
@@ -0,0 +1,132 @@
|
||||
package net.runelite.client.plugins.alchemicalhydra;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.image.BufferedImage;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.Prayer;
|
||||
import net.runelite.api.SpriteID;
|
||||
import net.runelite.client.game.SpriteManager;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||
import net.runelite.client.ui.overlay.components.InfoBoxComponent;
|
||||
import net.runelite.client.ui.overlay.components.PanelComponent;
|
||||
|
||||
@Singleton
|
||||
class HydraOverlay extends Overlay
|
||||
{
|
||||
private final HydraPlugin plugin;
|
||||
private final Client client;
|
||||
private final SpriteManager spriteManager;
|
||||
private final PanelComponent panelComponent = new PanelComponent();
|
||||
private static final Color redBgCol = new Color(156, 0, 0, 156);
|
||||
private static final Color yelBgCol = new Color(200, 156, 0, 156);
|
||||
private static final Color grnBgCol = new Color(0, 156, 0, 156);
|
||||
|
||||
@Inject
|
||||
HydraOverlay(HydraPlugin plugin, Client client, SpriteManager spriteManager)
|
||||
{
|
||||
this.plugin = plugin;
|
||||
this.client = client;
|
||||
this.spriteManager = spriteManager;
|
||||
setPosition(OverlayPosition.BOTTOM_RIGHT);
|
||||
panelComponent.setOrientation(PanelComponent.Orientation.VERTICAL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics2D)
|
||||
{
|
||||
Hydra hydra = plugin.getHydra();
|
||||
panelComponent.getChildren().clear();
|
||||
|
||||
if (hydra == null || client == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
//Add spec overlay first, to keep it above pray
|
||||
HydraPhase phase = hydra.getPhase();
|
||||
int attackCount = hydra.getAttackCount();
|
||||
int nextSpec = hydra.getNextSpecial() - attackCount;
|
||||
|
||||
if (nextSpec <= 3)
|
||||
{
|
||||
InfoBoxComponent specComponent = new InfoBoxComponent();
|
||||
|
||||
if (nextSpec == 0)
|
||||
{
|
||||
specComponent.setBackgroundColor(redBgCol);
|
||||
}
|
||||
else if (nextSpec == 1)
|
||||
{
|
||||
specComponent.setBackgroundColor(yelBgCol);
|
||||
}
|
||||
Image specImg = scaleImg(spriteManager.getSprite(phase.getSpecImage(), 0));
|
||||
|
||||
specComponent.setImage(specImg);
|
||||
specComponent.setText(" " + (nextSpec)); //hacky way to not have to figure out how to move text
|
||||
specComponent.setPreferredSize(new Dimension(40, 40));
|
||||
panelComponent.getChildren().add(specComponent);
|
||||
}
|
||||
|
||||
|
||||
Prayer nextPrayer = hydra.getNextAttack().getPrayer();
|
||||
Image prayImg = scaleImg(getPrayerImage(hydra.getNextAttack().getPrayer()));
|
||||
int nextSwitch = hydra.getNextSwitch();
|
||||
|
||||
InfoBoxComponent prayComponent = new InfoBoxComponent();
|
||||
|
||||
if (nextSwitch == 1)
|
||||
{
|
||||
prayComponent.setBackgroundColor(client.isPrayerActive(nextPrayer) ? yelBgCol : redBgCol);
|
||||
}
|
||||
else
|
||||
{
|
||||
prayComponent.setBackgroundColor(client.isPrayerActive(nextPrayer) ? grnBgCol : redBgCol);
|
||||
}
|
||||
|
||||
prayComponent.setImage(prayImg);
|
||||
prayComponent.setText(" " + nextSwitch);
|
||||
prayComponent.setColor(Color.white);
|
||||
prayComponent.setPreferredSize(new Dimension(40, 40));
|
||||
panelComponent.getChildren().add(prayComponent);
|
||||
|
||||
panelComponent.setPreferredSize(new Dimension(40, 0));
|
||||
panelComponent.setBorder(new Rectangle(0, 0, 0, 0));
|
||||
return panelComponent.render(graphics2D);
|
||||
}
|
||||
|
||||
private BufferedImage getPrayerImage(Prayer pray)
|
||||
{
|
||||
return pray == Prayer.PROTECT_FROM_MAGIC
|
||||
? spriteManager.getSprite(SpriteID.PRAYER_PROTECT_FROM_MAGIC, 0)
|
||||
: spriteManager.getSprite(SpriteID.PRAYER_PROTECT_FROM_MISSILES, 0);
|
||||
}
|
||||
|
||||
private Image scaleImg(final Image img)
|
||||
{
|
||||
if (img == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
final double width = img.getWidth(null);
|
||||
final double height = img.getHeight(null);
|
||||
final double size = 36; // Limit size to 2 as that is minimum size not causing breakage
|
||||
final double scalex = size / width;
|
||||
final double scaley = size / height;
|
||||
final double scale = Math.min(scalex, scaley);
|
||||
final int newWidth = (int) (width * scale);
|
||||
final int newHeight = (int) (height * scale);
|
||||
final BufferedImage scaledImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB);
|
||||
final Graphics g = scaledImage.createGraphics();
|
||||
g.drawImage(img, 0, 0, newWidth, newHeight, null);
|
||||
g.dispose();
|
||||
return scaledImage;
|
||||
}
|
||||
}
|
||||
42
alchemicalhydra/HydraPhase.java
Normal file
42
alchemicalhydra/HydraPhase.java
Normal file
@@ -0,0 +1,42 @@
|
||||
package net.runelite.client.plugins.alchemicalhydra;
|
||||
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.AnimationID;
|
||||
import net.runelite.api.ProjectileID;
|
||||
import net.runelite.api.SpriteID;
|
||||
|
||||
enum HydraPhase
|
||||
{
|
||||
ONE(3, AnimationID.HYDRA_1_1, AnimationID.HYDRA_1_2, ProjectileID.HYDRA_POISON, 0, SpriteID.BIG_ASS_GUTHIX_SPELL),
|
||||
TWO(3, AnimationID.HYDRA_2_1, AnimationID.HYDRA_2_2, 0, AnimationID.HYDRA_LIGHTNING, SpriteID.BIG_SPEC_TRANSFER),
|
||||
THREE(3, AnimationID.HYDRA_3_1, AnimationID.HYDRA_3_2, 0, AnimationID.HYDRA_FIRE, SpriteID.BIG_SUPERHEAT),
|
||||
FOUR(1, AnimationID.HYDRA_4_1, AnimationID.HYDRA_4_2, ProjectileID.HYDRA_POISON, 0, SpriteID.BIG_ASS_GUTHIX_SPELL);
|
||||
|
||||
@Getter
|
||||
private int attacksPerSwitch;
|
||||
|
||||
@Getter
|
||||
private int deathAnim1;
|
||||
|
||||
@Getter
|
||||
private int deathAnim2;
|
||||
|
||||
@Getter
|
||||
private int specProjectileId;
|
||||
|
||||
@Getter
|
||||
private int specAnimationId;
|
||||
|
||||
@Getter
|
||||
private int specImage;
|
||||
|
||||
HydraPhase(int attacksPerSwitch, int deathAnim1, int deathAnim2, int specProjectileId, int specAnimationId, int specImage)
|
||||
{
|
||||
this.attacksPerSwitch = attacksPerSwitch;
|
||||
this.deathAnim1 = deathAnim1;
|
||||
this.deathAnim2 = deathAnim2;
|
||||
this.specProjectileId = specProjectileId;
|
||||
this.specAnimationId = specAnimationId;
|
||||
this.specImage = specImage;
|
||||
}
|
||||
}
|
||||
248
alchemicalhydra/HydraPlugin.java
Normal file
248
alchemicalhydra/HydraPlugin.java
Normal file
@@ -0,0 +1,248 @@
|
||||
package net.runelite.client.plugins.alchemicalhydra;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import javax.inject.Inject;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Actor;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.NpcID;
|
||||
import net.runelite.api.Projectile;
|
||||
import net.runelite.api.coords.LocalPoint;
|
||||
import net.runelite.api.events.AnimationChanged;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.NpcSpawned;
|
||||
import net.runelite.api.events.ProjectileMoved;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.plugins.PluginType;
|
||||
import net.runelite.client.ui.overlay.OverlayManager;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Alchemical Hydra",
|
||||
description = "Show what to pray against hydra",
|
||||
tags = {"Hydra", "Lazy", "4 headed asshole"},
|
||||
type = PluginType.PVM
|
||||
)
|
||||
@Slf4j
|
||||
public class HydraPlugin extends Plugin
|
||||
{
|
||||
@Getter
|
||||
private HashSet<LocalPoint> poisonPoints = new HashSet<>();
|
||||
|
||||
@Getter
|
||||
private Hydra hydra;
|
||||
|
||||
private boolean inHydraInstance;
|
||||
private int lastAttackTick;
|
||||
private int lastPoisonTick;
|
||||
|
||||
private static final int[] HYDRA_REGIONS = {
|
||||
5279, 5280,
|
||||
5535, 5536
|
||||
};
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private OverlayManager overlayManager;
|
||||
|
||||
@Inject
|
||||
private HydraOverlay overlay;
|
||||
|
||||
@Inject
|
||||
private HydraPoisonOverlay poisonOverlay;
|
||||
|
||||
@Override
|
||||
protected void startUp()
|
||||
{
|
||||
inHydraInstance = checkArea();
|
||||
lastAttackTick = -1;
|
||||
poisonPoints.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown()
|
||||
{
|
||||
inHydraInstance = false;
|
||||
hydra = null;
|
||||
poisonPoints.clear();
|
||||
removeOverlays();
|
||||
lastAttackTick = -1;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
private void onGameStateChanged(GameStateChanged state)
|
||||
{
|
||||
if (state.getGameState() != GameState.LOGGED_IN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
inHydraInstance = checkArea();
|
||||
|
||||
if (inHydraInstance)
|
||||
{
|
||||
hydra = new Hydra();
|
||||
log.debug("Entered hydra instance");
|
||||
addOverlays();
|
||||
}
|
||||
else if (hydra != null)
|
||||
{
|
||||
removeOverlays();
|
||||
hydra = null;
|
||||
log.debug("Left hydra instance");
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
private void onNpcSpawned(NpcSpawned event)
|
||||
{
|
||||
if (!inHydraInstance || event.getNpc().getId() != NpcID.ALCHEMICAL_HYDRA)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
hydra = new Hydra();
|
||||
log.debug("Hydra spawned");
|
||||
addOverlays();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onAnimationChanged(AnimationChanged animationChanged)
|
||||
{
|
||||
Actor actor = animationChanged.getActor();
|
||||
|
||||
if (!inHydraInstance || hydra == null || actor == client.getLocalPlayer())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
HydraPhase phase = hydra.getPhase();
|
||||
|
||||
// Using the first animation sometimes fucks shit up, so just use 2
|
||||
if ( /* actor.getAnimation() == phase.getDeathAnim1() || */ actor.getAnimation() == phase.getDeathAnim2())
|
||||
{
|
||||
switch (phase)
|
||||
{
|
||||
case ONE:
|
||||
changePhase(HydraPhase.TWO);
|
||||
log.debug("Hydra phase 2");
|
||||
return;
|
||||
case TWO:
|
||||
changePhase(HydraPhase.THREE);
|
||||
log.debug("Hydra phase 3");
|
||||
return;
|
||||
case THREE:
|
||||
changePhase(HydraPhase.FOUR);
|
||||
log.debug("Hydra phase 4");
|
||||
return;
|
||||
case FOUR:
|
||||
hydra = null;
|
||||
poisonPoints.clear();
|
||||
log.debug("Hydra dead");
|
||||
removeOverlays();
|
||||
return;
|
||||
default:
|
||||
log.debug("Tried some weird shit");
|
||||
break;
|
||||
}
|
||||
|
||||
if (actor.getAnimation() == phase.getDeathAnim1() && phase == HydraPhase.THREE)
|
||||
{
|
||||
changePhase(HydraPhase.FOUR);
|
||||
}
|
||||
}
|
||||
else if (actor.getAnimation() == phase.getSpecAnimationId() && phase.getSpecAnimationId() != 0)
|
||||
{
|
||||
hydra.setNextSpecial(hydra.getNextSpecial() + 9);
|
||||
}
|
||||
|
||||
if (!poisonPoints.isEmpty() && lastPoisonTick + 10 < client.getTickCount())
|
||||
{
|
||||
poisonPoints.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onProjectileMoved(ProjectileMoved event)
|
||||
{
|
||||
if (!inHydraInstance || hydra == null
|
||||
|| client.getGameCycle() >= event.getProjectile().getStartMovementCycle())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Projectile projectile = event.getProjectile();
|
||||
int id = projectile.getId();
|
||||
if (hydra.getPhase().getSpecProjectileId() != 0 && hydra.getPhase().getSpecProjectileId() == id)
|
||||
{
|
||||
poisonPoints.add(event.getPosition());
|
||||
hydra.setNextSpecial(hydra.getNextSpecial() + 9);
|
||||
lastPoisonTick = client.getTickCount();
|
||||
}
|
||||
else if (client.getTickCount() != lastAttackTick
|
||||
&& (id == Hydra.AttackStyle.MAGIC.getProjId() || id == Hydra.AttackStyle.RANGED.getProjId()))
|
||||
{
|
||||
handleAttack(id);
|
||||
lastAttackTick = client.getTickCount();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkArea()
|
||||
{
|
||||
return Arrays.equals(client.getMapRegions(), HYDRA_REGIONS) && client.isInInstancedRegion();
|
||||
}
|
||||
|
||||
private void addOverlays()
|
||||
{
|
||||
overlayManager.add(overlay);
|
||||
overlayManager.add(poisonOverlay);
|
||||
}
|
||||
|
||||
private void removeOverlays()
|
||||
{
|
||||
overlayManager.remove(overlay);
|
||||
overlayManager.remove(poisonOverlay);
|
||||
}
|
||||
|
||||
private void changePhase(HydraPhase newPhase)
|
||||
{
|
||||
hydra.setPhase(newPhase);
|
||||
hydra.setNextSpecial(3);
|
||||
hydra.setAttackCount(0);
|
||||
if (newPhase == HydraPhase.FOUR)
|
||||
{
|
||||
switchStyles();
|
||||
hydra.setNextSwitch(newPhase.getAttacksPerSwitch());
|
||||
}
|
||||
}
|
||||
|
||||
private void switchStyles()
|
||||
{
|
||||
hydra.setNextAttack(hydra.getLastAttack() == Hydra.AttackStyle.MAGIC
|
||||
? Hydra.AttackStyle.RANGED
|
||||
: Hydra.AttackStyle.MAGIC);
|
||||
}
|
||||
|
||||
private void handleAttack(int id)
|
||||
{
|
||||
hydra.setNextSwitch(hydra.getNextSwitch() - 1);
|
||||
hydra.setAttackCount(hydra.getAttackCount() + 1);
|
||||
hydra.setLastAttack(hydra.getNextAttack());
|
||||
|
||||
if (id != hydra.getNextAttack().getProjId())
|
||||
{
|
||||
switchStyles();
|
||||
}
|
||||
else if (hydra.getNextSwitch() <= 0)
|
||||
{
|
||||
switchStyles();
|
||||
hydra.setNextSwitch(hydra.getPhase().getAttacksPerSwitch());
|
||||
}
|
||||
}
|
||||
}
|
||||
61
alchemicalhydra/HydraPoisonOverlay.java
Normal file
61
alchemicalhydra/HydraPoisonOverlay.java
Normal file
@@ -0,0 +1,61 @@
|
||||
package net.runelite.client.plugins.alchemicalhydra;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Polygon;
|
||||
import java.awt.geom.Area;
|
||||
import java.util.HashSet;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import net.runelite.api.Client;
|
||||
import static net.runelite.api.Perspective.getCanvasTileAreaPoly;
|
||||
import net.runelite.api.coords.LocalPoint;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import net.runelite.client.ui.overlay.OverlayLayer;
|
||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||
|
||||
@Singleton
|
||||
class HydraPoisonOverlay extends Overlay
|
||||
{
|
||||
private final HydraPlugin plugin;
|
||||
private final Client client;
|
||||
|
||||
@Inject
|
||||
public HydraPoisonOverlay(Client client, HydraPlugin plugin)
|
||||
{
|
||||
setPosition(OverlayPosition.DYNAMIC);
|
||||
setLayer(OverlayLayer.UNDER_WIDGETS);
|
||||
this.plugin = plugin;
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
final HashSet<LocalPoint> initialPoints = plugin.getPoisonPoints();
|
||||
Area poisonTiles = new Area();
|
||||
for (LocalPoint point : initialPoints)
|
||||
{
|
||||
Polygon poly = getCanvasTileAreaPoly(client, point, 3);
|
||||
if (poly == null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
poisonTiles.add(new Area(poly));
|
||||
}
|
||||
|
||||
if (poisonTiles.isEmpty())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
graphics.setPaintMode();
|
||||
graphics.setColor(new Color(255, 0, 0, 75));
|
||||
graphics.draw(poisonTiles);
|
||||
graphics.setColor(new Color(255, 0, 0, 30));
|
||||
graphics.fill(poisonTiles);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,37 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.139.
|
||||
* Copyright (c) 2019, Spedwards <https://github.com/Spedwards>
|
||||
* 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.profiles;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JLabel;
|
||||
@@ -17,107 +39,140 @@ import javax.swing.JPanel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.border.CompoundBorder;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.client.ui.ColorScheme;
|
||||
import net.runelite.client.util.ImageUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
class ProfilePanel
|
||||
extends JPanel {
|
||||
private static final Logger log = LoggerFactory.getLogger(ProfilePanel.class);
|
||||
private static final ImageIcon DELETE_ICON;
|
||||
private static final ImageIcon DELETE_HOVER_ICON;
|
||||
private final String loginText;
|
||||
private String password = null;
|
||||
@Slf4j
|
||||
class ProfilePanel extends JPanel
|
||||
{
|
||||
private static final ImageIcon DELETE_ICON;
|
||||
private static final ImageIcon DELETE_HOVER_ICON;
|
||||
|
||||
ProfilePanel(final Client client, final String data, final ProfilesConfig config) {
|
||||
String[] parts = data.split(":");
|
||||
this.loginText = parts[1];
|
||||
if (parts.length == 3) {
|
||||
this.password = parts[2];
|
||||
}
|
||||
final ProfilePanel panel = this;
|
||||
this.setLayout(new BorderLayout());
|
||||
this.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||
JPanel labelWrapper = new JPanel(new BorderLayout());
|
||||
labelWrapper.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||
labelWrapper.setBorder(new CompoundBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, ColorScheme.DARK_GRAY_COLOR), BorderFactory.createLineBorder(ColorScheme.DARKER_GRAY_COLOR)));
|
||||
JPanel panelActions = new JPanel(new BorderLayout(3, 0));
|
||||
panelActions.setBorder(new EmptyBorder(0, 0, 0, 8));
|
||||
panelActions.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||
final JLabel delete = new JLabel();
|
||||
delete.setIcon(DELETE_ICON);
|
||||
delete.setToolTipText("Delete account profile");
|
||||
delete.addMouseListener(new MouseAdapter(){
|
||||
static
|
||||
{
|
||||
final BufferedImage deleteImg = ImageUtil.getResourceStreamFromClass(ProfilesPlugin.class, "delete_icon.png");
|
||||
DELETE_ICON = new ImageIcon(deleteImg);
|
||||
DELETE_HOVER_ICON = new ImageIcon(ImageUtil.alphaOffset(deleteImg, -100));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
panel.getParent().remove(panel);
|
||||
ProfilesPanel.removeProfile(data);
|
||||
}
|
||||
private final String loginText;
|
||||
private final ProfilesPanel parent;
|
||||
private String password = null;
|
||||
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent e) {
|
||||
delete.setIcon(DELETE_HOVER_ICON);
|
||||
}
|
||||
ProfilePanel(final Client client, String data, ProfilesConfig config, ProfilesPanel parent)
|
||||
{
|
||||
this.parent = parent;
|
||||
String[] parts = data.split(":");
|
||||
this.loginText = parts[1];
|
||||
if (parts.length == 3)
|
||||
{
|
||||
this.password = parts[2];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(MouseEvent e) {
|
||||
delete.setIcon(DELETE_ICON);
|
||||
}
|
||||
});
|
||||
panelActions.add((Component)delete, "East");
|
||||
JLabel label = new JLabel();
|
||||
label.setText(parts[0]);
|
||||
label.setBorder(null);
|
||||
label.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||
label.setPreferredSize(new Dimension(0, 24));
|
||||
label.setForeground(Color.WHITE);
|
||||
label.setBorder(new EmptyBorder(0, 8, 0, 0));
|
||||
labelWrapper.add((Component)label, "Center");
|
||||
labelWrapper.add((Component)panelActions, "East");
|
||||
label.addMouseListener(new MouseAdapter(){
|
||||
final ProfilePanel panel = this;
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
if (SwingUtilities.isLeftMouseButton(e) && client.getGameState() == GameState.LOGIN_SCREEN) {
|
||||
client.setUsername(ProfilePanel.this.loginText);
|
||||
if (config.rememberPassword() && ProfilePanel.this.password != null) {
|
||||
client.setPassword(ProfilePanel.this.password);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
JPanel bottomContainer = new JPanel(new BorderLayout());
|
||||
bottomContainer.setBorder(new EmptyBorder(8, 0, 8, 0));
|
||||
bottomContainer.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||
bottomContainer.addMouseListener(new MouseAdapter(){
|
||||
setLayout(new BorderLayout());
|
||||
setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
if (SwingUtilities.isLeftMouseButton(e) && client.getGameState() == GameState.LOGIN_SCREEN) {
|
||||
client.setUsername(ProfilePanel.this.loginText);
|
||||
}
|
||||
}
|
||||
});
|
||||
JLabel login = new JLabel();
|
||||
login.setText(config.isStreamerMode() ? "Hidden email" : this.loginText);
|
||||
login.setBorder(null);
|
||||
login.setPreferredSize(new Dimension(0, 24));
|
||||
login.setForeground(Color.WHITE);
|
||||
login.setBorder(new EmptyBorder(0, 8, 0, 0));
|
||||
bottomContainer.add((Component)login, "Center");
|
||||
this.add((Component)labelWrapper, "North");
|
||||
this.add((Component)bottomContainer, "Center");
|
||||
}
|
||||
JPanel labelWrapper = new JPanel(new BorderLayout());
|
||||
labelWrapper.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||
labelWrapper.setBorder(new CompoundBorder(
|
||||
BorderFactory.createMatteBorder(0, 0, 1, 0, ColorScheme.DARK_GRAY_COLOR),
|
||||
BorderFactory.createLineBorder(ColorScheme.DARKER_GRAY_COLOR)
|
||||
));
|
||||
|
||||
static {
|
||||
BufferedImage deleteImg = ImageUtil.getResourceStreamFromClass(ProfilesPlugin.class, "net/runelite/client/plugins/profiles/delete_icon.png");
|
||||
DELETE_ICON = new ImageIcon(deleteImg);
|
||||
DELETE_HOVER_ICON = new ImageIcon(ImageUtil.alphaOffset(deleteImg, -100));
|
||||
}
|
||||
JPanel panelActions = new JPanel(new BorderLayout(3, 0));
|
||||
panelActions.setBorder(new EmptyBorder(0, 0, 0, 8));
|
||||
panelActions.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||
|
||||
JLabel delete = new JLabel();
|
||||
delete.setIcon(DELETE_ICON);
|
||||
delete.setToolTipText("Delete account profile");
|
||||
delete.addMouseListener(new MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e)
|
||||
{
|
||||
panel.getParent().remove(panel);
|
||||
try
|
||||
{
|
||||
parent.removeProfile(data);
|
||||
}
|
||||
catch (InvalidKeySpecException | NoSuchAlgorithmException ex)
|
||||
{
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent e)
|
||||
{
|
||||
delete.setIcon(DELETE_HOVER_ICON);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(MouseEvent e)
|
||||
{
|
||||
delete.setIcon(DELETE_ICON);
|
||||
}
|
||||
});
|
||||
|
||||
panelActions.add(delete, BorderLayout.EAST);
|
||||
|
||||
JLabel label = new JLabel();
|
||||
label.setText(parts[0]);
|
||||
label.setBorder(null);
|
||||
label.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||
label.setPreferredSize(new Dimension(0, 24));
|
||||
label.setForeground(Color.WHITE);
|
||||
label.setBorder(new EmptyBorder(0, 8, 0, 0));
|
||||
|
||||
labelWrapper.add(label, BorderLayout.CENTER);
|
||||
labelWrapper.add(panelActions, BorderLayout.EAST);
|
||||
label.addMouseListener(new MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e)
|
||||
{
|
||||
if (SwingUtilities.isLeftMouseButton(e) && client.getGameState() == GameState.LOGIN_SCREEN)
|
||||
{
|
||||
client.setUsername(loginText);
|
||||
if (config.rememberPassword() && password != null)
|
||||
{
|
||||
client.setPassword(password);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
JPanel bottomContainer = new JPanel(new BorderLayout());
|
||||
bottomContainer.setBorder(new EmptyBorder(8, 0, 8, 0));
|
||||
bottomContainer.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||
bottomContainer.addMouseListener(new MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e)
|
||||
{
|
||||
if (SwingUtilities.isLeftMouseButton(e) && client.getGameState() == GameState.LOGIN_SCREEN)
|
||||
{
|
||||
client.setUsername(loginText);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
JLabel login = new JLabel();
|
||||
login.setText(config.isStreamerMode() ? "Hidden email" : loginText);
|
||||
login.setBorder(null);
|
||||
login.setPreferredSize(new Dimension(0, 24));
|
||||
login.setForeground(Color.WHITE);
|
||||
login.setBorder(new EmptyBorder(0, 8, 0, 0));
|
||||
|
||||
bottomContainer.add(login, BorderLayout.CENTER);
|
||||
|
||||
add(labelWrapper, BorderLayout.NORTH);
|
||||
add(bottomContainer, BorderLayout.CENTER);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,26 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.139.
|
||||
* Copyright (c) 2019, Spedwards <https://github.com/Spedwards>
|
||||
* 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.profiles;
|
||||
|
||||
@@ -7,30 +28,74 @@ import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
|
||||
@ConfigGroup(value="profiles")
|
||||
public interface ProfilesConfig
|
||||
extends Config {
|
||||
@ConfigItem(keyName="profilesData", name="", description="", hidden=true)
|
||||
default public String profilesData() {
|
||||
return "";
|
||||
}
|
||||
@ConfigGroup("profiles")
|
||||
public interface ProfilesConfig extends Config
|
||||
{
|
||||
|
||||
@ConfigItem(keyName="profilesData", name="", description="")
|
||||
public void profilesData(String var1);
|
||||
|
||||
@ConfigItem(keyName="rememberPassword", name="Remember Password", description="Remembers passwords for accounts")
|
||||
default public boolean rememberPassword() {
|
||||
return true;
|
||||
}
|
||||
@ConfigItem(
|
||||
keyName = "profilesData",
|
||||
name = "",
|
||||
description = "",
|
||||
hidden = true
|
||||
)
|
||||
default String profilesData()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
@ConfigItem(keyName="streamerMode", name="Hide email addresses", description="Hides your account emails")
|
||||
default public boolean isStreamerMode() {
|
||||
return false;
|
||||
}
|
||||
@ConfigItem(
|
||||
keyName = "profilesData",
|
||||
name = "",
|
||||
description = ""
|
||||
)
|
||||
void profilesData(String str);
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "salt",
|
||||
name = "",
|
||||
description = "",
|
||||
hidden = true
|
||||
)
|
||||
default String salt()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "salt",
|
||||
name = "",
|
||||
description = ""
|
||||
)
|
||||
void salt(String key);
|
||||
|
||||
@ConfigItem(keyName="switchPanel", name="Auto-open Panel", description="Automatically switch to the account switcher panel on the login screen")
|
||||
default public boolean switchPanel() {
|
||||
return true;
|
||||
}
|
||||
@ConfigItem(
|
||||
keyName = "rememberPassword",
|
||||
name = "Remember Password",
|
||||
description = "Remembers passwords for accounts"
|
||||
)
|
||||
default boolean rememberPassword()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "streamerMode",
|
||||
name = "Hide email addresses",
|
||||
description = "Hides your account emails"
|
||||
)
|
||||
default boolean isStreamerMode()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "switchPanel",
|
||||
name = "Auto-open Panel",
|
||||
description = "Automatically switch to the account switcher panel on the login screen"
|
||||
)
|
||||
default boolean switchPanel()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,248 +1,555 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.139.
|
||||
* Copyright (c) 2019, Spedwards <https://github.com/Spedwards>
|
||||
* 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.profiles;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Insets;
|
||||
import java.awt.LayoutManager;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import java.awt.event.KeyAdapter;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.KeyListener;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.security.spec.KeySpec;
|
||||
import java.util.Arrays;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.Base64;
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.SecretKeyFactory;
|
||||
import javax.crypto.spec.PBEKeySpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import javax.inject.Inject;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JPasswordField;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.client.plugins.profiles.ProfilePanel;
|
||||
import net.runelite.client.plugins.profiles.ProfilesConfig;
|
||||
import net.runelite.client.ui.ColorScheme;
|
||||
import net.runelite.client.ui.PluginPanel;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
class ProfilesPanel
|
||||
extends PluginPanel {
|
||||
private static final Logger log = LoggerFactory.getLogger(ProfilesPanel.class);
|
||||
private static final String ACCOUNT_USERNAME = "Account Username";
|
||||
private static final String ACCOUNT_LABEL = "Account Label";
|
||||
private static final String PASSWORD_LABEL = "Account Password";
|
||||
private static final Dimension PREFERRED_SIZE = new Dimension(205, 30);
|
||||
private static final Dimension MINIMUM_SIZE = new Dimension(0, 30);
|
||||
private final Client client;
|
||||
private static ProfilesConfig profilesConfig;
|
||||
private final JTextField txtAccountLabel = new JTextField("Account Label");
|
||||
private final JPasswordField txtAccountLogin = new JPasswordField("Account Username");
|
||||
private final JPasswordField txtPasswordLogin = new JPasswordField("Account Password");
|
||||
private final JPanel profilesPanel = new JPanel();
|
||||
private GridBagConstraints c;
|
||||
|
||||
@Inject
|
||||
public ProfilesPanel(Client client, final ProfilesConfig config) {
|
||||
this.client = client;
|
||||
profilesConfig = config;
|
||||
this.setBorder(new EmptyBorder(18, 10, 0, 10));
|
||||
this.setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||
this.setLayout(new GridBagLayout());
|
||||
this.c = new GridBagConstraints();
|
||||
this.c.fill = 2;
|
||||
this.c.gridx = 0;
|
||||
this.c.gridy = 0;
|
||||
this.c.weightx = 1.0;
|
||||
this.c.weighty = 0.0;
|
||||
this.c.insets = new Insets(0, 0, 4, 0);
|
||||
this.txtAccountLabel.setPreferredSize(PREFERRED_SIZE);
|
||||
this.txtAccountLabel.setForeground(ColorScheme.MEDIUM_GRAY_COLOR);
|
||||
this.txtAccountLabel.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||
this.txtAccountLabel.setMinimumSize(MINIMUM_SIZE);
|
||||
this.txtAccountLabel.addFocusListener(new FocusListener(){
|
||||
|
||||
@Override
|
||||
public void focusGained(FocusEvent e) {
|
||||
if (ProfilesPanel.this.txtAccountLabel.getText().equals(ProfilesPanel.ACCOUNT_LABEL)) {
|
||||
ProfilesPanel.this.txtAccountLabel.setText("");
|
||||
ProfilesPanel.this.txtAccountLabel.setForeground(ColorScheme.LIGHT_GRAY_COLOR);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusLost(FocusEvent e) {
|
||||
if (ProfilesPanel.this.txtAccountLabel.getText().isEmpty()) {
|
||||
ProfilesPanel.this.txtAccountLabel.setForeground(ColorScheme.MEDIUM_GRAY_COLOR);
|
||||
ProfilesPanel.this.txtAccountLabel.setText(ProfilesPanel.ACCOUNT_LABEL);
|
||||
}
|
||||
}
|
||||
});
|
||||
this.add((Component)this.txtAccountLabel, this.c);
|
||||
++this.c.gridy;
|
||||
this.txtAccountLogin.setEchoChar('\u0000');
|
||||
this.txtAccountLogin.setPreferredSize(PREFERRED_SIZE);
|
||||
this.txtAccountLogin.setForeground(ColorScheme.MEDIUM_GRAY_COLOR);
|
||||
this.txtAccountLogin.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||
this.txtAccountLogin.setMinimumSize(MINIMUM_SIZE);
|
||||
this.txtAccountLogin.addFocusListener(new FocusListener(){
|
||||
|
||||
@Override
|
||||
public void focusGained(FocusEvent e) {
|
||||
if (ProfilesPanel.ACCOUNT_USERNAME.equals(String.valueOf(ProfilesPanel.this.txtAccountLogin.getPassword()))) {
|
||||
ProfilesPanel.this.txtAccountLogin.setText("");
|
||||
if (config.isStreamerMode()) {
|
||||
ProfilesPanel.this.txtAccountLogin.setEchoChar('*');
|
||||
}
|
||||
ProfilesPanel.this.txtAccountLogin.setForeground(ColorScheme.LIGHT_GRAY_COLOR);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusLost(FocusEvent e) {
|
||||
if (ProfilesPanel.this.txtAccountLogin.getPassword().length == 0) {
|
||||
ProfilesPanel.this.txtAccountLogin.setForeground(ColorScheme.MEDIUM_GRAY_COLOR);
|
||||
ProfilesPanel.this.txtAccountLogin.setText(ProfilesPanel.ACCOUNT_USERNAME);
|
||||
ProfilesPanel.this.txtAccountLogin.setEchoChar('\u0000');
|
||||
}
|
||||
}
|
||||
});
|
||||
this.add((Component)this.txtAccountLogin, this.c);
|
||||
++this.c.gridy;
|
||||
this.txtPasswordLogin.setEchoChar('\u0000');
|
||||
this.txtPasswordLogin.setPreferredSize(PREFERRED_SIZE);
|
||||
this.txtPasswordLogin.setForeground(ColorScheme.MEDIUM_GRAY_COLOR);
|
||||
this.txtPasswordLogin.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||
this.txtPasswordLogin.setToolTipText("Account password");
|
||||
this.txtPasswordLogin.setMinimumSize(MINIMUM_SIZE);
|
||||
this.txtPasswordLogin.addFocusListener(new FocusListener(){
|
||||
|
||||
@Override
|
||||
public void focusGained(FocusEvent e) {
|
||||
if (ProfilesPanel.PASSWORD_LABEL.equals(String.valueOf(ProfilesPanel.this.txtPasswordLogin.getPassword()))) {
|
||||
ProfilesPanel.this.txtPasswordLogin.setText("");
|
||||
ProfilesPanel.this.txtPasswordLogin.setEchoChar('*');
|
||||
ProfilesPanel.this.txtPasswordLogin.setForeground(ColorScheme.LIGHT_GRAY_COLOR);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusLost(FocusEvent e) {
|
||||
if (ProfilesPanel.this.txtPasswordLogin.getPassword().length == 0) {
|
||||
ProfilesPanel.this.txtPasswordLogin.setForeground(ColorScheme.MEDIUM_GRAY_COLOR);
|
||||
ProfilesPanel.this.txtPasswordLogin.setText(ProfilesPanel.PASSWORD_LABEL);
|
||||
ProfilesPanel.this.txtPasswordLogin.setEchoChar('\u0000');
|
||||
}
|
||||
}
|
||||
});
|
||||
if (config.rememberPassword()) {
|
||||
this.add((Component)this.txtPasswordLogin, this.c);
|
||||
++this.c.gridy;
|
||||
}
|
||||
this.c.insets = new Insets(0, 0, 15, 0);
|
||||
final JButton btnAddAccount = new JButton("Add Account");
|
||||
btnAddAccount.setPreferredSize(PREFERRED_SIZE);
|
||||
btnAddAccount.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||
btnAddAccount.setMinimumSize(MINIMUM_SIZE);
|
||||
btnAddAccount.addActionListener(e -> {
|
||||
String labelText = String.valueOf(this.txtAccountLabel.getText());
|
||||
String loginText = String.valueOf(this.txtAccountLogin.getPassword());
|
||||
String passwordText = String.valueOf(this.txtPasswordLogin.getPassword());
|
||||
if (labelText.equals(ACCOUNT_LABEL) || loginText.equals(ACCOUNT_USERNAME)) {
|
||||
return;
|
||||
}
|
||||
String data = config.rememberPassword() && this.txtPasswordLogin.getPassword() != null ? labelText + ":" + loginText + ":" + passwordText : labelText + ":" + loginText;
|
||||
log.info(data);
|
||||
this.addAccount(data);
|
||||
ProfilesPanel.addProfile(data);
|
||||
this.txtAccountLabel.setText(ACCOUNT_LABEL);
|
||||
this.txtAccountLabel.setForeground(ColorScheme.MEDIUM_GRAY_COLOR);
|
||||
this.txtAccountLogin.setText(ACCOUNT_USERNAME);
|
||||
this.txtAccountLogin.setEchoChar('\u0000');
|
||||
this.txtAccountLogin.setForeground(ColorScheme.MEDIUM_GRAY_COLOR);
|
||||
this.txtPasswordLogin.setText(PASSWORD_LABEL);
|
||||
this.txtPasswordLogin.setEchoChar('\u0000');
|
||||
this.txtPasswordLogin.setForeground(ColorScheme.MEDIUM_GRAY_COLOR);
|
||||
});
|
||||
this.txtAccountLogin.addKeyListener(new KeyAdapter(){
|
||||
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e) {
|
||||
if (e.getKeyCode() == 10) {
|
||||
btnAddAccount.doClick();
|
||||
btnAddAccount.requestFocus();
|
||||
}
|
||||
}
|
||||
});
|
||||
this.txtAccountLogin.addMouseListener(new MouseListener(){
|
||||
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(MouseEvent e) {
|
||||
}
|
||||
});
|
||||
this.add((Component)btnAddAccount, this.c);
|
||||
++this.c.gridy;
|
||||
this.profilesPanel.setLayout(new GridBagLayout());
|
||||
this.add((Component)this.profilesPanel, this.c);
|
||||
this.c.gridy = 0;
|
||||
this.c.insets = new Insets(0, 0, 5, 0);
|
||||
this.addAccounts(config.profilesData());
|
||||
}
|
||||
|
||||
void redrawProfiles() {
|
||||
this.profilesPanel.removeAll();
|
||||
this.c.gridy = 0;
|
||||
this.addAccounts(profilesConfig.profilesData());
|
||||
}
|
||||
|
||||
private void addAccount(String data) {
|
||||
ProfilePanel profile = new ProfilePanel(this.client, data, profilesConfig);
|
||||
++this.c.gridy;
|
||||
this.profilesPanel.add((Component)profile, this.c);
|
||||
this.revalidate();
|
||||
this.repaint();
|
||||
}
|
||||
|
||||
void addAccounts(String data) {
|
||||
if (!(data = data.trim()).contains(":")) {
|
||||
return;
|
||||
}
|
||||
Arrays.stream(data.split("\\n")).forEach(this::addAccount);
|
||||
}
|
||||
|
||||
static void addProfile(String data) {
|
||||
profilesConfig.profilesData(profilesConfig.profilesData() + data + "\n");
|
||||
}
|
||||
|
||||
static void removeProfile(String data) {
|
||||
profilesConfig.profilesData(profilesConfig.profilesData().replaceAll(data + "\\n", ""));
|
||||
}
|
||||
|
||||
@Slf4j
|
||||
class ProfilesPanel extends PluginPanel
|
||||
{
|
||||
private static final int iterations = 100000;
|
||||
private static final String UNLOCK_PASSWORD = "Encryption Password";
|
||||
private static final String LOAD_ACCOUNTS = "Load Accounts";
|
||||
private static final String ACCOUNT_USERNAME = "Account Username";
|
||||
private static final String ACCOUNT_LABEL = "Account Label";
|
||||
private static final String PASSWORD_LABEL = "Account Password";
|
||||
private static final Dimension PREFERRED_SIZE = new Dimension(PluginPanel.PANEL_WIDTH - 20, 30);
|
||||
private static final Dimension MINIMUM_SIZE = new Dimension(0, 30);
|
||||
|
||||
private final Client client;
|
||||
private static ProfilesConfig profilesConfig;
|
||||
|
||||
private final JPasswordField txtDecryptPassword = new JPasswordField(UNLOCK_PASSWORD);
|
||||
private final JButton btnLoadAccounts = new JButton(LOAD_ACCOUNTS);
|
||||
private final JTextField txtAccountLabel = new JTextField(ACCOUNT_LABEL);
|
||||
private final JPasswordField txtAccountLogin = new JPasswordField(ACCOUNT_USERNAME);
|
||||
private final JPasswordField txtPasswordLogin = new JPasswordField(PASSWORD_LABEL);
|
||||
private final JPanel profilesPanel = new JPanel();
|
||||
private GridBagConstraints c;
|
||||
|
||||
@Inject
|
||||
public ProfilesPanel(Client client, ProfilesConfig config)
|
||||
{
|
||||
super();
|
||||
this.client = client;
|
||||
profilesConfig = config;
|
||||
|
||||
setBorder(new EmptyBorder(18, 10, 0, 10));
|
||||
setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||
setLayout(new GridBagLayout());
|
||||
|
||||
c = new GridBagConstraints();
|
||||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
c.gridx = 0;
|
||||
c.gridy = 0;
|
||||
c.weightx = 1;
|
||||
c.weighty = 0;
|
||||
c.insets = new Insets(0, 0, 4, 0);
|
||||
|
||||
txtDecryptPassword.setEchoChar((char) 0);
|
||||
txtDecryptPassword.setPreferredSize(PREFERRED_SIZE);
|
||||
txtDecryptPassword.setForeground(ColorScheme.MEDIUM_GRAY_COLOR);
|
||||
txtDecryptPassword.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||
txtDecryptPassword.setMinimumSize(MINIMUM_SIZE);
|
||||
txtDecryptPassword.setToolTipText(UNLOCK_PASSWORD);
|
||||
txtDecryptPassword.addFocusListener(new FocusListener()
|
||||
{
|
||||
@Override
|
||||
public void focusGained(FocusEvent e)
|
||||
{
|
||||
txtDecryptPassword.setForeground(ColorScheme.LIGHT_GRAY_COLOR);
|
||||
if (String.valueOf(txtDecryptPassword.getPassword()).equals(UNLOCK_PASSWORD))
|
||||
{
|
||||
txtDecryptPassword.setText("");
|
||||
txtDecryptPassword.setEchoChar('*');
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusLost(FocusEvent e)
|
||||
{
|
||||
txtDecryptPassword.setForeground(ColorScheme.MEDIUM_GRAY_COLOR);
|
||||
if (txtDecryptPassword.getPassword().length == 0)
|
||||
{
|
||||
txtDecryptPassword.setText(UNLOCK_PASSWORD);
|
||||
txtDecryptPassword.setEchoChar((char) 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
add(txtDecryptPassword, c);
|
||||
c.gridy++;
|
||||
|
||||
btnLoadAccounts.setPreferredSize(PREFERRED_SIZE);
|
||||
btnLoadAccounts.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||
btnLoadAccounts.setMinimumSize(MINIMUM_SIZE);
|
||||
btnLoadAccounts.setToolTipText(LOAD_ACCOUNTS);
|
||||
btnLoadAccounts.addMouseListener(new MouseListener()
|
||||
{
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e)
|
||||
{
|
||||
try
|
||||
{
|
||||
redrawProfiles();
|
||||
}
|
||||
catch (InvalidKeySpecException | NoSuchAlgorithmException ex)
|
||||
{
|
||||
showErrorMessage("Unable to load data", "Incorrect password!");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(MouseEvent e)
|
||||
{
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
add(btnLoadAccounts, c);
|
||||
c.gridy++;
|
||||
|
||||
txtAccountLabel.setPreferredSize(PREFERRED_SIZE);
|
||||
txtAccountLabel.setForeground(ColorScheme.MEDIUM_GRAY_COLOR);
|
||||
txtAccountLabel.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||
txtAccountLabel.setMinimumSize(MINIMUM_SIZE);
|
||||
txtAccountLabel.addFocusListener(new FocusListener()
|
||||
{
|
||||
@Override
|
||||
public void focusGained(FocusEvent e)
|
||||
{
|
||||
if (txtAccountLabel.getText().equals(ACCOUNT_LABEL))
|
||||
{
|
||||
txtAccountLabel.setText("");
|
||||
txtAccountLabel.setForeground(ColorScheme.LIGHT_GRAY_COLOR);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusLost(FocusEvent e)
|
||||
{
|
||||
if (txtAccountLabel.getText().isEmpty())
|
||||
{
|
||||
txtAccountLabel.setForeground(ColorScheme.MEDIUM_GRAY_COLOR);
|
||||
txtAccountLabel.setText(ACCOUNT_LABEL);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
add(txtAccountLabel, c);
|
||||
c.gridy++;
|
||||
|
||||
// Do not hide username characters until they focus or if in streamer mode
|
||||
txtAccountLogin.setEchoChar((char) 0);
|
||||
txtAccountLogin.setPreferredSize(PREFERRED_SIZE);
|
||||
txtAccountLogin.setForeground(ColorScheme.MEDIUM_GRAY_COLOR);
|
||||
txtAccountLogin.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||
txtAccountLogin.setMinimumSize(MINIMUM_SIZE);
|
||||
txtAccountLogin.addFocusListener(new FocusListener()
|
||||
{
|
||||
@Override
|
||||
public void focusGained(FocusEvent e)
|
||||
{
|
||||
if (ACCOUNT_USERNAME.equals(String.valueOf(txtAccountLogin.getPassword())))
|
||||
{
|
||||
txtAccountLogin.setText("");
|
||||
if (config.isStreamerMode())
|
||||
{
|
||||
txtAccountLogin.setEchoChar('*');
|
||||
}
|
||||
txtAccountLogin.setForeground(ColorScheme.LIGHT_GRAY_COLOR);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusLost(FocusEvent e)
|
||||
{
|
||||
if (txtAccountLogin.getPassword().length == 0)
|
||||
{
|
||||
txtAccountLogin.setForeground(ColorScheme.MEDIUM_GRAY_COLOR);
|
||||
txtAccountLogin.setText(ACCOUNT_USERNAME);
|
||||
txtAccountLogin.setEchoChar((char) 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
add(txtAccountLogin, c);
|
||||
c.gridy++;
|
||||
|
||||
txtPasswordLogin.setEchoChar((char) 0);
|
||||
txtPasswordLogin.setPreferredSize(PREFERRED_SIZE);
|
||||
txtPasswordLogin.setForeground(ColorScheme.MEDIUM_GRAY_COLOR);
|
||||
txtPasswordLogin.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||
txtPasswordLogin.setToolTipText(PASSWORD_LABEL);
|
||||
txtPasswordLogin.setMinimumSize(MINIMUM_SIZE);
|
||||
txtPasswordLogin.addFocusListener(new FocusListener()
|
||||
{
|
||||
@Override
|
||||
public void focusGained(FocusEvent e)
|
||||
{
|
||||
if (PASSWORD_LABEL.equals(String.valueOf(txtPasswordLogin.getPassword())))
|
||||
{
|
||||
txtPasswordLogin.setText("");
|
||||
txtPasswordLogin.setEchoChar('*');
|
||||
txtPasswordLogin.setForeground(ColorScheme.LIGHT_GRAY_COLOR);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusLost(FocusEvent e)
|
||||
{
|
||||
if (txtPasswordLogin.getPassword().length == 0)
|
||||
{
|
||||
txtPasswordLogin.setForeground(ColorScheme.MEDIUM_GRAY_COLOR);
|
||||
txtPasswordLogin.setText(PASSWORD_LABEL);
|
||||
txtPasswordLogin.setEchoChar((char) 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if (config.rememberPassword())
|
||||
{
|
||||
add(txtPasswordLogin, c);
|
||||
c.gridy++;
|
||||
}
|
||||
c.insets = new Insets(0, 0, 15, 0);
|
||||
|
||||
JButton btnAddAccount = new JButton("Add Account");
|
||||
btnAddAccount.setPreferredSize(PREFERRED_SIZE);
|
||||
btnAddAccount.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||
btnAddAccount.setMinimumSize(MINIMUM_SIZE);
|
||||
btnAddAccount.addActionListener(e ->
|
||||
{
|
||||
String labelText = String.valueOf(txtAccountLabel.getText());
|
||||
String loginText = String.valueOf(txtAccountLogin.getPassword());
|
||||
String passwordText = String.valueOf(txtPasswordLogin.getPassword());
|
||||
|
||||
if (labelText.equals(ACCOUNT_LABEL) || loginText.equals(ACCOUNT_USERNAME))
|
||||
{
|
||||
return;
|
||||
}
|
||||
String data;
|
||||
if (config.rememberPassword() && txtPasswordLogin.getPassword() != null)
|
||||
{
|
||||
data = labelText + ":" + loginText + ":" + passwordText;
|
||||
}
|
||||
else
|
||||
{
|
||||
data = labelText + ":" + loginText;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if(!addProfile(data))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (InvalidKeySpecException | NoSuchAlgorithmException ex)
|
||||
{
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
this.addAccount(data);
|
||||
|
||||
txtAccountLabel.setText(ACCOUNT_LABEL);
|
||||
txtAccountLabel.setForeground(ColorScheme.MEDIUM_GRAY_COLOR);
|
||||
|
||||
txtAccountLogin.setText(ACCOUNT_USERNAME);
|
||||
txtAccountLogin.setEchoChar((char) 0);
|
||||
txtAccountLogin.setForeground(ColorScheme.MEDIUM_GRAY_COLOR);
|
||||
|
||||
txtPasswordLogin.setText(PASSWORD_LABEL);
|
||||
txtPasswordLogin.setEchoChar((char) 0);
|
||||
txtPasswordLogin.setForeground(ColorScheme.MEDIUM_GRAY_COLOR);
|
||||
});
|
||||
|
||||
txtAccountLogin.addKeyListener(new KeyAdapter()
|
||||
{
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e)
|
||||
{
|
||||
if (e.getKeyCode() == KeyEvent.VK_ENTER)
|
||||
{
|
||||
btnAddAccount.doClick();
|
||||
btnAddAccount.requestFocus();
|
||||
}
|
||||
}
|
||||
});
|
||||
txtAccountLogin.addMouseListener(new MouseListener()
|
||||
{
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent e)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(MouseEvent e)
|
||||
{
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
add(btnAddAccount, c);
|
||||
c.gridy++;
|
||||
|
||||
profilesPanel.setLayout(new GridBagLayout());
|
||||
add(profilesPanel, c);
|
||||
c.gridy = 0;
|
||||
c.insets = new Insets(0, 0, 5, 0);
|
||||
|
||||
//addAccounts(config.profilesData());
|
||||
}
|
||||
|
||||
void redrawProfiles() throws InvalidKeySpecException, NoSuchAlgorithmException
|
||||
{
|
||||
profilesPanel.removeAll();
|
||||
c.gridy = 0;
|
||||
addAccounts(getProfileData());
|
||||
|
||||
revalidate();
|
||||
repaint();
|
||||
}
|
||||
|
||||
private void addAccount(String data)
|
||||
{
|
||||
ProfilePanel profile = new ProfilePanel(client, data, profilesConfig, this);
|
||||
c.gridy++;
|
||||
profilesPanel.add(profile, c);
|
||||
|
||||
revalidate();
|
||||
repaint();
|
||||
}
|
||||
|
||||
void addAccounts(String data)
|
||||
{
|
||||
//log.info("Data: " + data);
|
||||
data = data.trim();
|
||||
if (!data.contains(":"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
Arrays.stream(data.split("\\n")).forEach(this::addAccount);
|
||||
}
|
||||
|
||||
boolean addProfile(String data) throws InvalidKeySpecException, NoSuchAlgorithmException
|
||||
{
|
||||
return setProfileData(
|
||||
getProfileData() + data + "\n");
|
||||
}
|
||||
|
||||
void removeProfile(String data) throws InvalidKeySpecException, NoSuchAlgorithmException
|
||||
{
|
||||
setProfileData(
|
||||
getProfileData().replaceAll(data + "\\n", ""));
|
||||
redrawProfiles();
|
||||
}
|
||||
|
||||
void setSalt(byte[] bytes)
|
||||
{
|
||||
profilesConfig.salt(base64Encode(bytes));
|
||||
}
|
||||
|
||||
byte[] getSalt()
|
||||
{
|
||||
if(profilesConfig.salt().length() == 0)
|
||||
{
|
||||
return new byte[0];
|
||||
}
|
||||
return base64Decode(profilesConfig.salt());
|
||||
}
|
||||
|
||||
SecretKey getAesKey() throws NoSuchAlgorithmException, InvalidKeySpecException
|
||||
{
|
||||
if(getSalt().length == 0)
|
||||
{
|
||||
byte[] b = new byte[16];
|
||||
SecureRandom.getInstanceStrong().nextBytes(b);
|
||||
setSalt(b);
|
||||
}
|
||||
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
|
||||
KeySpec spec = new PBEKeySpec(txtDecryptPassword.getPassword(), getSalt(), iterations, 128);
|
||||
SecretKey key = factory.generateSecret(spec);
|
||||
return key;
|
||||
}
|
||||
|
||||
String getProfileData() throws InvalidKeySpecException, NoSuchAlgorithmException
|
||||
{
|
||||
String tmp = profilesConfig.profilesData();
|
||||
if(tmp.startsWith("¬"))
|
||||
{
|
||||
if(txtDecryptPassword.getPassword().length == 0 || String.valueOf(txtDecryptPassword.getPassword()).equals(UNLOCK_PASSWORD))
|
||||
{
|
||||
showErrorMessage("Unable to load data", "Please enter a password!");
|
||||
return tmp;
|
||||
}
|
||||
tmp = tmp.substring(1);
|
||||
return decryptText(base64Decode(tmp), getAesKey());
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
boolean setProfileData(String data) throws InvalidKeySpecException, NoSuchAlgorithmException
|
||||
{
|
||||
if(txtDecryptPassword.getPassword().length == 0 || String.valueOf(txtDecryptPassword.getPassword()).equals(UNLOCK_PASSWORD))
|
||||
{
|
||||
showErrorMessage("Unable to save data", "Please enter a password!");
|
||||
return false;
|
||||
}
|
||||
byte[] enc = encryptText(data, getAesKey());
|
||||
if(enc.length == 0)
|
||||
return false;
|
||||
String s = "¬"+base64Encode(enc);
|
||||
profilesConfig.profilesData(s);
|
||||
return true;
|
||||
}
|
||||
|
||||
public byte[] base64Decode(String data)
|
||||
{
|
||||
return Base64.getDecoder().decode(data);
|
||||
}
|
||||
|
||||
public String base64Encode(byte[] data)
|
||||
{
|
||||
return Base64.getEncoder().encodeToString(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts login info
|
||||
*
|
||||
* @param text text to encrypt
|
||||
* @return encrypted string
|
||||
*/
|
||||
public static byte[] encryptText(String text, SecretKey aesKey)
|
||||
{
|
||||
try
|
||||
{
|
||||
Cipher cipher = Cipher.getInstance("AES");
|
||||
SecretKeySpec newKey = new SecretKeySpec(aesKey.getEncoded(), "AES");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, newKey);
|
||||
return cipher.doFinal(text.getBytes());
|
||||
}
|
||||
catch (NoSuchAlgorithmException | IllegalBlockSizeException | InvalidKeyException | BadPaddingException | NoSuchPaddingException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
public static String decryptText(byte[] enc, SecretKey aesKey)
|
||||
{
|
||||
try
|
||||
{
|
||||
Cipher cipher = Cipher.getInstance("AES");
|
||||
SecretKeySpec newKey = new SecretKeySpec(aesKey.getEncoded(), "AES");
|
||||
cipher.init(Cipher.DECRYPT_MODE, newKey);
|
||||
return new String(cipher.doFinal(enc));
|
||||
}
|
||||
catch (NoSuchAlgorithmException | IllegalBlockSizeException | InvalidKeyException | BadPaddingException | NoSuchPaddingException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public static void showErrorMessage(String title, String text)
|
||||
{
|
||||
SwingUtilities.invokeLater(() -> JOptionPane.showMessageDialog(null,
|
||||
text,
|
||||
title,
|
||||
JOptionPane.ERROR_MESSAGE));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,30 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.139.
|
||||
* Copyright (c) 2019, Spedwards <https://github.com/Spedwards>
|
||||
* 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.profiles;
|
||||
|
||||
import com.google.inject.Provides;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.Key;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
@@ -14,9 +34,10 @@ import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
@@ -25,112 +46,85 @@ import net.runelite.client.plugins.PluginType;
|
||||
import net.runelite.client.ui.ClientToolbar;
|
||||
import net.runelite.client.ui.NavigationButton;
|
||||
import net.runelite.client.util.ImageUtil;
|
||||
import javax.inject.Inject;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
@PluginDescriptor(
|
||||
|
||||
name="Account Switcher",
|
||||
description="Allow for a allows you to easily switch between multiple OSRS Accounts",
|
||||
tags={"profile", "account", "login", "log in"},
|
||||
type = PluginType.UTILITY
|
||||
name = "Account Switcher",
|
||||
description = "Allow for a allows you to easily switch between multiple OSRS Accounts",
|
||||
tags = {"profile", "account", "login", "log in", "pklite"},
|
||||
type = PluginType.UTILITY
|
||||
)
|
||||
public class ProfilesPlugin extends Plugin
|
||||
{
|
||||
@Inject
|
||||
private ClientToolbar clientToolbar;
|
||||
|
||||
public class ProfilesPlugin
|
||||
extends Plugin {
|
||||
@Inject
|
||||
private ClientToolbar clientToolbar;
|
||||
@Inject
|
||||
private Client client;
|
||||
@Inject
|
||||
private ProfilesConfig config;
|
||||
private ProfilesPanel panel;
|
||||
private NavigationButton navButton;
|
||||
String text = "Hello World";
|
||||
private static String key = "Bar12345Bar12345";
|
||||
private static Key aesKey = new SecretKeySpec(key.getBytes(), "AES");
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Provides
|
||||
ProfilesConfig getConfig(ConfigManager configManager) {
|
||||
return configManager.getConfig(ProfilesConfig.class);
|
||||
}
|
||||
@Inject
|
||||
private ProfilesConfig config;
|
||||
|
||||
@Override
|
||||
protected void startUp() throws Exception {
|
||||
this.panel = this.injector.getInstance(ProfilesPanel.class);
|
||||
BufferedImage icon = ImageUtil.getResourceStreamFromClass(this.getClass(), "/net/runelite/client/plugins/profiles/profiles_icon.png");
|
||||
this.navButton = NavigationButton.builder().tooltip("Profiles").icon(icon).priority(8).panel(this.panel).build();
|
||||
this.clientToolbar.addNavigation(this.navButton);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown() {
|
||||
this.clientToolbar.removeNavigation(this.navButton);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
private void onConfigChanged(ConfigChanged event) throws Exception {
|
||||
if (event.getGroup().equals("profiles") && event.getKey().equals("rememberPassword")) {
|
||||
this.panel = this.injector.getInstance(ProfilesPanel.class);
|
||||
this.shutDown();
|
||||
this.startUp();
|
||||
}
|
||||
}
|
||||
private ProfilesPanel panel;
|
||||
private NavigationButton navButton;
|
||||
|
||||
public static String decryptText(String text) {
|
||||
byte[] bb = new byte[text.length()];
|
||||
for (int i = 0; i < text.length(); ++i) {
|
||||
bb[i] = (byte)text.charAt(i);
|
||||
}
|
||||
Cipher cipher = null;
|
||||
try {
|
||||
cipher = Cipher.getInstance("AES");
|
||||
}
|
||||
catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
cipher.init(2, aesKey);
|
||||
}
|
||||
catch (InvalidKeyException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
Logger.getLogger("EncryptionLogger").info("Decrypted " + text + " to " + new String(cipher.doFinal(bb)));
|
||||
return new String(cipher.doFinal(bb));
|
||||
}
|
||||
catch (BadPaddingException | IllegalBlockSizeException e) {
|
||||
e.printStackTrace();
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public static String encryptText(String text) {
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance("AES");
|
||||
cipher.init(1, aesKey);
|
||||
byte[] encrypted = cipher.doFinal(text.getBytes());
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (byte b : encrypted) {
|
||||
sb.append((char)b);
|
||||
}
|
||||
Logger.getLogger("EncryptionLogger").info("Encrypted " + text + " to " + sb.toString());
|
||||
return sb.toString();
|
||||
}
|
||||
catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (NoSuchPaddingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (BadPaddingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (IllegalBlockSizeException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (InvalidKeyException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
@Provides
|
||||
ProfilesConfig getConfig(ConfigManager configManager)
|
||||
{
|
||||
return configManager.getConfig(ProfilesConfig.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startUp() throws Exception
|
||||
{
|
||||
panel = injector.getInstance(ProfilesPanel.class);
|
||||
|
||||
final BufferedImage icon = ImageUtil.getResourceStreamFromClass(getClass(), "profiles_icon.png");
|
||||
|
||||
navButton = NavigationButton.builder()
|
||||
.tooltip("Profiles")
|
||||
.icon(icon)
|
||||
.priority(8)
|
||||
.panel(panel)
|
||||
.build();
|
||||
|
||||
clientToolbar.addNavigation(navButton);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown()
|
||||
{
|
||||
clientToolbar.removeNavigation(navButton);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
void onGameStateChanged(GameStateChanged event)
|
||||
{
|
||||
if (event.getGameState().equals(GameState.LOGIN_SCREEN) && config.switchPanel())
|
||||
{
|
||||
if (!navButton.isSelected())
|
||||
{
|
||||
navButton.getOnSelect().run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
private void onConfigChanged(ConfigChanged event) throws Exception
|
||||
{
|
||||
if (event.getGroup().equals("profiles"))
|
||||
{
|
||||
if (event.getKey().equals("rememberPassword"))
|
||||
{
|
||||
panel = injector.getInstance(ProfilesPanel.class);
|
||||
this.shutDown();
|
||||
this.startUp();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user