aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main/java/SkyHanniInstallerFrame.java676
-rw-r--r--src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt23
-rw-r--r--src/main/java/at/hannibal2/skyhanni/api/CollectionAPI.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/FeatureToggle.kt15
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/Storage.java17
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt54
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/commands/SimpleCommand.java4
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/AshfangConfig.java9
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/BazaarConfig.java5
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/BingoConfig.java9
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/ChatConfig.java27
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/CommandsConfig.java4
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/DamageIndicatorConfig.java34
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/DevConfig.java6
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/DianaConfig.java24
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/DungeonConfig.java20
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/FishingConfig.java12
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/GardenConfig.java117
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/GhostCounterConfig.java2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/InventoryConfig.java23
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/ItemAbilityConfig.java9
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/MinionsConfig.java12
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/MiscConfig.java190
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/MobsConfig.java11
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/OldHidden.java3
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/RiftConfig.java39
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/SlayerConfig.java106
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/SummoningsConfig.java5
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/ChatManager.kt4
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/EntityData.kt5
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/GardenCropMilestones.kt185
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/MayorElection.kt9
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/ProfileStorageData.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/SackAPI.kt48
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/SlayerAPI.kt4
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/TitleUtils.kt12
-rw-r--r--src/main/java/at/hannibal2/skyhanni/events/SackChangeEvent.kt9
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/bazaar/BazaarData.kt1
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/bazaar/BazaarDataHolder.kt24
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/bingo/MinionCraftHelper.kt3
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/chat/ChatFilter.kt11
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/chat/Translator.kt218
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/cosmetics/CosmeticFollowingLine.kt129
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/damageindicator/BossType.kt9
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/damageindicator/DamageIndicatorManager.kt22
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/damageindicator/MobFinder.kt14
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/event/diana/BurrowWarpHelper.kt24
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/event/diana/GriffinPetWarning.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/event/diana/InquisitorWaypointShare.kt15
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/fame/AccountUpgradeReminder.kt5
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/fame/CityProjectFeatures.kt11
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/fishing/FishingTimer.kt10
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/TrophyFishFillet.kt3
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/AnitaMedalProfit.kt8
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/FarmingFortuneDisplay.kt18
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/GardenAPI.kt67
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/GardenCropMilestoneFix.kt19
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/GardenLevelDisplay.kt11
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/GardenNextJacobContest.kt273
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/GardenOptimalSpeed.kt3
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/GardenPlotBorders.kt120
-rwxr-xr-xsrc/main/java/at/hannibal2/skyhanni/features/garden/GardenYawAndPitch.kt14
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/ToolTooltipTweaks.kt8
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/composter/ComposterDisplay.kt7
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/composter/GardenComposterInventoryFeatures.kt5
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/farming/CropMoneyDisplay.kt35
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/farming/CropSpeedMeter.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/farming/FarmingWeightDisplay.kt70
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenBestCropTime.kt14
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenBurrowingSporesNotifier.kt3
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenCropMilestoneDisplay.kt30
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenCropSpeed.kt29
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenCustomKeybinds.kt14
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/farming/WildStrawberryDyeNotification.kt3
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/farming/WrongFungiCutterWarning.kt3
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/CaptureFarmingGear.kt60
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FFGuideGUI.kt42
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FFStats.kt30
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FarmingItems.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FarmingReforges.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FortuneStats.kt4
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FortuneUpgrades.kt8
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/TODO list66
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/pages/OverviewPage.kt43
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/inventory/AnitaExtraFarmingFortune.kt82
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/inventory/GardenCropMilestoneAverage.kt45
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/inventory/GardenCropMilestoneInventory.kt77
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/inventory/GardenNextPlotPrice.kt6
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorFeatures.kt125
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorTimer.kt3
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/visitor/VisitorReward.kt6
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/inventory/ItemDisplayOverlayFeatures.kt19
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/inventory/SackDisplay.kt4
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/itemabilities/abilitycooldown/ItemAbilityCooldown.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/BestiaryData.kt21
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/ChatPeek.kt3
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/ChickenHeadTimer.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/EnderNodeTracker.kt12
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/HarpFeatures.kt3
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/NonGodPotEffectDisplay.kt5
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/PasteIntoSigns.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/PetExpTooltip.kt51
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/RealTime.kt24
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/ServerRestartTitle.kt3
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/SuperpairsClicksAlert.kt60
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/TimeFeatures.kt46
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/discordrpc/DiscordStatus.kt8
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValue.kt20
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/Category.kt3
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/DefaultConfigFeatures.kt99
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/DefaultConfigOptionGui.kt197
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/FeatureToggleProcessor.kt81
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/FeatureToggleableOption.kt9
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/ResetSuggestionState.kt10
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/trevor/TrevorFeatures.kt5
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/trevor/TrevorSolver.kt6
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/mobs/MobHighlight.kt6
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/CrimsonIsleReputationHelper.kt10
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/dailykuudra/DailyKuudraBossHelper.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/dailyquest/DailyQuestHelper.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/miniboss/DailyMiniBossHelper.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/rift/area/dreadfarm/VoltHighlighter.kt4
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/rift/area/wyldwoods/ShyCruxWarnings.kt3
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/rift/everywhere/motes/ShowMotesNpcSellPrice.kt35
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/slayer/HighlightSlayerMiniBoss.kt52
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerBossSpawnSoon.kt3
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerItemProfitTracker.kt10
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerMiniBossFeatures.kt81
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerQuestWarning.kt5
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerRngMeterDisplay.kt3
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/slayer/VampireSlayerFeatures.kt40
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/slayer/blaze/BlazeSlayerFirePitsWarning.kt3
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/slayer/enderman/EndermanSlayerFeatures.kt135
-rw-r--r--src/main/java/at/hannibal2/skyhanni/test/SkyHanniTestCommand.kt29
-rw-r--r--src/main/java/at/hannibal2/skyhanni/test/TestExportTools.kt5
-rw-r--r--src/main/java/at/hannibal2/skyhanni/test/TestShowSlotNumber.kt4
-rw-r--r--src/main/java/at/hannibal2/skyhanni/test/command/CopyErrorCommand.kt7
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/APIUtil.kt35
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/ClipboardUtils.kt12
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/EntityUtils.kt9
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/GuiRenderUtils.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/ItemUtils.kt11
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/LorenzUtils.kt47
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt35
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/OSUtils.kt15
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/RenderUtils.kt32
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/SimpleTimeMark.kt6
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/SkyBlockItemModifierUtils.kt7
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt28
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/TimeUtils.kt10
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/jsonobjects/AnitaUpgradeCostsJson.java17
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/jsonobjects/GardenJson.java9
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt8
-rw-r--r--src/main/resources/assets/skyhanni/folder.pngbin0 -> 454 bytes
-rw-r--r--src/main/resources/assets/skyhanni/logo.pngbin0 -> 6357 bytes
-rw-r--r--src/test/java/at/hannibal2/skyhanni/test/ItemModifierTest.kt3
156 files changed, 3989 insertions, 1027 deletions
diff --git a/src/main/java/SkyHanniInstallerFrame.java b/src/main/java/SkyHanniInstallerFrame.java
new file mode 100644
index 000000000..878d2a0d2
--- /dev/null
+++ b/src/main/java/SkyHanniInstallerFrame.java
@@ -0,0 +1,676 @@
+import javax.imageio.ImageIO;
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.image.BufferedImage;
+import java.io.*;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.util.Locale;
+import java.util.Objects;
+import java.util.jar.JarFile;
+import java.util.regex.Pattern;
+import java.util.zip.ZipEntry;
+
+public class SkyHanniInstallerFrame extends JFrame implements ActionListener, MouseListener {
+ private static final Pattern IN_MODS_SUBFOLDER = Pattern.compile("1\\.8\\.9[/\\\\]?$");
+ private static final int TOTAL_HEIGHT = 435;
+ private static final int TOTAL_WIDTH = 404;
+ private JLabel logo = null;
+ private JLabel versionInfo = null;
+ private JLabel labelFolder = null;
+ private JPanel panelCenter = null;
+ private JPanel panelBottom = null;
+ private JPanel totalContentPane = null;
+ private JTextArea descriptionText = null;
+ private JTextArea forgeDescriptionText = null;
+ private JTextField textFieldFolderLocation = null;
+ private JButton buttonChooseFolder = null;
+ private JButton buttonInstall = null;
+ private JButton buttonOpenFolder = null;
+ private JButton buttonClose = null;
+ private int x = 0;
+ private int y = 0;
+
+ private int w = TOTAL_WIDTH;
+ private int h;
+ private int margin;
+
+ public SkyHanniInstallerFrame() {
+ try {
+ setName("SkyHanniInstallerFrame");
+ setTitle("SkyHanni Installer");
+ setResizable(false);
+ setSize(TOTAL_WIDTH, TOTAL_HEIGHT);
+ setContentPane(getPanelContentPane());
+
+ getButtonFolder().addActionListener(this);
+ getButtonInstall().addActionListener(this);
+ getButtonOpenFolder().addActionListener(this);
+ getButtonClose().addActionListener(this);
+ getForgeTextArea().addMouseListener(this);
+
+ pack();
+ setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
+
+ getFieldFolder().setText(getModsFolder().getPath());
+ getButtonInstall().setEnabled(true);
+ getButtonInstall().requestFocus();
+ } catch (Exception ex) {
+ showErrorPopup(ex);
+ }
+ }
+
+ public static void main(String[] args) {
+ try {
+ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+ SkyHanniInstallerFrame frame = new SkyHanniInstallerFrame();
+ frame.centerFrame(frame);
+ frame.setVisible(true);
+
+ } catch (Exception ex) {
+ showErrorPopup(ex);
+ }
+ }
+
+ private static String getStacktraceText(Throwable ex) {
+ StringWriter stringWriter = new StringWriter();
+ ex.printStackTrace(new PrintWriter(stringWriter));
+ return stringWriter.toString().replace("\t", " ");
+ }
+
+ private static void showErrorPopup(Throwable ex) {
+ ex.printStackTrace();
+
+ JTextArea textArea = new JTextArea(getStacktraceText(ex));
+ textArea.setEditable(false);
+ Font currentFont = textArea.getFont();
+ Font newFont = new Font(Font.MONOSPACED, currentFont.getStyle(), currentFont.getSize());
+ textArea.setFont(newFont);
+
+ JScrollPane errorScrollPane = new JScrollPane(textArea);
+ errorScrollPane.setPreferredSize(new Dimension(600, 400));
+ JOptionPane.showMessageDialog(null, errorScrollPane, "Error", JOptionPane.ERROR_MESSAGE);
+ }
+
+ private JPanel getPanelContentPane() {
+ if (totalContentPane == null) {
+ try {
+ totalContentPane = new JPanel();
+ totalContentPane.setName("PanelContentPane");
+ totalContentPane.setLayout(new BorderLayout(5, 5));
+ totalContentPane.setPreferredSize(new Dimension(TOTAL_WIDTH, TOTAL_HEIGHT));
+ totalContentPane.add(getPanelCenter(), "Center");
+ totalContentPane.add(getPanelBottom(), "South");
+ } catch (Throwable ivjExc) {
+ showErrorPopup(ivjExc);
+ }
+ }
+ return totalContentPane;
+ }
+
+ private JPanel getPanelCenter() {
+ if (panelCenter == null) {
+ try {
+ (panelCenter = new JPanel()).setName("PanelCenter");
+ panelCenter.setLayout(null);
+ panelCenter.add(getPictureLabel(), getPictureLabel().getName());
+ panelCenter.add(getVersionInfo(), getVersionInfo().getName());
+ panelCenter.add(getTextArea(), getTextArea().getName());
+ panelCenter.add(getForgeTextArea(), getForgeTextArea().getName());
+ panelCenter.add(getLabelFolder(), getLabelFolder().getName());
+ panelCenter.add(getFieldFolder(), getFieldFolder().getName());
+ panelCenter.add(getButtonFolder(), getButtonFolder().getName());
+ } catch (Throwable ivjExc) {
+ showErrorPopup(ivjExc);
+ }
+ }
+ return panelCenter;
+ }
+
+ private JLabel getPictureLabel() {
+ if (logo == null) {
+ try {
+ h = w / 2;
+ margin = 5;
+
+ BufferedImage myPicture = ImageIO.read(Objects.requireNonNull(getClass()
+ .getClassLoader()
+ .getResourceAsStream("assets/skyhanni/logo.png"), "Logo not found."));
+ Image scaled = myPicture.getScaledInstance(w - margin * 2, h - margin, Image.SCALE_SMOOTH);
+ logo = new JLabel(new ImageIcon(scaled));
+ logo.setName("Logo");
+ logo.setBounds(x + margin, y + margin, w - margin * 2, h - margin);
+ logo.setFont(new Font(Font.DIALOG, Font.BOLD, 18));
+ logo.setHorizontalAlignment(SwingConstants.CENTER);
+ logo.setPreferredSize(new Dimension(h * 742 / 537, h));
+
+ y += h;
+ } catch (Throwable ivjExc) {
+ showErrorPopup(ivjExc);
+ }
+ }
+ return logo;
+ }
+
+ private JLabel getVersionInfo() {
+ if (versionInfo == null) {
+ try {
+ h = 25;
+
+ versionInfo = new JLabel();
+ versionInfo.setName("LabelMcVersion");
+ versionInfo.setBounds(x, y, w, h);
+ versionInfo.setFont(new Font(Font.DIALOG, Font.BOLD, 14));
+ versionInfo.setHorizontalAlignment(SwingConstants.CENTER);
+ versionInfo.setPreferredSize(new Dimension(w, h));
+ versionInfo.setText("SkyHanni by hannibal2, Installer by Biscuit");
+
+ y += h;
+ } catch (Throwable ivjExc) {
+ showErrorPopup(ivjExc);
+ }
+ }
+ return versionInfo;
+ }
+
+ private JTextArea getTextArea() {
+ if (descriptionText == null) {
+ try {
+ h = 60;
+ margin = 10;
+
+ descriptionText = new JTextArea();
+ descriptionText.setName("TextArea");
+ descriptionText.setBounds(x + margin, y + margin, w - margin * 2, h - margin);
+ descriptionText.setEditable(false);
+ descriptionText.setHighlighter(null);
+ descriptionText.setEnabled(true);
+ descriptionText.setFont(new Font(Font.DIALOG, Font.PLAIN, 12));
+ descriptionText.setLineWrap(true);
+ descriptionText.setOpaque(false);
+ descriptionText.setPreferredSize(new Dimension(w - margin * 2, h - margin));
+ descriptionText.setText(
+ "This installer will copy SkyHanni into your forge mods folder for you, and replace any old versions that already exist. " +
+ "Close this if you prefer to do this yourself!");
+ descriptionText.setWrapStyleWord(true);
+
+ y += h;
+ } catch (Throwable ivjExc) {
+ showErrorPopup(ivjExc);
+ }
+ }
+ return descriptionText;
+ }
+
+ private JTextArea getForgeTextArea() {
+ if (forgeDescriptionText == null) {
+ try {
+ h = 55;
+ margin = 10;
+
+ forgeDescriptionText = new JTextArea();
+ forgeDescriptionText.setName("TextAreaForge");
+ forgeDescriptionText.setBounds(x + margin, y + margin, w - margin * 2, h - margin);
+ forgeDescriptionText.setEditable(false);
+ forgeDescriptionText.setHighlighter(null);
+ forgeDescriptionText.setEnabled(true);
+ forgeDescriptionText.setFont(new Font(Font.DIALOG, Font.PLAIN, 12));
+ forgeDescriptionText.setLineWrap(true);
+ forgeDescriptionText.setOpaque(false);
+ forgeDescriptionText.setPreferredSize(new Dimension(w - margin * 2, h - margin));
+ forgeDescriptionText.setText(
+ "However, you still need to install Forge client in order to be able to run this mod. Click here to visit the download page for Forge 1.8.9!");
+ forgeDescriptionText.setForeground(Color.BLUE.darker());
+ forgeDescriptionText.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
+ forgeDescriptionText.setWrapStyleWord(true);
+
+ y += h;
+ } catch (Throwable ivjExc) {
+ showErrorPopup(ivjExc);
+ }
+ }
+ return forgeDescriptionText;
+ }
+
+ private JLabel getLabelFolder() {
+ if (labelFolder == null) {
+ h = 16;
+ w = 65;
+
+ x += 10; // Padding
+
+ try {
+ labelFolder = new JLabel();
+ labelFolder.setName("LabelFolder");
+ labelFolder.setBounds(x, y + 2, w, h);
+ labelFolder.setPreferredSize(new Dimension(w, h));
+ labelFolder.setText("Mods Folder");
+ } catch (Throwable ivjExc) {
+ showErrorPopup(ivjExc);
+ }
+
+ x += w;
+ }
+ return labelFolder;
+ }
+
+ private JTextField getFieldFolder() {
+ if (textFieldFolderLocation == null) {
+ h = 20;
+ w = 287;
+
+ try {
+ textFieldFolderLocation = new JTextField();
+ textFieldFolderLocation.setName("FieldFolder");
+ textFieldFolderLocation.setBounds(x, y, w, h);
+ textFieldFolderLocation.setEditable(false);
+ textFieldFolderLocation.setPreferredSize(new Dimension(w, h));
+ } catch (Throwable ivjExc) {
+ showErrorPopup(ivjExc);
+ }
+
+ x += w;
+ }
+ return textFieldFolderLocation;
+ }
+
+ private JButton getButtonFolder() {
+ if (buttonChooseFolder == null) {
+ h = 20;
+ w = 25;
+
+ x += 10; // Padding
+
+ try {
+ BufferedImage myPicture = ImageIO.read(Objects.requireNonNull(getClass()
+ .getClassLoader()
+ .getResourceAsStream("assets/skyhanni/folder.png"), "Folder icon not found."));
+ Image scaled = myPicture.getScaledInstance(w - 8, h - 6, Image.SCALE_SMOOTH);
+ buttonChooseFolder = new JButton(new ImageIcon(scaled));
+ buttonChooseFolder.setName("ButtonFolder");
+ buttonChooseFolder.setBounds(x, y, w, h);
+ buttonChooseFolder.setPreferredSize(new Dimension(w, h));
+ } catch (Throwable ivjExc) {
+ showErrorPopup(ivjExc);
+ }
+ }
+ return buttonChooseFolder;
+ }
+
+ private JPanel getPanelBottom() {
+ if (panelBottom == null) {
+ try {
+ panelBottom = new JPanel();
+ panelBottom.setName("PanelBottom");
+ panelBottom.setLayout(new FlowLayout(FlowLayout.CENTER, 15, 10));
+ panelBottom.setPreferredSize(new Dimension(390, 55));
+ panelBottom.add(getButtonInstall(), getButtonInstall().getName());
+ panelBottom.add(getButtonOpenFolder(), getButtonOpenFolder().getName());
+ panelBottom.add(getButtonClose(), getButtonClose().getName());
+ } catch (Throwable ivjExc) {
+ showErrorPopup(ivjExc);
+ }
+ }
+ return panelBottom;
+ }
+
+ private JButton getButtonInstall() {
+ if (buttonInstall == null) {
+ w = 100;
+ h = 26;
+
+ try {
+ buttonInstall = new JButton();
+ buttonInstall.setName("ButtonInstall");
+ buttonInstall.setPreferredSize(new Dimension(w, h));
+ buttonInstall.setText("Install");
+ } catch (Throwable ivjExc) {
+ showErrorPopup(ivjExc);
+ }
+ }
+ return buttonInstall;
+ }
+
+ private JButton getButtonOpenFolder() {
+ if (buttonOpenFolder == null) {
+ w = 130;
+ h = 26;
+
+ try {
+ buttonOpenFolder = new JButton();
+ buttonOpenFolder.setName("ButtonOpenFolder");
+ buttonOpenFolder.setPreferredSize(new Dimension(w, h));
+ buttonOpenFolder.setText("Open Mods Folder");
+ } catch (Throwable ivjExc) {
+ showErrorPopup(ivjExc);
+ }
+ }
+ return buttonOpenFolder;
+ }
+
+ private JButton getButtonClose() {
+ if (buttonClose == null) {
+ w = 100;
+ h = 26;
+
+ try {
+ (buttonClose = new JButton()).setName("ButtonClose");
+ buttonClose.setPreferredSize(new Dimension(w, h));
+ buttonClose.setText("Cancel");
+ } catch (Throwable ivjExc) {
+ showErrorPopup(ivjExc);
+ }
+ }
+ return buttonClose;
+ }
+
+ public void onFolderSelect() {
+ File currentDirectory = new File(getFieldFolder().getText());
+
+ JFileChooser jFileChooser = new JFileChooser(currentDirectory);
+ jFileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+ jFileChooser.setAcceptAllFileFilterUsed(false);
+ if (jFileChooser.showOpenDialog(this) == 0) {
+ File newDirectory = jFileChooser.getSelectedFile();
+ getFieldFolder().setText(newDirectory.getPath());
+ }
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if (e.getSource() == getButtonClose()) {
+ dispose();
+ System.exit(0);
+ }
+ if (e.getSource() == getButtonFolder()) {
+ onFolderSelect();
+ }
+ if (e.getSource() == getButtonInstall()) {
+ onInstall();
+ }
+ if (e.getSource() == getButtonOpenFolder()) {
+ onOpenFolder();
+ }
+ }
+
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ if (e.getSource() == getForgeTextArea()) {
+ try {
+ Desktop.getDesktop().browse(new URI(
+ "http://files.minecraftforge.net/maven/net/minecraftforge/forge/index_1.8.9.html"));
+ } catch (IOException | URISyntaxException ex) {
+ showErrorPopup(ex);
+ }
+ }
+ }
+
+ public void onInstall() {
+ try {
+ File modsFolder = new File(getFieldFolder().getText());
+ if (!modsFolder.exists()) {
+ showErrorMessage("Folder not found: " + modsFolder.getPath());
+ return;
+ }
+ if (!modsFolder.isDirectory()) {
+ showErrorMessage("Not a folder: " + modsFolder.getPath());
+ return;
+ }
+ tryInstall(modsFolder);
+ } catch (Exception e) {
+ showErrorPopup(e);
+ }
+ }
+
+ private void tryInstall(File modsFolder) {
+ File thisFile = getThisFile();
+
+ if (thisFile != null) {
+ boolean inSubFolder = IN_MODS_SUBFOLDER.matcher(modsFolder.getPath()).find();
+
+ boolean deletingFailure = false;
+ if (modsFolder.isDirectory()) { // Delete in this current folder.
+ boolean failed = findSkyblockAddonsAndDelete(modsFolder.listFiles());
+ if (failed) deletingFailure = true;
+ }
+ if (inSubFolder) { // We are in the 1.8.9 folder, delete in the parent folder as well.
+ if (modsFolder.getParentFile().isDirectory()) {
+ boolean failed = findSkyblockAddonsAndDelete(modsFolder.getParentFile().listFiles());
+ if (failed) deletingFailure = true;
+ }
+ } else { // We are in the main mods folder, but the 1.8.9 subfolder exists... delete in there too.
+ File subFolder = new File(modsFolder, "1.8.9");
+ if (subFolder.exists() && subFolder.isDirectory()) {
+ boolean failed = findSkyblockAddonsAndDelete(subFolder.listFiles());
+ if (failed) deletingFailure = true;
+ }
+ }
+
+ if (deletingFailure) return;
+
+ if (thisFile.isDirectory()) {
+ showErrorMessage("This file is a directory... Are we in a development environment?");
+ return;
+ }
+
+ try {
+ Files.copy(thisFile.toPath(), new File(modsFolder, thisFile.getName()).toPath());
+ } catch (Exception ex) {
+ showErrorPopup(ex);
+ return;
+ }
+
+ showMessage("SkyHanni has been successfully installed into your mods folder.");
+ dispose();
+ System.exit(0);
+ }
+ }
+
+ private boolean findSkyblockAddonsAndDelete(File[] files) {
+ if (files == null) return false;
+
+ for (File file : files) {
+ if (!file.isDirectory() && file.getPath().endsWith(".jar")) {
+ try {
+ JarFile jarFile = new JarFile(file);
+ ZipEntry mcModInfo = jarFile.getEntry("mcmod.info");
+ if (mcModInfo != null) {
+ InputStream inputStream = jarFile.getInputStream(mcModInfo);
+ String modID = getModIDFromInputStream(inputStream);
+ if (modID.equals("SkyHanni")) {
+ jarFile.close();
+ try {
+ boolean deleted = file.delete();
+ if (!deleted) {
+ throw new Exception();
+ }
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ showErrorMessage("Was not able to delete the other SkyHanni files found in your mods folder!" +
+ System.lineSeparator() +
+ "Please make sure that your minecraft is currently closed and try again, or feel" +
+ System.lineSeparator() +
+ "free to open your mods folder and delete those files manually.");
+ return true;
+ }
+ continue;
+ }
+ }
+ jarFile.close();
+ } catch (Exception ex) {
+ // Just don't check the file I guess, move on to the next...
+ }
+ }
+ }
+ return false;
+ }
+
+ public void onOpenFolder() {
+ try {
+ Desktop.getDesktop().open(getModsFolder());
+ } catch (Exception e) {
+ showErrorPopup(e);
+ }
+ }
+
+ public File getModsFolder() {
+ String userHome = System.getProperty("user.home", ".");
+
+ File modsFolder = getFile(userHome, "minecraft/mods/1.8.9");
+ if (!modsFolder.exists()) {
+ modsFolder = getFile(userHome, "minecraft/mods");
+ }
+
+ if (!modsFolder.exists() && !modsFolder.mkdirs()) {
+ throw new RuntimeException("The working directory could not be created: " + modsFolder);
+ }
+ return modsFolder;
+ }
+
+ public File getFile(String userHome, String minecraftPath) {
+ File workingDirectory;
+ switch (getOperatingSystem()) {
+ case LINUX:
+ case SOLARIS: {
+ workingDirectory = new File(userHome, '.' + minecraftPath + '/');
+ break;
+ }
+ case WINDOWS: {
+ String applicationData = System.getenv("APPDATA");
+ if (applicationData != null) {
+ workingDirectory = new File(applicationData, "." + minecraftPath + '/');
+ break;
+ }
+ workingDirectory = new File(userHome, '.' + minecraftPath + '/');
+ break;
+ }
+ case MACOS: {
+ workingDirectory = new File(userHome, "Library/Application Support/" + minecraftPath);
+ break;
+ }
+ default: {
+ workingDirectory = new File(userHome, minecraftPath + '/');
+ break;
+ }
+ }
+ return workingDirectory;
+ }
+
+ public OperatingSystem getOperatingSystem() {
+ String osName = System.getProperty("os.name").toLowerCase(Locale.US);
+ if (osName.contains("win")) {
+ return OperatingSystem.WINDOWS;
+
+ } else if (osName.contains("mac")) {
+ return OperatingSystem.MACOS;
+
+ } else if (osName.contains("solaris") || osName.contains("sunos")) {
+
+ return OperatingSystem.SOLARIS;
+ } else if (osName.contains("linux") || osName.contains("unix")) {
+
+ return OperatingSystem.LINUX;
+ }
+ return OperatingSystem.UNKNOWN;
+ }
+
+ public void centerFrame(JFrame frame) {
+ Rectangle rectangle = frame.getBounds();
+ Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+ Rectangle screenRectangle = new Rectangle(0, 0, screenSize.width, screenSize.height);
+
+ int newX = screenRectangle.x + (screenRectangle.width - rectangle.width) / 2;
+ int newY = screenRectangle.y + (screenRectangle.height - rectangle.height) / 2;
+
+ if (newX < 0) newX = 0;
+ if (newY < 0) newY = 0;
+
+ frame.setBounds(newX, newY, rectangle.width, rectangle.height);
+ }
+
+ public void showMessage(String message) {
+ JOptionPane.showMessageDialog(null, message, "SkyHanni", JOptionPane.INFORMATION_MESSAGE);
+ }
+
+ public void showErrorMessage(String message) {
+ JOptionPane.showMessageDialog(null, message, "SkyHanni - Error", JOptionPane.ERROR_MESSAGE);
+ }
+
+ private String getModIDFromInputStream(InputStream inputStream) {
+ String version = "";
+ try {
+ BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
+ while ((version = bufferedReader.readLine()) != null) {
+ if (version.contains("\"modid\": \"")) {
+ version = version.split(Pattern.quote("\"modid\": \""))[1];
+ version = version.substring(0, version.length() - 2);
+ break;
+ }
+ }
+ } catch (Exception ex) {
+ // RIP, couldn't find the modid...
+ }
+ return version;
+ }
+
+// private String getVersionFromMcmodInfo() {
+// String version = "";
+// try {
+// BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(Objects.requireNonNull(getClass()
+// .getClassLoader()
+// .getResourceAsStream("mcmod.info"), "mcmod.info not found.")));
+// while ((version = bufferedReader.readLine()) != null) {
+// if (version.contains("\"version\": \"")) {
+// version = version.split(Pattern.quote("\"version\": \""))[1];
+// version = version.substring(0, version.length() - 2);
+// break;
+// }
+// }
+// } catch (Exception ex) {
+// // It's okay, I guess just don't use the version lol.
+// }
+// return version;
+// }
+
+ private File getThisFile() {
+ try {
+ return new File(SkyHanniInstallerFrame.class
+ .getProtectionDomain()
+ .getCodeSource()
+ .getLocation()
+ .toURI());
+ } catch (URISyntaxException ex) {
+ showErrorPopup(ex);
+ }
+ return null;
+ }
+
+ @Override
+ public void mousePressed(MouseEvent e) {
+ }
+
+ @Override
+ public void mouseReleased(MouseEvent e) {
+ }
+
+ @Override
+ public void mouseEntered(MouseEvent e) {
+ }
+
+ @Override
+ public void mouseExited(MouseEvent e) {
+ }
+
+ public enum OperatingSystem {
+ LINUX,
+ SOLARIS,
+ WINDOWS,
+ MACOS,
+ UNKNOWN
+ }
+} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt
index b998e7f07..7628a2bfb 100644
--- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt
+++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt
@@ -20,6 +20,7 @@ import at.hannibal2.skyhanni.features.commands.PartyTransferCommand
import at.hannibal2.skyhanni.features.commands.SendCoordinatedCommand
import at.hannibal2.skyhanni.features.commands.WarpIsCommand
import at.hannibal2.skyhanni.features.commands.WikiCommand
+import at.hannibal2.skyhanni.features.cosmetics.CosmeticFollowingLine
import at.hannibal2.skyhanni.features.damageindicator.DamageIndicatorManager
import at.hannibal2.skyhanni.features.dungeon.*
import at.hannibal2.skyhanni.features.event.diana.*
@@ -56,6 +57,7 @@ import at.hannibal2.skyhanni.features.misc.discordrpc.DiscordRPCManager
import at.hannibal2.skyhanni.features.misc.ghostcounter.GhostCounter
import at.hannibal2.skyhanni.features.misc.items.EstimatedItemValue
import at.hannibal2.skyhanni.features.misc.items.EstimatedWardrobePrice
+import at.hannibal2.skyhanni.features.misc.massconfiguration.DefaultConfigFeatures
import at.hannibal2.skyhanni.features.misc.tabcomplete.PlayerTabComplete
import at.hannibal2.skyhanni.features.misc.tabcomplete.WarpTabComplete
import at.hannibal2.skyhanni.features.misc.teleportpad.TeleportPadCompactName
@@ -126,7 +128,7 @@ import org.apache.logging.log4j.Logger
clientSideOnly = true,
useMetadata = true,
guiFactory = "at.hannibal2.skyhanni.config.ConfigGuiForgeInterop",
- version = "0.20.Beta.8",
+ version = "0.20.Beta.14",
)
class SkyHanniMod {
@Mod.EventHandler
@@ -153,7 +155,7 @@ class SkyHanniMod {
loadModule(OtherInventoryData)
loadModule(TabListData())
loadModule(RenderGuiData())
- loadModule(GardenCropMilestones())
+ loadModule(GardenCropMilestones)
loadModule(GardenCropUpgrades())
loadModule(OwnInventoryData())
loadModule(ToolTipData())
@@ -163,11 +165,12 @@ class SkyHanniMod {
loadModule(MayorElection())
loadModule(GardenComposterUpgradesData())
loadModule(ActionBarStatsData)
- loadModule(GardenCropMilestoneAverage())
+ loadModule(GardenCropMilestoneInventory())
loadModule(GardenCropSpeed)
loadModule(ProfileStorageData)
loadModule(TitleData())
loadModule(BlockData())
+ loadModule(DefaultConfigFeatures)
// APIs
loadModule(BazaarApi())
@@ -179,6 +182,7 @@ class SkyHanniMod {
loadModule(SlayerAPI)
loadModule(PurseAPI())
loadModule(RiftAPI)
+ loadModule(SackAPI())
// features
loadModule(BazaarOrderHelper())
@@ -215,7 +219,7 @@ class SkyHanniMod {
loadModule(AshfangHideDamageIndicator())
loadModule(ItemStars())
loadModule(MinionFeatures())
- loadModule(RealTime())
+ loadModule(TimeFeatures())
loadModule(RngMeterInventory())
loadModule(WikiCommand())
loadModule(SendCoordinatedCommand())
@@ -225,7 +229,7 @@ class SkyHanniMod {
loadModule(AreaMiniBossFeatures())
loadModule(MobHighlight())
loadModule(MarkedPlayerManager())
- loadModule(HighlightSlayerMiniBoss())
+ loadModule(SlayerMiniBossFeatures())
loadModule(PlayerDeathMessages())
loadModule(HighlightDungeonDeathmite())
loadModule(DungeonHideItems())
@@ -285,7 +289,7 @@ class SkyHanniMod {
loadModule(DicerRngDropCounter())
loadModule(CropMoneyDisplay)
loadModule(JacobFarmingContestsInventory())
- loadModule(GardenNextJacobContest())
+ loadModule(GardenNextJacobContest)
loadModule(WrongFungiCutterWarning())
loadModule(FarmingArmorDrops())
loadModule(JoinCrystalHollows())
@@ -293,6 +297,7 @@ class SkyHanniMod {
loadModule(GardenVisitorColorNames())
loadModule(TeleportPadCompactName())
loadModule(AnitaMedalProfit())
+ loadModule(AnitaExtraFarmingFortune())
loadModule(ComposterDisplay())
loadModule(GardenComposterInventoryFeatures())
loadModule(MinionCollectLogic())
@@ -379,6 +384,11 @@ class SkyHanniMod {
loadModule(CompactBestiaryChatMessage())
loadModule(WatchdogHider())
loadModule(AccountUpgradeReminder())
+ loadModule(PetExpTooltip())
+ loadModule(Translator())
+ loadModule(GardenPlotBorders())
+ loadModule(CosmeticFollowingLine())
+ loadModule(SuperpairsClicksAlert())
init()
@@ -392,6 +402,7 @@ class SkyHanniMod {
loadModule(TestCopyBestiaryValues)
loadModule(HighlightMissingRepoItems())
loadModule(ParkourWaypointSaver())
+ loadModule(TestShowSlotNumber())
}
@Mod.EventHandler
diff --git a/src/main/java/at/hannibal2/skyhanni/api/CollectionAPI.kt b/src/main/java/at/hannibal2/skyhanni/api/CollectionAPI.kt
index ca1be6890..43ea964ee 100644
--- a/src/main/java/at/hannibal2/skyhanni/api/CollectionAPI.kt
+++ b/src/main/java/at/hannibal2/skyhanni/api/CollectionAPI.kt
@@ -71,7 +71,7 @@ class CollectionAPI {
fun isCollectionTier0(lore: List<String>) = lore.map { collectionTier0Pattern.matcher(it) }.any { it.matches() }
- fun getCollectionCounter(internalName: NEUInternalName) = collectionValue[internalName]
+ fun getCollectionCounter(internalName: NEUInternalName): Long? = collectionValue[internalName]
// TODO add support for replenish (higher collection than actual items in inv)
fun addFromInventory(internalName: NEUInternalName, amount: Int) {
diff --git a/src/main/java/at/hannibal2/skyhanni/config/FeatureToggle.kt b/src/main/java/at/hannibal2/skyhanni/config/FeatureToggle.kt
new file mode 100644
index 000000000..bf9db0553
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/config/FeatureToggle.kt
@@ -0,0 +1,15 @@
+package at.hannibal2.skyhanni.config
+
+import io.github.moulberry.moulconfig.annotations.ConfigEditorBoolean
+
+/**
+ * Annotate a [ConfigEditorBoolean] to indicate that it is a feature toggle.
+ */
+@Retention(AnnotationRetention.RUNTIME)
+@Target(AnnotationTarget.FIELD)
+annotation class FeatureToggle(
+ /**
+ * Indicate that this field being true means the corresponding feature is enabled.
+ */
+ val trueIsEnabled: Boolean = true,
+)
diff --git a/src/main/java/at/hannibal2/skyhanni/config/Storage.java b/src/main/java/at/hannibal2/skyhanni/config/Storage.java
index 19322e15c..2b9755926 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/Storage.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/Storage.java
@@ -21,10 +21,16 @@ import java.util.*;
public class Storage {
@Expose
+ public boolean hasPlayedBefore = false;
+
+ @Expose
+ public Map<String, List<String>> knownFeatureToggles = new HashMap<>();
+
+ @Expose
public Map<Long, List<CropType>> gardenJacobFarmingContestTimes = new HashMap<>();
@Expose
- public String apiKey = "";
+ public Boolean contestSendingAsked = false;
@Expose
public Map<UUID, PlayerSpecific> players = new HashMap<>();
@@ -227,6 +233,15 @@ public class Storage {
@Expose
public long lastComposterEmptyWarningTime = 0;
+
+ @Expose
+ public FarmingWeightConfig farmingWeight = new FarmingWeightConfig();
+
+ public static class FarmingWeightConfig {
+
+ @Expose
+ public int lastFarmingWeightLeaderboard = -1;
+ }
}
@Expose
diff --git a/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt b/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt
index 478eb4a4b..acd280967 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt
+++ b/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt
@@ -7,15 +7,18 @@ import at.hannibal2.skyhanni.data.ChatManager
import at.hannibal2.skyhanni.data.GuiEditManager
import at.hannibal2.skyhanni.features.bingo.BingoCardDisplay
import at.hannibal2.skyhanni.features.bingo.BingoNextStepHelper
+import at.hannibal2.skyhanni.features.chat.Translator
import at.hannibal2.skyhanni.features.event.diana.BurrowWarpHelper
import at.hannibal2.skyhanni.features.event.diana.InquisitorWaypointShare
import at.hannibal2.skyhanni.features.fame.AccountUpgradeReminder
import at.hannibal2.skyhanni.features.fame.CityProjectFeatures
import at.hannibal2.skyhanni.features.garden.GardenAPI
import at.hannibal2.skyhanni.features.garden.GardenCropTimeCommand
+import at.hannibal2.skyhanni.features.garden.GardenNextJacobContest
import at.hannibal2.skyhanni.features.garden.composter.ComposterOverlay
import at.hannibal2.skyhanni.features.garden.farming.CropMoneyDisplay
import at.hannibal2.skyhanni.features.garden.farming.CropSpeedMeter
+import at.hannibal2.skyhanni.features.garden.farming.FarmingWeightDisplay
import at.hannibal2.skyhanni.features.garden.farming.GardenStartLocation
import at.hannibal2.skyhanni.features.garden.fortuneguide.CaptureFarmingGear
import at.hannibal2.skyhanni.features.garden.fortuneguide.FFGuideGUI
@@ -24,6 +27,7 @@ import at.hannibal2.skyhanni.features.misc.CollectionTracker
import at.hannibal2.skyhanni.features.misc.MarkedPlayerManager
import at.hannibal2.skyhanni.features.misc.discordrpc.DiscordRPCManager
import at.hannibal2.skyhanni.features.misc.ghostcounter.GhostUtil
+import at.hannibal2.skyhanni.features.misc.massconfiguration.DefaultConfigFeatures
import at.hannibal2.skyhanni.features.slayer.SlayerItemProfitTracker
import at.hannibal2.skyhanni.test.PacketTest
import at.hannibal2.skyhanni.test.SkyHanniConfigSearchResetCommand
@@ -102,6 +106,11 @@ object Commands {
registerCommand("skyhanni", "Opens the main SkyHanni config", openMainMenu)
registerCommand("ff", "Opens the Farming Fortune Guide") { openFortuneGuide() }
registerCommand("shcommands", "Shows this list") { commandHelp(it) }
+ registerCommand0("shdefaultoptions", "Select default options", {
+ DefaultConfigFeatures.onCommand(
+ it.getOrNull(0) ?: "null", it.getOrNull(1) ?: "null"
+ )
+ }, DefaultConfigFeatures::onComplete)
}
private fun usersNormal() {
@@ -136,6 +145,17 @@ object Commands {
) { clearFarmingItems() }
registerCommand("shresetghostcounter", "Resets the ghost counter stats") { GhostUtil.reset() }
registerCommand("shbingotoggle", "Toggle the bingo card display mode") { BingoCardDisplay.toggleCommand() }
+ registerCommand(
+ "shfarmingprofile",
+ "Look up the farming profile from yourself or another player on elitebot.dev"
+ ) { FarmingWeightDisplay.lookUpCommand(it) }
+ registerCommand(
+ "shcopytranslation",
+ "<language code (2 letters)> <messsage to translate>\n" +
+ "Requires the Chat > Translator feature to be enabled.\n" +
+ "Copies the translation for a given message to your clipboard. " +
+ "Language codes are at the end of the translation when you click on a message."
+ ) { Translator.fromEnglish(it) }
}
private fun usersBugFix() {
@@ -164,6 +184,14 @@ object Commands {
"shdebugdata",
"Prints debug data in the clipboard"
) { SkyHanniTestCommand.debugData(it) }
+ registerCommand(
+ "shversion",
+ "Prints the SkyHanni version in the chat"
+ ) { SkyHanniTestCommand.debugVersion() }
+ registerCommand(
+ "shcarrot",
+ "Toggles receiving the 12 fortune from carrots"
+ ) { CaptureFarmingGear.reverseCarrotFortune() }
}
private fun developersDebugFeatures() {
@@ -225,8 +253,12 @@ object Commands {
registerCommand("shshareinquis", "") { InquisitorWaypointShare.sendInquisitor() }
registerCommand("shcopyerror", "") { CopyErrorCommand.command(it) }
registerCommand("shstopcityprojectreminder", "") { CityProjectFeatures.disable() }
+ registerCommand("shsendcontests", "") { GardenNextJacobContest.shareContestConfirmed(it) }
registerCommand("shstopaccountupgradereminder", "") { AccountUpgradeReminder.disable() }
-
+ registerCommand(
+ "shsendtranslation",
+ "Respond with a translation of the message that the user clicks"
+ ) { Translator.toEnglish(it) }
}
private fun commandHelp(args: Array<String>) {
@@ -282,8 +314,24 @@ object Commands {
config.outdatedItems.clear()
}
- private fun registerCommand(name: String, description: String, function: (Array<String>) -> Unit) {
- ClientCommandHandler.instance.registerCommand(SimpleCommand(name, createCommand(function)))
+ private fun registerCommand(
+ name: String,
+ description: String,
+ function: (Array<String>) -> Unit
+ ) = registerCommand0(name, description, function)
+
+ private fun registerCommand0(
+ name: String,
+ description: String,
+ function: (Array<String>) -> Unit,
+ autoComplete: ((Array<String>) -> List<String>) = { listOf() }
+ ) {
+ ClientCommandHandler.instance.registerCommand(
+ SimpleCommand(
+ name,
+ createCommand(function)
+ ) { _, b, _ -> autoComplete(b) }
+ )
commands.add(CommandInfo(name, description, currentCategory))
}
diff --git a/src/main/java/at/hannibal2/skyhanni/config/commands/SimpleCommand.java b/src/main/java/at/hannibal2/skyhanni/config/commands/SimpleCommand.java
index fa2c310de..9ff8ade64 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/commands/SimpleCommand.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/commands/SimpleCommand.java
@@ -32,9 +32,9 @@ public class SimpleCommand extends CommandBase {
public abstract void processCommand(ICommandSender sender, String[] args);
}
- public abstract static class TabCompleteRunnable {
+ public interface TabCompleteRunnable {
- public abstract List<String> tabComplete(ICommandSender sender, String[] args, BlockPos pos);
+ List<String> tabComplete(ICommandSender sender, String[] args, BlockPos pos);
}
public boolean canCommandSenderUseCommand(ICommandSender sender) {
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/AshfangConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/AshfangConfig.java
index 3515b9280..575a1987d 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/AshfangConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/AshfangConfig.java
@@ -1,5 +1,6 @@
package at.hannibal2.skyhanni.config.features;
+import at.hannibal2.skyhanni.config.FeatureToggle;
import at.hannibal2.skyhanni.config.core.config.Position;
import com.google.gson.annotations.Expose;
import io.github.moulberry.moulconfig.annotations.ConfigEditorBoolean;
@@ -11,6 +12,7 @@ public class AshfangConfig {
@Expose
@ConfigOption(name = "Freeze", desc = "Show the cooldown for how long Ashfang blocks your abilities.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean freezeCooldown = false;
@Expose
@@ -19,6 +21,7 @@ public class AshfangConfig {
@Expose
@ConfigOption(name = "Reset Time", desc = "Show the cooldown until Ashfang pulls his underlings back.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean nextResetCooldown = false;
@Expose
@@ -27,6 +30,7 @@ public class AshfangConfig {
@Expose
@ConfigOption(name = "Gravity Orbs", desc = "Shows the Gravity Orbs more clearly.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean gravityOrbs = false;
@Expose
@@ -37,6 +41,7 @@ public class AshfangConfig {
@Expose
@ConfigOption(name = "Blazing Souls", desc = "Shows the Blazing Souls more clearly.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean blazingSouls = false;
@Expose
@@ -47,20 +52,24 @@ public class AshfangConfig {
@Expose
@ConfigOption(name = "Highlight Blazes", desc = "Highlight the different blazes in their respective colors.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean highlightBlazes = false;
@Expose
@ConfigOption(name = "Hide Particles", desc = "Hide particles around the Ashfang boss.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean hideParticles = false;
@Expose
@ConfigOption(name = "Hide Names", desc = "Hide the names of full health blazes around Ashfang (only useful when highlight blazes is enabled)")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean hideNames = false;
@Expose
@ConfigOption(name = "Hide Damage", desc = "Hide damage splashes around Ashfang.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean hideDamageSplash = false;
}
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/BazaarConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/BazaarConfig.java
index 8f12ba667..8d3565765 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/BazaarConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/BazaarConfig.java
@@ -1,5 +1,6 @@
package at.hannibal2.skyhanni.config.features;
+import at.hannibal2.skyhanni.config.FeatureToggle;
import at.hannibal2.skyhanni.config.core.config.Position;
import com.google.gson.annotations.Expose;
import io.github.moulberry.moulconfig.annotations.ConfigEditorBoolean;
@@ -10,16 +11,19 @@ public class BazaarConfig {
@Expose
@ConfigOption(name = "Purchase Helper", desc = "Highlights the item you are trying to buy in the Bazaar.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean purchaseHelper = true;
@Expose
@ConfigOption(name = "Order Helper", desc = "Show visual hints inside the Bazaar Manage Order view when items are ready to pickup or outbid.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean orderHelper = false;
@Expose
@ConfigOption(name = "Best Sell Method", desc = "Show the price difference between sell instantly and sell offer.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean bestSellMethod = false;
@Expose
@@ -28,5 +32,6 @@ public class BazaarConfig {
@Expose
@ConfigOption(name = "Cancelled Buy Order Clipboard", desc = "Saves missing items from cancelled buy orders to clipboard for faster re-entry.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean cancelledBuyOrderClipboard = false;
}
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/BingoConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/BingoConfig.java
index e083fbcbe..36bec57bc 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/BingoConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/BingoConfig.java
@@ -1,5 +1,6 @@
package at.hannibal2.skyhanni.config.features;
+import at.hannibal2.skyhanni.config.FeatureToggle;
import at.hannibal2.skyhanni.config.core.config.Position;
import com.google.gson.annotations.Expose;
import io.github.moulberry.moulconfig.annotations.Accordion;
@@ -18,6 +19,7 @@ public class BingoConfig {
@Expose
@ConfigOption(name = "Enable", desc = "Displays the bingo card.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean enabled = true;
@Expose
@ConfigOption(name = "Quick Toggle", desc = "Quickly toggle the bingo card or the step helper by sneaking with SkyBlock menu in hand.")
@@ -39,9 +41,11 @@ public class BingoConfig {
@ConfigOption(
name = "Show Guide",
desc = "Show tips and difficulty for bingo goals inside the bingo card inventory.\n" +
- "§eData from Bingo Splash Community§7, made by §cMayxo"
+ "These tips are made from inspirations and guides from the community,\n"+
+ "aiming to help you to complete the bingo card."
)
@ConfigEditorBoolean
+ @FeatureToggle
public boolean bingoSplashGuide = true;
@Expose
@@ -59,11 +63,13 @@ public class BingoConfig {
@ConfigOption(name = "Enable", desc = "Shortens chat messages about skill level ups, collection gains, " +
"new area discoveries and skyblock level up messages while on bingo.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean enabled = true;
@Expose
@ConfigOption(name = "Hide Border", desc = "Hide the border messages before and after the compact level up messages.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean hideBorder = true;
@Expose
@@ -75,6 +81,7 @@ public class BingoConfig {
@Expose
@ConfigOption(name = "Minion Craft Helper", desc = "Show how many more items you need to upgrade the minion in your inventory. Especially useful for bingo.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean minionCraftHelperEnabled = true;
@Expose
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/ChatConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/ChatConfig.java
index 352d01589..9833cf182 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/ChatConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/ChatConfig.java
@@ -1,5 +1,6 @@
package at.hannibal2.skyhanni.config.features;
+import at.hannibal2.skyhanni.config.FeatureToggle;
import com.google.gson.annotations.Expose;
import io.github.moulberry.moulconfig.annotations.*;
import org.lwjgl.input.Keyboard;
@@ -21,42 +22,49 @@ public class ChatConfig {
@ConfigOption(name = "Hypixel Hub", desc = "Block messages outside SkyBlock in the Hypixel lobby: player joins, loot boxes, prototype lobby messages, radiating generosity and Hypixel tournaments.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 0)
+ @FeatureToggle
public boolean hypixelHub = true;
@Expose
@ConfigOption(name = "Empty", desc = "Hide all the empty messages from the chat.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 0)
+ @FeatureToggle
public boolean empty = true;
@Expose
@ConfigOption(name = "Warping", desc = "Block 'sending request to join...' and 'warping...' messages.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 0)
+ @FeatureToggle
public boolean warping = true;
@Expose
@ConfigOption(name = "Welcome", desc = "Hide the 'welcome to SkyBlock' message.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 0)
+ @FeatureToggle
public boolean welcome = true;
@Expose
@ConfigOption(name = "Guild Exp", desc = "Hide guild exp messages.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 0)
+ @FeatureToggle
public boolean guildExp = true;
@Expose
@ConfigOption(name = "Friend Join Left", desc = "Hide friend join/left messages.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 0)
+ @FeatureToggle
public boolean friendJoinLeft = false;
@Expose
@ConfigOption(name = "Winter Gifts", desc = "Hide useless winter gift messages.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 0)
+ @FeatureToggle
public boolean winterGift = false;
@Expose
@@ -64,24 +72,28 @@ public class ChatConfig {
"(Except powder numbers over 1k, Prehistoric Egg and Automaton Parts)")
@ConfigEditorBoolean
@ConfigAccordionId(id = 0)
+ @FeatureToggle
public boolean powderMining = true;
@Expose
@ConfigOption(name = "Kill Combo", desc = "Hide messages about the current kill combo from the Grandma Wolf Pet.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 0)
+ @FeatureToggle
public boolean killCombo = false;
@Expose
@ConfigOption(name = "Watchdog", desc = "Hide the message where Hypixel is flexing how many players they have banned over the last week.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 0)
+ @FeatureToggle
public boolean watchDog = true;
@Expose
@ConfigOption(name = "Profile Join", desc = "Hide 'You are playing on profile' and 'Profile ID' chat messages")
@ConfigEditorBoolean
@ConfigAccordionId(id = 0)
+ @FeatureToggle
public boolean profileJoin = true;
//TODO remove
@@ -89,6 +101,7 @@ public class ChatConfig {
@ConfigOption(name = "Others", desc = "Hide other annoying messages.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 0)
+ @FeatureToggle
public boolean others = false;
@Expose
@@ -100,43 +113,57 @@ public class ChatConfig {
@ConfigOption(name = "Player Rank Hider", desc = "Hide player ranks in all chat messages.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 1)
+ @FeatureToggle
public boolean playerRankHider = false;
@Expose
@ConfigOption(name = "Chat Filter", desc = "Scan messages sent by players for blacklisted words and grey out the message if any are found.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 1)
+ @FeatureToggle
public boolean chatFilter = false;
@Expose
@ConfigOption(name = "Dungeon Filter", desc = "Hide annoying messages in dungeons.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean dungeonMessages = true;
@Expose
@ConfigOption(name = "Dungeon Boss Messages", desc = "Hide messages from the watcher and bosses in the dungeon.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean dungeonBossMessages = false;
@Expose
@ConfigOption(name = "Hide Far Deaths", desc = "Hide other players' death messages, " +
"except for players who are nearby or during dungeons/a Kuudra fight.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean hideFarDeathMessages = false;
//TODO jawbus + thunder
@Expose
@ConfigOption(name = "Compact Potion Message", desc = "Shorten chat messages about player potion effects.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean compactPotionMessage = true;
@Expose
@ConfigOption(name = "Compact Bestiary Message", desc = "Shorten the bestiary level up message, showing additional information when hovering.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean compactBestiaryMessage = true;
@Expose
@ConfigOption(name = "Arachne Hider", desc = "Hide chat messages about the Arachne Fight while outside of §eArachne's Sanctuary§7.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean hideArachneMessages = false;
+
+ @Expose
+ @ConfigOption(name = "Translator", desc = "Click on a message to translate it into English. Use /shcopytranslation to get the translation from English. Translation is not guaranteed to be 100% accurate.")
+ @ConfigEditorBoolean
+ @FeatureToggle
+ public boolean translator = false;
}
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/CommandsConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/CommandsConfig.java
index dd0668743..0c29f707e 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/CommandsConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/CommandsConfig.java
@@ -1,5 +1,6 @@
package at.hannibal2.skyhanni.config.features;
+import at.hannibal2.skyhanni.config.FeatureToggle;
import com.google.gson.annotations.Expose;
import io.github.moulberry.moulconfig.annotations.ConfigEditorBoolean;
import io.github.moulberry.moulconfig.annotations.ConfigOption;
@@ -9,16 +10,19 @@ public class CommandsConfig {
@Expose
@ConfigOption(name = "Fandom Wiki", desc = "Use Fandom wiki (§ehypixel-skyblock.fandom.com§7) instead of the Hypixel wiki (§ewiki.hypixel.net§7).")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean useFandomWiki = false;
@Expose
@ConfigOption(name = "Party transfer", desc = "Allows §e/pt <player> §7as alias for §e/party transfer§7.\n" +
"§7SkyBlock command §e/pt §7to check the play time still works.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean usePartyTransferAlias = true;
@Expose
@ConfigOption(name = "Replace Warp Is", desc = "Replaces §e/warp is §7with §e/is§7. Idk why. Ask §cKaeso")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean replaceWarpIs = false;
}
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/DamageIndicatorConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/DamageIndicatorConfig.java
index 099b2c3c4..94ff6f497 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/DamageIndicatorConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/DamageIndicatorConfig.java
@@ -1,5 +1,6 @@
package at.hannibal2.skyhanni.config.features;
+import at.hannibal2.skyhanni.config.FeatureToggle;
import com.google.gson.annotations.Expose;
import io.github.moulberry.moulconfig.annotations.*;
@@ -12,6 +13,7 @@ public class DamageIndicatorConfig {
@Expose
@ConfigOption(name = "Damage Indicator Enabled", desc = "Show the boss' remaining health.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean enabled = false;
@Expose
@@ -23,7 +25,7 @@ public class DamageIndicatorConfig {
@ConfigOption(
name = "Boss Name",
desc = "Change how the boss name should be displayed.")
- @ConfigEditorDropdown(values = {"Disabled", "Full Name", "Short Name"})
+ @ConfigEditorDropdown(values = {"Hidden", "Full Name", "Short Name"})
public int bossName = 1;
@Expose
@@ -56,11 +58,12 @@ public class DamageIndicatorConfig {
"Dummy",
"§bArachne",
"§bThe Rift Bosses",
- "§bRiftstalker Bloodfiend"
+ "§bRiftstalker Bloodfiend",
+ "§6Reindrake"
}
)
//TODO only show currently working and tested features
- public List<Integer> bossesToShow = new ArrayList<>(Arrays.asList(0, 1, 2, 5, 6, 7, 8, 9, 18, 19, 21, 22, 23));
+ public List<Integer> bossesToShow = new ArrayList<>(Arrays.asList(0, 1, 2, 5, 6, 7, 8, 9, 18, 19, 21, 22, 23, 24));
@Expose
@ConfigOption(name = "Hide Damage Splash", desc = "Hiding damage splashes near the damage indicator.")
@@ -73,11 +76,6 @@ public class DamageIndicatorConfig {
public boolean showDamageOverTime = false;
@Expose
- @ConfigOption(name = "Health During Laser", desc = "Show the health of Voidgloom Seraph 4 during the laser phase.")
- @ConfigEditorBoolean
- public boolean showHealthDuringLaser = false;
-
- @Expose
@ConfigOption(name = "Hide Nametag", desc = "Hide the vanilla nametag of damage indicator bosses.")
@ConfigEditorBoolean
public boolean hideVanillaNametag = false;
@@ -89,9 +87,27 @@ public class DamageIndicatorConfig {
@Expose
+ @ConfigOption(name = "Ender Slayer", desc = "")
+ @Accordion
+ public EnderSlayerConfig enderSlayer = new EnderSlayerConfig();
+
+ public static class EnderSlayerConfig {
+
+ @Expose
+ @ConfigOption(name = "Laser phase timer", desc = "Show a timer when the laser phase will end.")
+ @ConfigEditorBoolean
+ public boolean laserPhaseTimer = false;
+
+ @Expose
+ @ConfigOption(name = "Health During Laser", desc = "Show the health of Voidgloom Seraph 4 during the laser phase.")
+ @ConfigEditorBoolean
+ public boolean showHealthDuringLaser = false;
+ }
+
+ @Expose
@ConfigOption(name = "Vampire Slayer", desc = "")
@Accordion
- public VampireSlayerConfig vampireSlayer = new VampireSlayerConfig();
+ public DamageIndicatorConfig.VampireSlayerConfig vampireSlayer = new DamageIndicatorConfig.VampireSlayerConfig();
public static class VampireSlayerConfig {
@Expose
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/DevConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/DevConfig.java
index f7ee9f765..751e48a1c 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/DevConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/DevConfig.java
@@ -47,6 +47,12 @@ public class DevConfig {
public boolean showInternalName = false;
@Expose
+ @ConfigOption(name = "Show NPC Price", desc = "Show NPC price in item lore.")
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 0)
+ public boolean showNpcPrice = false;
+
+ @Expose
@ConfigOption(name = "Show empty internal names", desc = "Shows internal name even for items with none.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 0)
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/DianaConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/DianaConfig.java
index 99437bb83..3321e76e6 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/DianaConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/DianaConfig.java
@@ -1,5 +1,6 @@
package at.hannibal2.skyhanni.config.features;
+import at.hannibal2.skyhanni.config.FeatureToggle;
import com.google.gson.annotations.Expose;
import io.github.moulberry.moulconfig.annotations.*;
import org.lwjgl.input.Keyboard;
@@ -9,11 +10,13 @@ public class DianaConfig {
@Expose
@ConfigOption(name = "Soopy Guess", desc = "Uses §eSoopy's Guess Logic §7to find the next burrow. Does not require SoopyV2 or ChatTriggers to be installed.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean burrowsSoopyGuess = false;
@Expose
@ConfigOption(name = "Nearby Detection", desc = "Show burrows near you.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean burrowsNearbyDetection = false;
@Expose
@@ -32,6 +35,25 @@ public class DianaConfig {
public int keyBindWarp = Keyboard.KEY_NONE;
@Expose
+ @ConfigOption(name = "Ignored Warps", desc = "")
+ @Accordion
+ public IgnoredWarpsConfig ignoredWarps = new IgnoredWarpsConfig();
+
+ public static class IgnoredWarpsConfig {
+
+ @Expose
+ @ConfigOption(name = "Crypt", desc = "Ignore the crypt warp point (Because it takes a long time to leave).")
+ @ConfigEditorBoolean
+ public boolean crypt = false;
+
+ @Expose
+ @ConfigOption(name = "Wizard", desc = "Ignore the wizard tower warp point (Because it is easy to fall into the rift).")
+ @ConfigEditorBoolean
+ public boolean wizard = false;
+
+ }
+
+ @Expose
@ConfigOption(name = "Inquisitor Waypoint Sharing", desc = "")
@Accordion
@ConfigAccordionId(id = 9)
@@ -42,6 +64,7 @@ public class DianaConfig {
@Expose
@ConfigOption(name = "Enabled", desc = "Shares your Inquisitor and receiving other Inquisitors via Party Chat.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean enabled = true;
@Expose
@@ -68,5 +91,6 @@ public class DianaConfig {
@Expose
@ConfigOption(name = "Griffin Pet Warning", desc = "Warn when holding an Ancestral Spade while no Griffin pet is selected.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean petWarning = true;
}
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/DungeonConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/DungeonConfig.java
index 3e086812e..b0677f462 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/DungeonConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/DungeonConfig.java
@@ -1,5 +1,6 @@
package at.hannibal2.skyhanni.config.features;
+import at.hannibal2.skyhanni.config.FeatureToggle;
import at.hannibal2.skyhanni.config.core.config.Position;
import com.google.gson.annotations.Expose;
import io.github.moulberry.moulconfig.annotations.ConfigAccordionId;
@@ -12,11 +13,13 @@ public class DungeonConfig {
@Expose
@ConfigOption(name = "Clicked Blocks", desc = "Highlight levers, chests, and wither essence when clicked in dungeons.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean highlightClickedBlocks = false;
@Expose
@ConfigOption(name = "Milestones Display", desc = "Show the current milestone in dungeons.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean showMilestonesDisplay = false;
@Expose
@@ -25,6 +28,7 @@ public class DungeonConfig {
@Expose
@ConfigOption(name = "Death Counter Display", desc = "Display the total amount of deaths in the current dungeon.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean deathCounterDisplay = false;
@Expose
@@ -39,6 +43,7 @@ public class DungeonConfig {
"particles are no longer displayed and the music stops playing, but the loot chests are still displayed.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 2)
+ @FeatureToggle
public boolean cleanEndToggle = false;
@Expose
@@ -51,11 +56,13 @@ public class DungeonConfig {
@Expose
@ConfigOption(name = "Boss Damage Splash", desc = "Hides damage splashes while inside the boss room (fixes a Skytils feature).")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean damageSplashBoss = false;
@Expose
@ConfigOption(name = "Highlight Deathmites", desc = "Highlight deathmites in dungeon in red color.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean highlightDeathmites = true;
@ConfigOption(name = "Object Hider", desc = "Hide various things in dungeons.")
@@ -66,48 +73,56 @@ public class DungeonConfig {
@ConfigOption(name = "Hide Superboom TNT", desc = "Hide Superboom TNT laying around in dungeons.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 3)
+ @FeatureToggle
public boolean hideSuperboomTNT = false;
@Expose
@ConfigOption(name = "Hide Blessings", desc = "Hide Blessings laying around in dungeons.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 3)
+ @FeatureToggle
public boolean hideBlessing = false;
@Expose
@ConfigOption(name = "Hide Revive Stones", desc = "Hide Revive Stones laying around in dungeons.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 3)
+ @FeatureToggle
public boolean hideReviveStone = false;
@Expose
@ConfigOption(name = "Hide Premium Flesh", desc = "Hide Premium Flesh laying around in dungeons.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 3)
+ @FeatureToggle
public boolean hidePremiumFlesh = false;
@Expose
@ConfigOption(name = "Hide Journal Entry", desc = "Hide Journal Entry pages laying around in dungeons.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 3)
+ @FeatureToggle
public boolean hideJournalEntry = false;
@Expose
@ConfigOption(name = "Hide Skeleton Skull", desc = "Hide Skeleton Skulls laying around in dungeons.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 3)
+ @FeatureToggle
public boolean hideSkeletonSkull = true;
@Expose
@ConfigOption(name = "Hide Healer Orbs", desc = "Hides the damage, ability damage and defensive orbs that spawn when the healer kills mobs.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 3)
+ @FeatureToggle
public boolean hideHealerOrbs = false;
@Expose
@ConfigOption(name = "Hide Healer Fairy", desc = "Hide the golden fairy that follows the healer in dungeons.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 3)
+ @FeatureToggle
public boolean hideHealerFairy = false;
@ConfigOption(name = "Message Filter", desc = "")
@@ -118,6 +133,7 @@ public class DungeonConfig {
@ConfigOption(name = "Keys and Doors", desc = "Hides the chat message when picking up keys or opening doors in dungeons.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 4)
+ @FeatureToggle
public boolean messageFilterKeysAndDoors = false;
@ConfigOption(name = "Dungeon Copilot", desc = "")
@@ -128,6 +144,7 @@ public class DungeonConfig {
@ConfigOption(name = "Copilot Enabled", desc = "Suggests what to do next in dungeons.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 5)
+ @FeatureToggle
public boolean copilotEnabled = false;
@Expose
@@ -141,17 +158,20 @@ public class DungeonConfig {
@ConfigOption(name = "Colored Class Level", desc = "Color class levels in party finder.")
@ConfigAccordionId(id = 6)
@ConfigEditorBoolean
+ @FeatureToggle
public boolean partyFinderColoredClassLevel = true;
@Expose
@ConfigOption(name = "Moving Skeleton Skulls", desc = "Highlight Skeleton Skulls when combining into an " +
"orange Skeletor (not useful when combined with feature Hide Skeleton Skull).")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean highlightSkeletonSkull = true;
@Expose
@ConfigOption(name = "Croesus Chest", desc = "Adds a visual highlight to the Croesus inventory that " +
"shows unopened chests.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean croesusUnopenedChestTracker = true;
}
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/FishingConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/FishingConfig.java
index 80c7e33cd..3dccd1b3c 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/FishingConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/FishingConfig.java
@@ -1,5 +1,6 @@
package at.hannibal2.skyhanni.config.features;
+import at.hannibal2.skyhanni.config.FeatureToggle;
import at.hannibal2.skyhanni.config.core.config.Position;
import com.google.gson.annotations.Expose;
import io.github.moulberry.moulconfig.annotations.*;
@@ -19,6 +20,7 @@ public class FishingConfig {
)
@ConfigEditorBoolean
@ConfigAccordionId(id = 0)
+ @FeatureToggle
public boolean trophyCounter = false;
@Expose
@@ -66,12 +68,14 @@ public class FishingConfig {
@ConfigOption(name = "Fillet Tooltip", desc = "Show fillet value of trophy fish in tooltip.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 0)
+ @FeatureToggle
public boolean trophyFilletTooltip = true;
@Expose
@ConfigOption(name = "Odger Waypoint", desc = "Show the Odger waypoint when trophy fishes are in the inventory and no lava rod in hand.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 0)
+ @FeatureToggle
public boolean odgerLocation = true;
@ConfigOption(name = "Thunder Spark", desc = "")
@@ -82,6 +86,7 @@ public class FishingConfig {
@ConfigOption(name = "Thunder Spark Highlight", desc = "Highlight Thunder Sparks after killing a Thunder")
@ConfigEditorBoolean
@ConfigAccordionId(id = 1)
+ @FeatureToggle
public boolean thunderSparkHighlight = false;
@Expose
@@ -101,6 +106,7 @@ public class FishingConfig {
)
@ConfigEditorBoolean
@ConfigAccordionId(id = 2)
+ @FeatureToggle
public boolean barnTimer = true;
@Expose
@@ -113,6 +119,7 @@ public class FishingConfig {
)
@ConfigEditorBoolean
@ConfigAccordionId(id = 2)
+ @FeatureToggle
public boolean barnTimerCrystalHollows = true;
@Expose
@@ -150,6 +157,7 @@ public class FishingConfig {
@Expose
@ConfigOption(name = "Enable", desc = "Hide the Chum/Chumcap Bucket name tags for other players.")
@ConfigEditorBoolean
+ @FeatureToggle
public Property<Boolean> enabled = Property.of(true);
@Expose
@@ -173,6 +181,7 @@ public class FishingConfig {
@Expose
@ConfigOption(name = "Enabled", desc = "Show the fished item name above the item when fishing.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean enabled = true;
@Expose
@@ -188,6 +197,7 @@ public class FishingConfig {
desc = "Counts how many sharks have been caught."
)
@ConfigEditorBoolean
+ @FeatureToggle
public boolean sharkFishCounter = false;
@Expose
@@ -196,10 +206,12 @@ public class FishingConfig {
@Expose
@ConfigOption(name = "Shorten Fishing Message", desc = "Shortens the chat message that says what type of sea creature you have fished.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean shortenFishingMessage = false;
@Expose
@ConfigOption(name = "Compact Double Hook", desc = "Adds Double Hook to the sea creature chat message instead of in a previous line.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean compactDoubleHook = true;
}
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/GardenConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/GardenConfig.java
index 36d2fbb50..59867fb8a 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/GardenConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/GardenConfig.java
@@ -1,5 +1,6 @@
package at.hannibal2.skyhanni.config.features;
+import at.hannibal2.skyhanni.config.FeatureToggle;
import at.hannibal2.skyhanni.config.commands.Commands;
import at.hannibal2.skyhanni.config.core.config.Position;
import at.hannibal2.skyhanni.features.garden.inventory.GardenPlotIcon;
@@ -26,6 +27,7 @@ public class GardenConfig {
@ConfigOption(name = "Copper Price", desc = "Show copper to coin prices inside the SkyMart inventory.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 0)
+ @FeatureToggle
public boolean skyMartCopperPrice = true;
@Expose
@@ -53,6 +55,7 @@ public class GardenConfig {
"and a number for how many visitors are already waiting.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 2)
+ @FeatureToggle
public boolean visitorTimerEnabled = true;
@Expose
@@ -82,6 +85,7 @@ public class GardenConfig {
@ConfigOption(name = "Items Needed", desc = "Show all items needed for the visitors.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 3)
+ @FeatureToggle
public boolean visitorNeedsDisplay = true;
@Expose
@@ -110,6 +114,7 @@ public class GardenConfig {
@ConfigOption(name = "Item Preview", desc = "Show the base type for the required items next to new visitors. §cNote that some visitors may require any crop.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 3)
+ @FeatureToggle
public boolean visitorItemPreview = true;
@Expose
@@ -122,6 +127,7 @@ public class GardenConfig {
@ConfigOption(name = "Visitor Price", desc = "Show the bazaar price of the items required for the visitors, like in NEU.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 4)
+ @FeatureToggle
public boolean visitorShowPrice = false;
@Expose
@@ -134,18 +140,21 @@ public class GardenConfig {
@ConfigOption(name = "Copper Price", desc = "Show the price per copper inside the visitor gui.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 4)
+ @FeatureToggle
public boolean visitorCopperPrice = true;
@Expose
@ConfigOption(name = "Copper Time", desc = "Show the time required per copper inside the visitor gui.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 4)
+ @FeatureToggle
public boolean visitorCopperTime = false;
@Expose
@ConfigOption(name = "Garden Exp Price", desc = "Show the price per garden experience inside the visitor gui.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 4)
+ @FeatureToggle
public boolean visitorExperiencePrice = false;
@Expose
@@ -159,16 +168,19 @@ public class GardenConfig {
@Expose
@ConfigOption(name = "Notify in Chat", desc = "Send a Chat message once you talk to a visitor with reward.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean notifyInChat = true;
@Expose
@ConfigOption(name = "Show over Name", desc = "Show the reward name above the visitor name.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean showOverName = true;
@Expose
@ConfigOption(name = "Prevent Refusing", desc = "Prevent the refusal of a visitor with reward.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean preventRefusing = true;
@Expose
@@ -193,6 +205,8 @@ public class GardenConfig {
"§9Dedication IV",
"§9Music Rune",
"§cSpace Helmet",
+ "§9Cultivating I",
+ "§9Replenish I",
}
)
public List<Integer> drops = new ArrayList<>(Arrays.asList(0, 1, 2, 3, 4, 5));
@@ -204,12 +218,14 @@ public class GardenConfig {
@ConfigOption(name = "Notification Chat", desc = "Show in chat when a new visitor is visiting your island.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 1)
+ @FeatureToggle
public boolean visitorNotificationChat = true;
@Expose
@ConfigOption(name = "Notification Title", desc = "Show a title when a new visitor is visiting your island.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 1)
+ @FeatureToggle
public boolean visitorNotificationTitle = true;
@Expose
@@ -222,18 +238,21 @@ public class GardenConfig {
@ConfigOption(name = "Colored Name", desc = "Show the visitor name in the color of the rarity.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 1)
+ @FeatureToggle
public boolean visitorColoredName = true;
@Expose
@ConfigOption(name = "Hypixel Message", desc = "Hide the chat message from Hypixel that a new visitor has arrived at your garden.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 1)
+ @FeatureToggle
public boolean visitorHypixelArrivedMessage = true;
@Expose
@ConfigOption(name = "Hide Chat", desc = "Hide chat messages from the visitors in garden. (Except Beth and Spaceman)")
@ConfigEditorBoolean
@ConfigAccordionId(id = 1)
+ @FeatureToggle
public boolean visitorHideChat = true;
@Expose
@@ -249,6 +268,7 @@ public class GardenConfig {
desc = "Tallies up statistic about visitors and the rewards you have received from them."
)
@ConfigEditorBoolean
+ @FeatureToggle
public boolean enabled = true;
@Expose
@@ -310,24 +330,28 @@ public class GardenConfig {
@ConfigOption(name = "Crop Milestone", desc = "Show the number of crop milestones in the inventory.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 5)
+ @FeatureToggle
public boolean numberCropMilestone = true;
@Expose
@ConfigOption(name = "Average Milestone", desc = "Show the average crop milestone in the crop milestone inventory.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 5)
+ @FeatureToggle
public boolean numberAverageCropMilestone = true;
@Expose
@ConfigOption(name = "Crop Upgrades", desc = "Show the number of upgrades in the crop upgrades inventory.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 5)
+ @FeatureToggle
public boolean numberCropUpgrades = true;
@Expose
@ConfigOption(name = "Composter Upgrades", desc = "Show the number of upgrades in the composter upgrades inventory.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 5)
+ @FeatureToggle
public boolean numberComposterUpgrades = true;
@Expose
@@ -339,10 +363,11 @@ public class GardenConfig {
@ConfigOption(
name = "Progress Display",
desc = "Shows the progress and ETA until the next crop milestone is reached and the current crops/minute value. " +
- "§cRequires a tool with either a counter or cultivating enchantment."
+ "§eRequires a tool with either a counter or cultivating enchantment for full accuracy."
)
@ConfigEditorBoolean
@ConfigAccordionId(id = 6)
+ @FeatureToggle
public boolean cropMilestoneProgress = true;
@Expose
@@ -426,6 +451,7 @@ public class GardenConfig {
desc = "Lists all crops and their ETA till next milestone. Sorts for best crop for getting garden or SkyBlock levels.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 7)
+ @FeatureToggle
public boolean cropMilestoneBestDisplay = true;
// TODO moulconfig runnable support
@@ -494,6 +520,7 @@ public class GardenConfig {
desc = "Show the progress and ETA for mushroom crops when farming other crops because of the mushroom cow perk.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 15)
+ @FeatureToggle
public boolean cropMilestoneMushroomPetPerkEnabled = true;
@Expose
@@ -527,6 +554,7 @@ public class GardenConfig {
@ConfigOption(name = "Enabled", desc = "Use custom keybinds while holding a farming tool or daedalus axe in the hand. §cOnly updates after scrolling in the hotbar.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 8)
+ @FeatureToggle
public boolean keyBindEnabled = false;
@ConfigOption(name = "Disable All", desc = "Disable all keys.")
@@ -614,9 +642,11 @@ public class GardenConfig {
public boolean optimalSpeed = false;
@Expose
- @ConfigOption(name = "Enabled", desc = "Show the optimal speed for your current tool in the hand.\n(Thanks MelonKingDE for the default values).")
+ @ConfigOption(name = "Enabled", desc = "Show the optimal speed for your current tool in the hand.\n" +
+ "(Thanks MelonKingDE for the default values).")
@ConfigEditorBoolean
@ConfigAccordionId(id = 9)
+ @FeatureToggle
public boolean optimalSpeedEnabled = true;
@Expose
@@ -629,6 +659,7 @@ public class GardenConfig {
@ConfigOption(name = "Rancher Boots", desc = "Allows you to set the optimal speed in the rancher boots overlay by clicking on the presets.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 9)
+ @FeatureToggle
public boolean optimalSpeedSignEnabled = true;
@Expose
@@ -726,6 +757,7 @@ public class GardenConfig {
@ConfigOption(name = "Display", desc = "Show the current garden level and progress to the next level.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 10)
+ @FeatureToggle
public boolean gardenLevelDisplay = true;
@Expose
@@ -742,6 +774,7 @@ public class GardenConfig {
"See §ehttps://elitebot.dev/info §7for more info.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 11)
+ @FeatureToggle
public boolean eliteFarmingWeightDisplay = true;
@Expose
@@ -762,6 +795,12 @@ public class GardenConfig {
public boolean eliteFarmingWeightOvertakeETA = false;
@Expose
+ @ConfigOption(name = "Offscreen Drop Message", desc = "Show a chat message when joining garden how many spots you have dropped since last garden join.")
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 11)
+ public boolean eliteFarmingWeightoffScreenDropMessage = true;
+
+ @Expose
@ConfigOption(name = "Always ETA", desc = "Show the Overtake ETA always, even when not farming at the moment.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 11)
@@ -774,6 +813,12 @@ public class GardenConfig {
public String eliteFarmingWeightETAGoalRank = "10000";
@Expose
+ @ConfigOption(name = "Show below 200", desc = "Show the farming weight data even if you are below 200 weight.")
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 11)
+ public boolean eliteFarmingWeightIgnoreLow = false;
+
+ @Expose
@ConfigOption(name = "Dicer Counter", desc = "")
@ConfigEditorAccordion(id = 12)
public boolean dicerCounter = false;
@@ -782,12 +827,14 @@ public class GardenConfig {
@ConfigOption(name = "Rng Drop Counter", desc = "Count RNG drops for Melon Dicer and Pumpkin Dicer.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 12)
+ @FeatureToggle
public boolean dicerCounterDisplay = true;
@Expose
@ConfigOption(name = "Hide Chat", desc = "Hide the chat message when dropping a RNG Dicer drop.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 12)
+ @FeatureToggle
public boolean dicerCounterHideChat = false;
@Expose
@@ -804,6 +851,7 @@ public class GardenConfig {
"Supports Bountiful, Mushroom Cow Perk and Dicer drops. Thier toggles are below.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 13)
+ @FeatureToggle
public boolean moneyPerHourDisplay = true;
// TODO moulconfig runnable support
@@ -923,6 +971,7 @@ public class GardenConfig {
@ConfigOption(name = "Show Jacob's Contest", desc = "Show the current or next Jacob's farming contest time and crops.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 14)
+ @FeatureToggle
public boolean nextJacobContestDisplay = true;
@Expose
@@ -938,6 +987,18 @@ public class GardenConfig {
public boolean nextJacobContestOtherGuis = false;
@Expose
+ @ConfigOption(name = "Fetch Contests", desc = "Automatically fetch contests from elitebot.dev for the current year if they're uploaded already.")
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 14)
+ public boolean nextJacobContestsFetchAutomatically = true;
+
+ @Expose
+ @ConfigOption(name = "Share Contests", desc = "Share the list of upcoming contests to elitebot.dev for everyone else to then fetch automatically.")
+ @ConfigEditorDropdown(values = { "Ask When Needed", "Share Automatically", "Disabled" })
+ @ConfigAccordionId(id = 14)
+ public int nextJacobContestsShareAutomatically = 0;
+
+ @Expose
@ConfigOption(name = "Warning", desc = "Show a warning shortly before a new Jacob's contest starts.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 14)
@@ -972,33 +1033,45 @@ public class GardenConfig {
@ConfigOption(name = "Show Counter", desc = "Count all §9Cropie§7, §5Squash §7and §6Fermento §7dropped.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 18)
+ @FeatureToggle
public boolean farmingArmorDropsEnabled = true;
@Expose
@ConfigOption(name = "Hide Chat", desc = "Hide the chat message when receiving a farming armor drop.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 18)
+ @FeatureToggle
public boolean farmingArmorDropsHideChat = false;
@Expose
public Position farmingArmorDropsPos = new Position(16, -232, false, true);
@Expose
- @ConfigOption(name = "Anita Medal Profit", desc = "")
+ @ConfigOption(name = "Anita Shop", desc = "")
@ConfigEditorAccordion(id = 16)
public boolean anitaMedalProfit = false;
@Expose
@ConfigOption(
- name = "Show Prices",
+ name = "Medal Prices",
desc = "Helps to identify profitable items to buy at the Anita item shop " +
"and potential profit from selling the item at the auction house."
)
@ConfigEditorBoolean
@ConfigAccordionId(id = 16)
+ @FeatureToggle
public boolean anitaMedalProfitEnabled = true;
@Expose
+ @ConfigOption(
+ name = "Extra Farming Fortune",
+ desc = "Show current tier and cost to max out in the item tooltip.")
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 16)
+ @FeatureToggle
+ public boolean extraFarmingFortune = true;
+
+ @Expose
public Position anitaMedalProfitPos = new Position(206, 158, false, true);
@Expose
@@ -1013,6 +1086,7 @@ public class GardenConfig {
)
@ConfigEditorBoolean
@ConfigAccordionId(id = 17)
+ @FeatureToggle
public boolean composterOverlay = true;
@Expose
@@ -1034,6 +1108,7 @@ public class GardenConfig {
)
@ConfigEditorBoolean
@ConfigAccordionId(id = 17)
+ @FeatureToggle
public boolean composterDisplayEnabled = true;
@Expose
@@ -1043,6 +1118,7 @@ public class GardenConfig {
)
@ConfigEditorBoolean
@ConfigAccordionId(id = 17)
+ @FeatureToggle
public boolean composterDisplayOutsideGarden = false;
@Expose
@@ -1061,6 +1137,7 @@ public class GardenConfig {
)
@ConfigEditorBoolean
@ConfigAccordionId(id = 17)
+ @FeatureToggle
public boolean composterUpgradePrice = true;
@Expose
@@ -1079,6 +1156,7 @@ public class GardenConfig {
)
@ConfigEditorBoolean
@ConfigAccordionId(id = 17)
+ @FeatureToggle
public boolean composterHighLightUpgrade = true;
@Expose
@@ -1088,6 +1166,7 @@ public class GardenConfig {
)
@ConfigEditorBoolean
@ConfigAccordionId(id = 17)
+ @FeatureToggle
public boolean composterInventoryNumbers = true;
@Expose
@@ -1100,6 +1179,7 @@ public class GardenConfig {
@ConfigOption(name = "Enable", desc = "Show a notification when organic matter or fuel runs low in your composter.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 21)
+ @FeatureToggle
public boolean composterNotifyLowEnabled = true;
@Expose
@@ -1146,6 +1226,7 @@ public class GardenConfig {
)
@ConfigEditorBoolean
@ConfigAccordionId(id = 22)
+ @FeatureToggle
public boolean farmingFortuneDisplay = true;
@Expose
@@ -1177,6 +1258,7 @@ public class GardenConfig {
)
@ConfigEditorBoolean
@ConfigAccordionId(id = 20)
+ @FeatureToggle
public boolean compactToolTooltips = false;
@Expose
@@ -1200,6 +1282,16 @@ public class GardenConfig {
public int cropTooltipFortune = 1;
@Expose
+ @ConfigOption(
+ name = "Total Crop Milestone",
+ desc = "Shows the progress bar till maxed crop milestone in the crop milestone inventory."
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 20)
+ @FeatureToggle
+ public boolean cropMilestoneTotalProgress = true;
+
+ @Expose
@ConfigOption(name = "Yaw and Pitch", desc = "")
@Accordion
public YawPitchDisplay yawPitchDisplay = new YawPitchDisplay();
@@ -1209,6 +1301,7 @@ public class GardenConfig {
@Expose
@ConfigOption(name = "Enable", desc = "Displays yaw and pitch while holding a farming tool. Automatically fades out if there is no movement.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean enabled = false;
@Expose
@@ -1269,6 +1362,7 @@ public class GardenConfig {
@Expose
@ConfigOption(name = "Enable", desc = "Show the start waypoint for your farm with the currently holding tool.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean enabled = false;
}
@@ -1282,6 +1376,7 @@ public class GardenConfig {
@Expose
@ConfigOption(name = "Enable", desc = "Enable icon replacement in the Configure Plots menu.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean enabled = true;
@ConfigOption(name = "Hard Reset", desc = "Reset every slot to it's original item.")
@@ -1295,27 +1390,32 @@ public class GardenConfig {
@Expose
@ConfigOption(name = "Plot Price", desc = "Show the price of the plot in coins when inside the Configure Plots inventory.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean plotPrice = true;
@Expose
@ConfigOption(name = "Desk in Menu", desc = "Show a Desk button in the SkyBlock Menu. Opens the /desk command on click.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean deskInSkyBlockMenu = true;
@Expose
@ConfigOption(name = "Fungi Cutter Warning", desc = "Warn when breaking mushroom with the wrong Fungi Cutter mode.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean fungiCutterWarn = true;
@Expose
@ConfigOption(name = "Burrowing Spores", desc = "Show a notification when a Burrowing Spores spawns during farming mushrooms.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean burrowingSporesNotification = true;
@Expose
@ConfigOption(name = "Wild Strawberry", desc = "Show a notification when a Wild Strawberry Dye drops during farming.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean wildStrawberryDyeNotification = true;
@Expose
@@ -1324,6 +1424,7 @@ public class GardenConfig {
desc = "Show the minimum needed Farming Fortune for reaching each medal in Jacob's Farming Contest inventory."
)
@ConfigEditorBoolean
+ @FeatureToggle
public boolean farmingFortuneForContest = true;
@Expose
@@ -1335,6 +1436,7 @@ public class GardenConfig {
desc = "Show the time and missing FF for every crop inside Jacob's Farming Contest inventory."
)
@ConfigEditorBoolean
+ @FeatureToggle
public boolean jacobContextTimes = true;
@Expose
@@ -1346,6 +1448,7 @@ public class GardenConfig {
desc = "Show the average Blocks Per Second and blocks clicked at the end of a Jacob Farming Contest in chat."
)
@ConfigEditorBoolean
+ @FeatureToggle
public boolean jacobContestSummary = true;
@Expose
@@ -1355,4 +1458,10 @@ public class GardenConfig {
@Expose
public Position cropSpeedMeterPos = new Position(278, -236, false, true);
+
+ @Expose
+ @ConfigOption(name = "Enable Plot Borders", desc = "Enable the use of F3 + G hotkey to show Garden plot borders. Similar to how later minecraft version render chunk borders.")
+ @ConfigEditorBoolean
+ @FeatureToggle
+ public boolean plotBorders = true;
} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/GhostCounterConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/GhostCounterConfig.java
index 4e41b0dbc..da971dd6c 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/GhostCounterConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/GhostCounterConfig.java
@@ -1,5 +1,6 @@
package at.hannibal2.skyhanni.config.features;
+import at.hannibal2.skyhanni.config.FeatureToggle;
import at.hannibal2.skyhanni.config.core.config.Position;
import at.hannibal2.skyhanni.features.misc.ghostcounter.GhostFormatting;
import at.hannibal2.skyhanni.features.misc.ghostcounter.GhostUtil;
@@ -15,6 +16,7 @@ public class GhostCounterConfig {
@Expose
@ConfigOption(name = "Enabled", desc = "Enable ghost counter.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean enabled = true;
@Expose
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/InventoryConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/InventoryConfig.java
index ff2c0eb83..571a9a15b 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/InventoryConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/InventoryConfig.java
@@ -1,5 +1,6 @@
package at.hannibal2.skyhanni.config.features;
+import at.hannibal2.skyhanni.config.FeatureToggle;
import at.hannibal2.skyhanni.config.core.config.Position;
import com.google.gson.annotations.Expose;
import io.github.moulberry.moulconfig.annotations.*;
@@ -18,6 +19,7 @@ public class InventoryConfig {
@ConfigOption(name = "Enabled", desc = "Hide items that are not clickable in the current inventory: ah, bz, accessory bag, etc.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 0)
+ @FeatureToggle
public boolean hideNotClickableItems = false;
@Expose
@@ -53,18 +55,21 @@ public class InventoryConfig {
@ConfigOption(name = "Floor Names", desc = "Show the floor names in the catacombs rng meter inventory.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 1)
+ @FeatureToggle
public boolean rngMeterFloorName = false;
@Expose
@ConfigOption(name = "No Drop", desc = "Highlight floors without a drop selected in the catacombs rng meter inventory.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 1)
+ @FeatureToggle
public boolean rngMeterNoDrop = false;
@Expose
@ConfigOption(name = "Selected Drop", desc = "Highlight the selected drop in the catacombs or slayer rng meter inventory.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 1)
+ @FeatureToggle
public boolean rngMeterSelectedDrop = false;
@ConfigOption(name = "Stats Tuning", desc = "")
@@ -75,24 +80,28 @@ public class InventoryConfig {
@ConfigOption(name = "Selected Stats", desc = "Show the tuning stats in the Thaumaturgy inventory.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 2)
+ @FeatureToggle
public boolean statsTuningSelectedStats = true;
@Expose
@ConfigOption(name = "Tuning Points", desc = "Show the amount of selected tuning points in the stats tuning inventory.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 2)
+ @FeatureToggle
public boolean statsTuningPoints = true;
@Expose
@ConfigOption(name = "Selected Template", desc = "Highlight the selected template in the stats tuning inventory.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 2)
+ @FeatureToggle
public boolean statsTuningSelectedTemplate = true;
@Expose
@ConfigOption(name = "Template Stats", desc = "Show the type of stats for the tuning point templates.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 2)
+ @FeatureToggle
public boolean statsTuningTemplateStats = true;
@Expose
@@ -104,18 +113,21 @@ public class InventoryConfig {
@ConfigOption(name = "Unclaimed Rewards", desc = "Highlight contests with unclaimed rewards in the jacob inventory.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 3)
+ @FeatureToggle
public boolean jacobFarmingContestHighlightRewards = true;
@Expose
@ConfigOption(name = "Duplicate Hider", desc = "Hides duplicate farming contests in the inventory.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 3)
+ @FeatureToggle
public boolean jacobFarmingContestHideDuplicates = true;
@Expose
@ConfigOption(name = "Contest Time", desc = "Adds the real time format to the contest description.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 3)
+ @FeatureToggle
public boolean jacobFarmingContestRealTime = true;
@Expose
@@ -128,6 +140,7 @@ public class InventoryConfig {
@Expose
@ConfigOption(name = "Enabled", desc = "Show contained items inside a sack inventory.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean enabled = true;
@Expose
@@ -196,6 +209,7 @@ public class InventoryConfig {
@Expose
@ConfigOption(name = "Enabled", desc = "Enabled estimated value of chest")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean enabled = false;
@Expose
@@ -216,6 +230,7 @@ public class InventoryConfig {
@Expose
@ConfigOption(name = "Highlight slot", desc = "Highlight slot where the item is when you hover over it in the display.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean enableHighlight = true;
@Expose
@@ -272,7 +287,7 @@ public class InventoryConfig {
"§bPet Level",
"§bMinion Tier",
"§bCrimson Armor",
- "§bWishing Compass",
+ "§7(Removed)",
"§bKuudra Key",
"§bSkill Level",
"§bCollection Level",
@@ -286,35 +301,41 @@ public class InventoryConfig {
@Expose
@ConfigOption(name = "Sack Name", desc = "Show an abbreviation of the sack name.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean displaySackName = false;
@Expose
@ConfigOption(name = "Anvil Combine Helper", desc = "Suggests the same item in the inventory when trying to combine two items in the anvil.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean anvilCombineHelper = false;
@Expose
@ConfigOption(name = "Item Stars",
desc = "Show a compact star count in the item name for all items.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean itemStars = false;
@Expose
@ConfigOption(name = "Highlight Depleted Bonzo's Masks",
desc = "Highlights used Bonzo's Masks with a background.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean highlightDepletedBonzosMasks = false;
@Expose
@ConfigOption(name = "Missing Tasks",
desc = "Highlight missing tasks in the SkyBlock level guide inventory.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean highlightMissingSkyBlockLevelGuide = true;
@Expose
@ConfigOption(name = "Highlight Auctions",
desc = "Highlight own items that are sold in green and that are expired in red.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean highlightAuctions = true;
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/ItemAbilityConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/ItemAbilityConfig.java
index e4fc4f186..4b245db4d 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/ItemAbilityConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/ItemAbilityConfig.java
@@ -1,18 +1,15 @@
package at.hannibal2.skyhanni.config.features;
+import at.hannibal2.skyhanni.config.FeatureToggle;
import com.google.gson.annotations.Expose;
-import io.github.moulberry.moulconfig.annotations.ConfigAccordionId;
-import io.github.moulberry.moulconfig.annotations.ConfigEditorAccordion;
-import io.github.moulberry.moulconfig.annotations.ConfigEditorBoolean;
-import io.github.moulberry.moulconfig.annotations.ConfigEditorColour;
-import io.github.moulberry.moulconfig.annotations.ConfigEditorDropdown;
-import io.github.moulberry.moulconfig.annotations.ConfigOption;
+import io.github.moulberry.moulconfig.annotations.*;
public class ItemAbilityConfig {
@Expose
@ConfigOption(name = "Ability Cooldown", desc = "Show the cooldown of item abilities.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean itemAbilityCooldown = false;
@Expose
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/MinionsConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/MinionsConfig.java
index 17abf034a..dd2debc75 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/MinionsConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/MinionsConfig.java
@@ -1,19 +1,16 @@
package at.hannibal2.skyhanni.config.features;
+import at.hannibal2.skyhanni.config.FeatureToggle;
import at.hannibal2.skyhanni.config.core.config.Position;
import com.google.gson.annotations.Expose;
-import io.github.moulberry.moulconfig.annotations.ConfigAccordionId;
-import io.github.moulberry.moulconfig.annotations.ConfigEditorAccordion;
-import io.github.moulberry.moulconfig.annotations.ConfigEditorBoolean;
-import io.github.moulberry.moulconfig.annotations.ConfigEditorColour;
-import io.github.moulberry.moulconfig.annotations.ConfigEditorSlider;
-import io.github.moulberry.moulconfig.annotations.ConfigOption;
+import io.github.moulberry.moulconfig.annotations.*;
public class MinionsConfig {
@Expose
@ConfigOption(name = "Name Display", desc = "Show the minion name and tier over the minion.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean nameDisplay = true;
@Expose
@@ -29,6 +26,7 @@ public class MinionsConfig {
@ConfigOption(name = "Last Minion Display", desc = "Marks the location of the last clicked minion, even through walls.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 0)
+ @FeatureToggle
public boolean lastClickedMinionDisplay = false;
@Expose
@@ -61,6 +59,7 @@ public class MinionsConfig {
@ConfigOption(name = "Emptied Time Display", desc = "Show the time when the hopper in the minion was last emptied.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 1)
+ @FeatureToggle
public boolean emptiedTimeDisplay = false;
@Expose
@@ -87,5 +86,6 @@ public class MinionsConfig {
@Expose
@ConfigOption(name = "Hide Mob Nametag", desc = "Hiding the nametag of mobs close to minions.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean hideMobsNametagNearby = false;
}
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/MiscConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/MiscConfig.java
index 588a52345..6a8bc4576 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/MiscConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/MiscConfig.java
@@ -1,16 +1,9 @@
package at.hannibal2.skyhanni.config.features;
+import at.hannibal2.skyhanni.config.FeatureToggle;
import at.hannibal2.skyhanni.config.core.config.Position;
import com.google.gson.annotations.Expose;
-import io.github.moulberry.moulconfig.annotations.Accordion;
-import io.github.moulberry.moulconfig.annotations.ConfigAccordionId;
-import io.github.moulberry.moulconfig.annotations.ConfigEditorAccordion;
-import io.github.moulberry.moulconfig.annotations.ConfigEditorBoolean;
-import io.github.moulberry.moulconfig.annotations.ConfigEditorDraggableList;
-import io.github.moulberry.moulconfig.annotations.ConfigEditorDropdown;
-import io.github.moulberry.moulconfig.annotations.ConfigEditorKeybind;
-import io.github.moulberry.moulconfig.annotations.ConfigEditorText;
-import io.github.moulberry.moulconfig.annotations.ConfigOption;
+import io.github.moulberry.moulconfig.annotations.*;
import io.github.moulberry.moulconfig.observer.Property;
import org.lwjgl.input.Keyboard;
@@ -29,24 +22,59 @@ public class MiscConfig {
@ConfigOption(name = "Pet Display", desc = "Show the currently active pet.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 0)
+ @FeatureToggle
public boolean petDisplay = false;
@Expose
- public Position petDisplayPos = new Position(-330, -15, false, true);
+ @ConfigOption(name = "Pet Experience Tooltip", desc = "Show the currently active pet.")
+ @ConfigAccordionId(id = 0)
+ @Accordion
+ public PetExperienceToolTipConfig petExperienceToolTip = new PetExperienceToolTipConfig();
- @Expose
- @ConfigOption(name = "Time", desc = "")
- @ConfigEditorAccordion(id = 1)
- public boolean time = false;
+ public static class PetExperienceToolTipConfig {
+
+ @Expose
+ @ConfigOption(name = "Enabled", desc = "Show the full pet exp and the progress to level 100 (ignoring rarity) when hovering over an pet while pressing shift key.")
+ @ConfigEditorBoolean
+ @FeatureToggle
+ public boolean petDisplay = true;
+
+ @Expose
+ @ConfigOption(name = "Show Always", desc = "Show this info always, even if not pressing shift key.")
+ @ConfigEditorBoolean
+ public boolean showAlways = false;
+
+ }
@Expose
- @ConfigOption(name = "Real Time", desc = "Display the current computer time, a handy feature when playing in full-screen mode.")
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 1)
- public boolean realTime = false;
+ public Position petDisplayPos = new Position(-330, -15, false, true);
+ // rename this to just "time will cause a config reset
+ @ConfigOption(name = "Time Features", desc = "")
+ @Accordion
@Expose
- public Position realTimePos = new Position(10, 10, false, true);
+ public TimeConfig timeConfigs = new TimeConfig();
+
+ public static class TimeConfig {
+
+ @Expose
+ @ConfigOption(name = "Real Time", desc = "Display the current computer time, a handy feature when playing in full-screen mode.")
+ @ConfigEditorBoolean
+ @FeatureToggle
+ public boolean realTime = false;
+
+ @Expose
+ public Position realTimePos = new Position(10, 10, false, true);
+
+ @Expose
+ @ConfigOption(name = "Winter Time", desc = "While on the Winter Island, show a timer until Jerry's Workshop closes.")
+ @ConfigEditorBoolean
+ @FeatureToggle
+ public boolean winterTime = true;
+
+ @Expose
+ public Position winterTimePos = new Position(10, 10, false, true);
+ }
@ConfigOption(name = "Hide Armor", desc = "")
@Accordion
@@ -78,6 +106,7 @@ public class MiscConfig {
@ConfigOption(name = "Hide Damage Splash", desc = "Hide all damage splashes anywhere in SkyBlock.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 4)
+ @FeatureToggle
public boolean hideDamageSplash = false;
@Expose
@@ -89,12 +118,14 @@ public class MiscConfig {
@ConfigOption(name = "Non God Pot Effects", desc = "Display the active potion effects that are not part of the god pot.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 5)
+ @FeatureToggle
public boolean nonGodPotEffectDisplay = false;
@Expose
@ConfigOption(name = "Show Mixins", desc = "Include god pot mixins in the non god pot effects display.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 5)
+ @FeatureToggle
public boolean nonGodPotEffectShowMixins = false;
@Expose
@@ -109,6 +140,7 @@ public class MiscConfig {
@ConfigOption(name = "Crimson Isle Reputation", desc = "Enable features around Reputation features in the Crimson Isle.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 6)
+ @FeatureToggle
public boolean crimsonIsleReputationHelper = true;
@Expose
@@ -128,10 +160,10 @@ public class MiscConfig {
public Position crimsonIsleReputationHelperPos = new Position(10, 10, false, true);
@Expose
- @ConfigOption(name = "Reputation Locations", desc = "Crimson Isles waypoints for locations to get reputation.")
- @ConfigEditorBoolean
+ @ConfigOption(name = "Show Locations", desc = "Crimson Isles waypoints for locations to get reputation.")
+ @ConfigEditorDropdown(values = {"Always", "Only With Hotkey", "Never"})
@ConfigAccordionId(id = 6)
- public boolean crimsonIsleReputationLocation = false;
+ public int crimsonIsleReputationShowLocation = 1;
@Expose
@ConfigOption(name = "Tia Relay", desc = "")
@@ -142,6 +174,7 @@ public class MiscConfig {
@ConfigOption(name = "Tia Relay Waypoint", desc = "Show the next relay waypoint for Tia the Fairy, where maintenance for the abiphone network needs to be done.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 7)
+ @FeatureToggle
public boolean tiaRelayNextWaypoint = true;
@Expose
@@ -154,12 +187,14 @@ public class MiscConfig {
@ConfigOption(name = "Tia Relay Helper", desc = "Helps with solving the sound puzzle.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 7)
+ @FeatureToggle
public boolean tiaRelayHelper = true;
@Expose
@ConfigOption(name = "Tia Relay Mute", desc = "Mutes the sound when close to the relay.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 7)
+ @FeatureToggle
public boolean tiaRelayMute = true;
@Expose
@@ -171,6 +206,7 @@ public class MiscConfig {
@ConfigOption(name = "Tps Display", desc = "Show the TPS of the current server, like in Soopy.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 8)
+ @FeatureToggle
public boolean tpsDisplayEnabled = false;
@Expose
@@ -185,42 +221,49 @@ public class MiscConfig {
@ConfigOption(name = "Blaze Particles", desc = "Hide blaze particles.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 9)
+ @FeatureToggle
public boolean hideBlazeParticles = false;
@Expose
@ConfigOption(name = "Enderman Particles", desc = "Hide enderman particles.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 9)
+ @FeatureToggle
public boolean hideEndermanParticles = false;
@Expose
@ConfigOption(name = "Fireball Particles", desc = "Hide fireball particles.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 9)
+ @FeatureToggle
public boolean hideFireballParticles = true;
@Expose
@ConfigOption(name = "Fire Particles", desc = "Hide particles from the fire block.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 9)
+ @FeatureToggle
public boolean hideFireBlockParticles = true;
@Expose
@ConfigOption(name = "Smoke Particles", desc = "Hide smoke particles.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 9)
+ @FeatureToggle
public boolean hideSmokeParticles = false;
@Expose
@ConfigOption(name = "Far Particles", desc = "Hide particles that are more than 40 blocks away.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 9)
+ @FeatureToggle
public boolean hideFarParticles = true;
@Expose
@ConfigOption(name = "Close Redstone Particles", desc = "Hide redstone particles around the player (appear for some potion effects).")
@ConfigEditorBoolean
@ConfigAccordionId(id = 9)
+ @FeatureToggle
public boolean hideCloseRedstoneparticles = true;
@Expose
@@ -232,12 +275,14 @@ public class MiscConfig {
@ConfigOption(name = "Enabled", desc = "Show the cooldown until the next time you can lay an egg with the Chicken Head.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 10)
+ @FeatureToggle
public boolean chickenHeadTimerDisplay = false;
@Expose
@ConfigOption(name = "Hide Chat", desc = "Hide the 'You laid an egg!' chat message.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 10)
+ @FeatureToggle
public boolean chickenHeadTimerHideChat = true;
@Expose
@@ -252,6 +297,7 @@ public class MiscConfig {
@ConfigOption(name = "Enable Estimated Price", desc = "Displays an estimated item value for the item you hover over.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 11)
+ @FeatureToggle
public boolean estimatedIemValueEnabled = false;
@Expose
@@ -267,6 +313,17 @@ public class MiscConfig {
public boolean estimatedIemValueAlwaysEnabled = true;
@Expose
+ @ConfigOption(name = "Enchantments Cap", desc = "Only show the top # most expensive enchantments.")
+ @ConfigEditorSlider(
+ minValue = 1,
+ maxValue = 30,
+ minStep = 1
+ )
+ @ConfigAccordionId(id = 11)
+ public Property<Integer> estimatedIemValueEnchantmentsCap = Property.of(7);
+
+
+ @Expose
@ConfigOption(name = "Show Exact Price", desc = "Show the exact total price instead of the compact number.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 11)
@@ -276,6 +333,7 @@ public class MiscConfig {
@ConfigOption(name = "Show Armor Value", desc = "Show the value of the full armor in the wardrobe inventory.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 11)
+ @FeatureToggle
public boolean estimatedIemValueArmor = true;
@Expose
@@ -291,6 +349,7 @@ public class MiscConfig {
@Expose
@ConfigOption(name = "Enable Discord RPC", desc = "Details about your SkyBlock session displayed through Discord.")
@ConfigEditorBoolean
+ @FeatureToggle
public Property<Boolean> enabled = Property.of(false);
@Expose
@@ -366,6 +425,7 @@ public class MiscConfig {
@ConfigOption(name = "Trapper Solver", desc = "Assists you in finding Trevor's mobs. §eNote: May not always work as expected. " +
"§cWill not help you to find rabbits or sheep in the Oasis!")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean trapperSolver = true;
@Expose
@@ -376,6 +436,7 @@ public class MiscConfig {
@Expose
@ConfigOption(name = "Warp to Trapper", desc = "Warp to Trevor's Den. Works only inside the Farming Islands.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean warpToTrapper = false;
@Expose
@@ -386,6 +447,7 @@ public class MiscConfig {
@Expose
@ConfigOption(name = "Trapper Cooldown", desc = "Change the color of Trevor and adds a cooldown over his head.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean trapperTalkCooldown = true;
}
@@ -399,11 +461,13 @@ public class MiscConfig {
@Expose
@ConfigOption(name = "Compact Name", desc = "Hide the 'Warp to' and 'No Destination' texts over teleport pads.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean compactName = false;
@Expose
@ConfigOption(name = "Inventory Numbers", desc = "Show the number of the teleport pads inside the 'Change Destination' inventory as stack size.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean inventoryNumbers = false;
}
@@ -417,16 +481,19 @@ public class MiscConfig {
@Expose
@ConfigOption(name = "Show Materials", desc = "Show materials needed for contributing to the City Project.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean showMaterials = true;
@Expose
@ConfigOption(name = "Show Ready", desc = "Mark contributions that are ready to participate.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean showReady = true;
@Expose
@ConfigOption(name = "Daily Reminder", desc = "Remind every 24 hours to participate.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean dailyReminder = true;
@Expose
@@ -443,31 +510,35 @@ public class MiscConfig {
@Expose
@ConfigOption(name = "Warps", desc = "Tab complete the warp-point names when typing §e/warp <TAB>§7.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean warps = true;
@Expose
@ConfigOption(name = "Island Players", desc = "Tab complete other players on the same island.")
- @ConfigEditorBoolean
public boolean islandPlayers = true;
@Expose
@ConfigOption(name = "Friends", desc = "Tab complete friends from your friends list.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean friends = true;
@Expose
@ConfigOption(name = "Only Best Friends", desc = "Only Tab Complete best friends.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean onlyBestFriends = false;
@Expose
@ConfigOption(name = "Party", desc = "Tab complete party members.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean party = true;
@Expose
@ConfigOption(name = "VIP Visits", desc = "Tab complete the visit to special users with cake souls on it.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean vipVisits = true;
}
@@ -481,11 +552,13 @@ public class MiscConfig {
@Expose
@ConfigOption(name = "Show in Overlay", desc = "Show the number of Pocket Sack-In-A-Sack applied on a sack icon as an overlay.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean showOverlay = false;
@Expose
@ConfigOption(name = "Replace In Lore", desc = "Replace how text is displayed in lore.\nShow §eis stitched with 2/3...\n§7Instead of §eis stitched with two...")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean replaceLore = true;
}
@@ -499,6 +572,7 @@ public class MiscConfig {
@Expose
@ConfigOption(name = "Enabled", desc = "Adding a mod list, allowing to quickly switch between different mod menus.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean enabled = false;
@Expose
@@ -529,6 +603,7 @@ public class MiscConfig {
"§eIce calculations are an estimate but are relatively accurate."
)
@ConfigEditorBoolean
+ @FeatureToggle
public boolean enabled = true;
@Expose
@@ -592,6 +667,7 @@ public class MiscConfig {
"Also tracks drops from Endermen."
)
@ConfigEditorBoolean
+ @FeatureToggle
public boolean enabled = false;
@Expose
@@ -666,6 +742,7 @@ public class MiscConfig {
@Expose
@ConfigOption(name = "Enable", desc = "Show bestiary data overlay in the bestiary menu.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean enabled = false;
@Expose
@@ -711,11 +788,13 @@ public class MiscConfig {
@Expose
@ConfigOption(name = "Highlight Commission Mobs", desc = "Highlight Mobs that are part of active commissions.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean highlightCommissionMobs = false;
@Expose
@ConfigOption(name = "King Talisman Helper", desc = "Show kings you have not talked to yet, and when the next missing king will appear.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean kingTalismanHelper = false;
@Expose
@@ -724,12 +803,56 @@ public class MiscConfig {
@Expose
@ConfigOption(name = "Names in Core", desc = "Show the names of the 4 areas while in the center of crystal hollows.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean crystalHollowsNamesInCore = false;
}
@Expose
+ @ConfigOption(name = "Cosmetic", desc = "")
+ @Accordion
+ public CosmeticConfig cosmeticConfig = new CosmeticConfig();
+
+ public static class CosmeticConfig {
+
+ @Expose
+ @ConfigOption(name = "Following Line", desc = "")
+ @Accordion
+ public FollowingLineConfig followingLineConfig = new FollowingLineConfig();
+
+ public static class FollowingLineConfig {
+
+ @Expose
+ @ConfigOption(name = "Enabled", desc = "Draw a colored line behind the player.")
+ @ConfigEditorBoolean
+ @FeatureToggle
+ public boolean enabled = false;
+
+ @Expose
+ @ConfigOption(name = "Line color", desc = "Color of the line.")
+ @ConfigEditorColour
+ public String lineColor = "0:255:255:255:255";
+
+ @Expose
+ @ConfigOption(name = "Time Alive", desc = "Time in seconds until the line fades out.")
+ @ConfigEditorSlider(minStep = 1, minValue = 1, maxValue = 30)
+ public int secondsAlive = 3;
+
+ @Expose
+ @ConfigOption(name = "Max Line Width", desc = "Max width of the line.")
+ @ConfigEditorSlider(minStep = 1, minValue = 1, maxValue = 10)
+ public int lineWidth = 4;
+
+ @Expose
+ @ConfigOption(name = "Behind Blocks", desc = "Show behind blocks.")
+ @ConfigEditorBoolean
+ public boolean behindBlocks = false;
+ }
+ }
+
+ @Expose
@ConfigOption(name = "Exp Bottles", desc = "Hides all the experience orbs lying on the ground.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean hideExpBottles = false;
@Expose
@@ -738,41 +861,49 @@ public class MiscConfig {
@Expose
@ConfigOption(name = "Brewing Stand Overlay", desc = "Display the Item names directly inside the Brewing Stand.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean brewingStandOverlay = true;
@Expose
@ConfigOption(name = "Red Scoreboard Numbers", desc = "Hide the red scoreboard numbers at the right side of the screen.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean hideScoreboardNumbers = false;
@Expose
@ConfigOption(name = "Hide Piggy", desc = "Replacing 'Piggy' with 'Purse' in the Scoreboard.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean hidePiggyScoreboard = true;
@Expose
@ConfigOption(name = "Explosions Hider", desc = "Hide explosions.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean hideExplosions = false;
@Expose
@ConfigOption(name = "CH Join", desc = "Helps buy a Pass for accessing the Crystal Hollows if needed.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean crystalHollowsJoin = true;
@Expose
@ConfigOption(name = "Fire Overlay Hider", desc = "Hide the fire overlay (Like in Skytils).")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean hideFireOverlay = false;
@Expose
@ConfigOption(name = "Paste Into Signs", desc = "Allows you to paste the clipboard into signs when you press Ctrl + V.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean pasteIntoSigns = true;
@Expose
@ConfigOption(name = "Movement Speed", desc = "Show the player movement speed in blocks per second.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean playerMovementSpeed = false;
@Expose
@@ -781,41 +912,54 @@ public class MiscConfig {
@Expose
@ConfigOption(name = "Pet Candy Used", desc = "Show the number of pet candies used on a pet.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean petCandyUsed = true;
@Expose
@ConfigOption(name = "Server Restart Title", desc = "Show a title with seconds remaining until the server restarts after a Game Update or Scheduled Restart.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean serverRestartTitle = true;
@Expose
@ConfigOption(name = "Piece Of Wizard Portal", desc = "Restore the Earned By lore line on bought Piece Of Wizard Portal.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean restorePieceOfWizardPortalLore = true;
@Expose
@ConfigOption(name = "Patcher Coords Waypoint", desc = "Highlight the coordinates sent by Patcher.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean patcherSendCoordWaypoint = false;
@Expose
@ConfigOption(name = "Harp Keybinds", desc = "In Melody's Harp, press buttons with your number row on the keyboard instead of clicking.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean harpKeybinds = false;
@Expose
@ConfigOption(name = "Harp Numbers", desc = "In Melody's Harp, show buttons as stack size (intended to be used with Harp Keybinds).")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean harpNumbers = false;
@Expose
@ConfigOption(name = "Account Upgrade Reminder", desc = "Remind you to claim account upgrades when complete.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean accountUpgradeReminder = true;
@Expose
+ @ConfigOption(name = "Superpairs Clicks Alert", desc = "Display an alert when you reach the maximum clicks gained from Chronomatron or Ultrasequencer.")
+ @ConfigEditorBoolean
+ public boolean superpairsClicksAlert = false;
+
+ @Expose
@ConfigOption(name = "Config Button", desc = "Add a button to the pause menu to configure SkyHanni.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean configButtonOnPause = true;
@Expose
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/MobsConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/MobsConfig.java
index 68d79b7a4..d81c176a9 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/MobsConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/MobsConfig.java
@@ -1,5 +1,6 @@
package at.hannibal2.skyhanni.config.features;
+import at.hannibal2.skyhanni.config.FeatureToggle;
import com.google.gson.annotations.Expose;
import io.github.moulberry.moulconfig.annotations.ConfigAccordionId;
import io.github.moulberry.moulconfig.annotations.ConfigEditorAccordion;
@@ -17,24 +18,28 @@ public class MobsConfig {
@ConfigOption(name = "Area Boss", desc = "Highlight Golden Ghoul, Old Wolf, Voidling Extremist and Millenia-Aged Blaze.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 0)
+ @FeatureToggle
public boolean areaBossHighlight = true;
@Expose
@ConfigOption(name = "Arachne Keeper", desc = "Highlight the Arachne Keeper in the Spider's Den in purple color.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 0)
+ @FeatureToggle
public boolean arachneKeeperHighlight = true;
@Expose
@ConfigOption(name = "Corleone", desc = "Highlight Boss Corleone in the Crystal Hollows.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 0)
+ @FeatureToggle
public boolean corleoneHighlighter = true;
@Expose
@ConfigOption(name = "Zealot", desc = "Highlight Zealots and Bruisers in The End.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 0)
+ @FeatureToggle
public boolean zealotBruiserHighlighter = false;
@Expose
@@ -44,18 +49,21 @@ public class MobsConfig {
)
@ConfigEditorBoolean
@ConfigAccordionId(id = 0)
+ @FeatureToggle
public boolean specialZealotHighlighter = true;
@Expose
@ConfigOption(name = "Corrupted Mob", desc = "Highlight corrupted mobs in purple color.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 0)
+ @FeatureToggle
public boolean corruptedMobHighlight = false;
@Expose
@ConfigOption(name = "Arachne Boss", desc = "Highlight the arachne boss in red and mini bosses in orange.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 0)
+ @FeatureToggle
public boolean arachneBossHighlighter = true;
@Expose
@@ -71,15 +79,18 @@ public class MobsConfig {
)
@ConfigEditorBoolean
@ConfigAccordionId(id = 1)
+ @FeatureToggle
public boolean areaBossRespawnTimer = false;
@Expose
@ConfigOption(name = "Enderman TP Hider", desc = "Stops the Enderman Teleportation animation.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean endermanTeleportationHider = true;
@Expose
@ConfigOption(name = "Arachne Minis Hider", desc = "Hides the nametag above arachne minis.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean hideNameTagArachneMinis = true;
}
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/OldHidden.java b/src/main/java/at/hannibal2/skyhanni/config/features/OldHidden.java
index 23de8abe9..9e6cf0edf 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/OldHidden.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/OldHidden.java
@@ -15,9 +15,6 @@ import java.util.Map;
public class OldHidden {
@Expose
- public String apiKey = "";
-
- @Expose
public String currentPet = "";
@Expose
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/RiftConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/RiftConfig.java
index 11cefd38e..fa099ad29 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/RiftConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/RiftConfig.java
@@ -1,5 +1,6 @@
package at.hannibal2.skyhanni.config.features;
+import at.hannibal2.skyhanni.config.FeatureToggle;
import at.hannibal2.skyhanni.config.core.config.Position;
import com.google.gson.annotations.Expose;
import io.github.moulberry.moulconfig.annotations.*;
@@ -17,6 +18,7 @@ public class RiftConfig {
@Expose
@ConfigOption(name = "Enabled", desc = "Show the remaining rift time, max time, percentage, and extra time changes.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean enabled = true;
@Expose
@@ -43,6 +45,7 @@ public class RiftConfig {
@Expose
@ConfigOption(name = "Crux Talisman Display", desc = "Display progress of the Crux Talisman on screen.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean enabled = false;
@Expose
@@ -53,6 +56,7 @@ public class RiftConfig {
@Expose
@ConfigOption(name = "Show Bonuses", desc = "Show bonuses you get from the talisman.")
@ConfigEditorBoolean
+ @FeatureToggle
public Property<Boolean> showBonuses = Property.of(true);
@Expose
@@ -69,6 +73,7 @@ public class RiftConfig {
@Expose
@ConfigOption(name = "Enabled", desc = "Click on Enigma Souls in Rift Guides to highlight their location.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean enabled = true;
@Expose
@@ -96,6 +101,7 @@ public class RiftConfig {
@ConfigOption(name = "Shy Crux Warning", desc = "Shows a warning when a Shy Crux is going to steal your time. " +
"Useful if you play without volume.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean shyWarning = true;
@ConfigOption(name = "Larvas", desc = "")
@@ -108,6 +114,7 @@ public class RiftConfig {
@Expose
@ConfigOption(name = "Highlight", desc = "Highlight §cLarvas on trees §7while holding a §eLarva Hook §7in the hand.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean highlight = true;
@Expose
@@ -128,6 +135,7 @@ public class RiftConfig {
@ConfigOption(name = "Highlight", desc = "Highlight the small §cOdonatas §7flying around the trees while holding a " +
"§eEmpty Odonata Bottle §7in the hand.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean highlight = true;
@Expose
@@ -155,16 +163,19 @@ public class RiftConfig {
@Expose
@ConfigOption(name = "Hacking Solver", desc = "Highlights the correct button to click in the hacking inventory.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean solver = true;
@Expose
@ConfigOption(name = "Color Guide", desc = "Tells you which colour to pick.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean colour = true;
@Expose
@ConfigOption(name = "Terminal Waypoints", desc = "While wearing the helmet, waypoints will appear at each terminal location.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean waypoints = true;
}
}
@@ -179,6 +190,7 @@ public class RiftConfig {
@ConfigOption(name = "Agaricus Cap", desc = "Counts down the time until §eAgaricus Cap (Mushroom) " +
"§7changes color from brown to red and is breakable.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean agaricusCap = true;
@ConfigOption(name = "Volt Crux", desc = "")
@@ -191,11 +203,13 @@ public class RiftConfig {
@Expose
@ConfigOption(name = "Volt Warning", desc = "Shows a warning while a volt is discharging lightning.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean voltWarning = true;
@Expose
@ConfigOption(name = "Volt Range Highlighter", desc = "Shows the area in which a Volt might strike lightning.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean voltRange = true;
@Expose
@@ -206,6 +220,7 @@ public class RiftConfig {
@Expose
@ConfigOption(name = "Volt mood color", desc = "Change the color of the volt enemy depending on their mood.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean voltMoodMeter = false;
}
@@ -219,6 +234,7 @@ public class RiftConfig {
@Expose
@ConfigOption(name = "Enabled", desc = "Show Wilted Berberis helper.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean enabled = true;
@Expose
@@ -251,6 +267,7 @@ public class RiftConfig {
@Expose
@ConfigOption(name = "Enabled", desc = "Helps solving the lava maze in the mirror verse by showing the correct way.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean enabled = true;
@Expose
@@ -271,6 +288,7 @@ public class RiftConfig {
@Expose
@ConfigOption(name = "Hide others players", desc = "Hide other players while doing the lava maze.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean hidePlayers = false;
}
@@ -285,6 +303,7 @@ public class RiftConfig {
@Expose
@ConfigOption(name = "Enabled", desc = "Helps solving the upside down parkour in the mirror verse by showing the correct way.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean enabled = true;
@Expose
@@ -310,6 +329,7 @@ public class RiftConfig {
@Expose
@ConfigOption(name = "Hide others players", desc = "Hide other players while doing the upside down parkour.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean hidePlayers = false;
}
@@ -324,6 +344,7 @@ public class RiftConfig {
@Expose
@ConfigOption(name = "Enabled", desc = "Helps to solve the dance room in the mirror verse by showing multiple tasks at once.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean enabled = false;
@Expose
@@ -344,6 +365,7 @@ public class RiftConfig {
@Expose
@ConfigOption(name = "Hide Title", desc = "Hide Instructions, \"§aIt's happening!\" §7and \"§aKeep it up!\" §7titles.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean hideOriginalTitle = false;
@Expose
@@ -426,6 +448,7 @@ public class RiftConfig {
@Expose
@ConfigOption(name = "Enabled", desc = "Highlights the location of the invisible Tubulator blocks (Laser Parkour).")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean enabled = true;
@Expose
@@ -451,6 +474,7 @@ public class RiftConfig {
@Expose
@ConfigOption(name = "Hide others players", desc = "Hide other players while doing the lava maze.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean hidePlayers = false;
}
}
@@ -481,6 +505,7 @@ public class RiftConfig {
@Expose
@ConfigOption(name = "Enabled", desc = "Display progress Living Metal Suit")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean enabled = false;
@Expose
@@ -502,11 +527,13 @@ public class RiftConfig {
@Expose
@ConfigOption(name = "Enabled", desc = "Show a line between Defense blocks and the mob and highlight the blocks.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean enabled = true;
@Expose
@ConfigOption(name = "Hide Particles", desc = "Hide particles around Defense Blocks")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean hideParticles = false;
@Expose
@@ -526,11 +553,13 @@ public class RiftConfig {
@Expose
@ConfigOption(name = "Living Metal", desc = "Show a moving animation between Living Metal and the next block.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean enabled = true;
@Expose
@ConfigOption(name = "Hide Particles", desc = "Hide Living Metal particles.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean hideParticles = false;
}
@@ -546,6 +575,7 @@ public class RiftConfig {
@Expose
@ConfigOption(name = "Highlight Blobbercysts", desc = "Highlight Blobbercysts in Bacte fight.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean highlightBlobbercysts = true;
}
@@ -566,11 +596,13 @@ public class RiftConfig {
@Expose
@ConfigOption(name = "Enabled", desc = "Show locations of inactive Blood Effigy.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean enabled = false;
@Expose
@ConfigOption(name = "Respawning Soon", desc = "Show effigies that are about to respawn.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean respawningSoon = false;
@Expose
@@ -585,6 +617,7 @@ public class RiftConfig {
@Expose
@ConfigOption(name = "Unknown Times", desc = "Show effigies without known time.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean unknownTime = false;
}
}
@@ -610,6 +643,7 @@ public class RiftConfig {
@Expose
@ConfigOption(name = "Show Motes Price", desc = "Show the Motes NPC price in the item lore.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean showPrice = true;
@Expose
@@ -626,6 +660,7 @@ public class RiftConfig {
@Expose
@ConfigOption(name = "Inventory value", desc = "Show total Motes NPC price for the current opened inventory.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean enabled = true;
@Expose
@@ -649,11 +684,13 @@ public class RiftConfig {
@Expose
@ConfigOption(name = "Highlight Motes Orbs", desc = "Highlight flying Motes Orbs.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean enabled = true;
@Expose
@ConfigOption(name = "Hide Particles", desc = "Hide normal motes orbs particles.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean hideParticles = false;
}
@@ -661,10 +698,12 @@ public class RiftConfig {
@Expose
@ConfigOption(name = "Highlight Guide", desc = "Highlight things to do in the Rift Guide.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean highlightGuide = true;
@Expose
@ConfigOption(name = "Horsezooka Hider", desc = "Hide horses while holding the Horsezooka in the hand.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean horsezookaHider = false;
}
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/SlayerConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/SlayerConfig.java
index 7814b954e..d6af72b41 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/SlayerConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/SlayerConfig.java
@@ -1,5 +1,6 @@
package at.hannibal2.skyhanni.config.features;
+import at.hannibal2.skyhanni.config.FeatureToggle;
import at.hannibal2.skyhanni.config.core.config.Position;
import com.google.gson.annotations.Expose;
import io.github.moulberry.moulconfig.annotations.*;
@@ -12,33 +13,67 @@ public class SlayerConfig {
public boolean enderman = false;
@Expose
- @ConfigOption(name = "Highlight Yang Glyph", desc = "Highlight the enderman slayer Yang Glyph (beacon) in red color. Supports beacon in hand and beacon flying.")
- @ConfigEditorBoolean
+ @ConfigOption(name = "Yang Glyph (beacon)", desc = "")
@ConfigAccordionId(id = 0)
- public boolean slayerEndermanBeacon = false;
+ @Accordion
+ public EndermanBeaconConfig endermanBeaconConfig = new EndermanBeaconConfig();
- @Expose
- @ConfigOption(name = "Beacon Warning", desc = "Displays a warning mid-screen then the enderman Slayer throws a Yang Glyph (beacon).")
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 0)
- public boolean slayerEndermanBeaconWaring = false;
+ public static class EndermanBeaconConfig {
+
+ @Expose
+ @ConfigOption(name = "Highlight Beacon",
+ desc = "Highlight the Enderman Slayer Yang Glyph (beacon) in red color and added an timer when he explodes. " +
+ "Supports beacon in hand and beacon flying.")
+ @ConfigEditorBoolean
+ @FeatureToggle
+ public boolean highlightBeacon = true;
+
+ @Expose
+ @ConfigOption(name = "Beacon Color", desc = "Color of the beacon.")
+ @ConfigEditorColour
+ public String beaconColor = "0:255:255:0:88";
+
+ @Expose
+ @ConfigOption(name = "Show Warning", desc = "Displays a warning mid-screen then the Enderman Slayer throws a Yang Glyph (beacon).")
+ @ConfigEditorBoolean
+ @FeatureToggle
+ public boolean showWarning = false;
+
+ @Expose
+ @ConfigOption(name = "Show Line", desc = "Draw a line starting at your crosshair to the beacon.")
+ @ConfigEditorBoolean
+ @FeatureToggle
+ public boolean showLine = false;
+
+ @Expose
+ @ConfigOption(name = "Line color", desc = "Color of the line.")
+ @ConfigEditorColour
+ public String lneColor = "0:255:255:0:88";
+
+ @Expose
+ @ConfigOption(name = "Line Width", desc = "Width of the line.")
+ @ConfigEditorSlider(minStep = 1, minValue = 1, maxValue = 10)
+ public int lineWidth = 3;
+ }
@Expose
- @ConfigOption(name = "Highlight Nukekebi Skulls", desc = "Highlights the enderman Slayer Nukekebi Skulls.")
+ @ConfigOption(name = "Highlight Nukekubi Skulls", desc = "Highlights the Enderman Slayer Nukekubi Skulls (Eyes).")
@ConfigEditorBoolean
+ @FeatureToggle
@ConfigAccordionId(id = 0)
public boolean endermanHighlightNukekebi = false;
@Expose
- @ConfigOption(name = "Phase Display", desc = "Show the current phase of the enderman slayer in damage indcator.")
+ @ConfigOption(name = "Phase Display", desc = "Show the current phase of the Enderman Slayer in damage indcator.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 0)
public boolean endermanPhaseDisplay = false;
@Expose
- @ConfigOption(name = "Hide Particles", desc = "Hide particles around enderman slayer bosses and mini bosses.")
+ @ConfigOption(name = "Hide Particles", desc = "Hide particles around Enderman Slayer bosses and mini bosses.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 0)
+ @FeatureToggle
public boolean endermanHideParticles = false;
@Expose
@@ -56,18 +91,21 @@ public class SlayerConfig {
@ConfigOption(name = "Colored Mobs", desc = "Color the blaze slayer boss and the demons in the right hellion shield color.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 2)
+ @FeatureToggle
public boolean blazeColoredMobs = false;
@Expose
@ConfigOption(name = "Blaze Daggers", desc = "Faster and permanent display for the Blaze Slayer daggers.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 2)
+ @FeatureToggle
public boolean blazeDaggers = false;
@Expose
@ConfigOption(name = "Right Dagger", desc = "Mark the right dagger to use for blaze slayer in the dagger overlay.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 2)
+ @FeatureToggle
public boolean blazeMarkRightHellionShield = false;
@Expose
@@ -80,12 +118,14 @@ public class SlayerConfig {
@ConfigOption(name = "Hide Chat", desc = "Remove the wrong blaze slayer dagger messages from chat.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 2)
+ @FeatureToggle
public boolean blazeHideDaggerWarning = false;
@Expose
@ConfigOption(name = "Fire Pits", desc = "Warning when the fire pit phase starts for the Blaze Slayer tier 3 and 4.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 1)
+ @FeatureToggle
public boolean firePitsWarning = false;
@Expose
@@ -98,6 +138,7 @@ public class SlayerConfig {
@ConfigOption(name = "Clear View", desc = "Hide particles and fireballs near blaze slayer bosses and demons.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 1)
+ @FeatureToggle
public boolean blazeClearView = false;
@Expose
@@ -117,6 +158,7 @@ public class SlayerConfig {
@Expose
@ConfigOption(name = "Highlight your boss", desc = "Highlight your own vampire slayer boss.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean highlight = true;
@Expose
@@ -127,16 +169,19 @@ public class SlayerConfig {
@Expose
@ConfigOption(name = "Steak Alert", desc = "Show a title when you can steak your boss.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean steakAlert = true;
@Expose
@ConfigOption(name = "Twinclaws Title", desc = "Send a title when Twinclaws is about to happen.\nWork on others highlighted people boss.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean twinClawsTitle = true;
@Expose
@ConfigOption(name = "Twinclaws Sound", desc = "Play a sound when Twinclaws is about to happen.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean twinClawsSound = true;
}
@@ -150,6 +195,7 @@ public class SlayerConfig {
@Expose
@ConfigOption(name = "Highlight Others people boss", desc = "Highlight others players boss.\nYou need to hit them first.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean highlight = true;
@Expose
@@ -160,16 +206,19 @@ public class SlayerConfig {
@Expose
@ConfigOption(name = "Steak Alert", desc = "Show a title when you can steak the boss.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean steakAlert = true;
@Expose
@ConfigOption(name = "Twinclaws Title", desc = "Send a title when Twinclaws is about to happen.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean twinClawsTitle = true;
@Expose
@ConfigOption(name = "Twinclaws Sound", desc = "Play a sound when Twinclaws is about to happen.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean twinClawsSound = true;
}
@@ -182,6 +231,7 @@ public class SlayerConfig {
@Expose
@ConfigOption(name = "Highlight Co-op Boss", desc = "Highlight boss of your co-op member.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean highlight = true;
@Expose
@@ -197,16 +247,19 @@ public class SlayerConfig {
@Expose
@ConfigOption(name = "Steak Alert", desc = "Show a title when you can steak the boss.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean steakAlert = true;
@Expose
@ConfigOption(name = "Twinclaws Title", desc = "Send a title when Twinclaws is about to happen.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean twinClawsTitle = true;
@Expose
@ConfigOption(name = "Twinclaws Sound", desc = "Play a sound when Twinclaws is about to happen.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean twinClawsSound = true;
}
@@ -223,6 +276,7 @@ public class SlayerConfig {
@Expose
@ConfigOption(name = "Low Health", desc = "Change color when the boss is below 20% health.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean changeColorWhenCanSteak = true;
@Expose
@@ -236,17 +290,18 @@ public class SlayerConfig {
public int twinclawsDelay = 0;
@Expose
- @ConfigOption(name = "Draw line", desc = "Draw a line starting at your crosshair to the boss head")
+ @ConfigOption(name = "Draw line", desc = "Draw a line starting at your crosshair to the boss head.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean drawLine = false;
@Expose
- @ConfigOption(name = "Line color", desc = "Color of the line")
+ @ConfigOption(name = "Line color", desc = "Color of the line.")
@ConfigEditorColour
public String lineColor = "0:255:255:0:88";
@Expose
- @ConfigOption(name = "Line Width", desc = "Width of the line")
+ @ConfigOption(name = "Line Width", desc = "Width of the line.")
@ConfigEditorSlider(minStep = 1, minValue = 1, maxValue = 10)
public int lineWidth = 1;
@@ -260,11 +315,13 @@ public class SlayerConfig {
@Expose
@ConfigOption(name = "Highlight blood Ichor", desc = "Highlight the blood Ichor.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean highlight = false;
@Expose
@ConfigOption(name = "Beacon Beam", desc = "Render a beacon beam where the Blood Ichor is.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean renderBeam = true;
@Expose
@@ -275,6 +332,7 @@ public class SlayerConfig {
@Expose
@ConfigOption(name = "Show lines", desc = "Draw lines that start from the head of the boss and end on the Blood Ichor.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean showLines = false;
@Expose
@@ -293,6 +351,7 @@ public class SlayerConfig {
@Expose
@ConfigOption(name = "Highlight Killer Spring", desc = "Highlight the Killer Spring tower.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean highlight = false;
@Expose
@@ -303,6 +362,7 @@ public class SlayerConfig {
@Expose
@ConfigOption(name = "Show lines", desc = "Draw lines that start from the head of the boss and end on the Killer Spring tower.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean showLines = false;
@Expose
@@ -323,6 +383,7 @@ public class SlayerConfig {
@ConfigOption(name = "Enabled", desc = "Count all items you pick up while doing slayer, " +
"keep track of how much you pay for starting slayers and calculating the overall profit.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean enabled = true;
@Expose
@@ -332,6 +393,7 @@ public class SlayerConfig {
@ConfigOption(name = "Price in Chat", desc = "Show an extra chat message when you pick up an item. " +
"(This contains name, amount and price)")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean priceInChat = false;
@Expose
@@ -347,6 +409,7 @@ public class SlayerConfig {
@Expose
@ConfigOption(name = "Title Warning", desc = "Show an title for expensive item pickups.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean titleWarning = false;
@Expose
@@ -365,6 +428,7 @@ public class SlayerConfig {
@Expose
@ConfigOption(name = "Enabled", desc = "Show the name and price of items laying on the ground. §cOnly in slayer areas!")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean enabled = true;
@Expose
@@ -383,10 +447,11 @@ public class SlayerConfig {
@Expose
@ConfigOption(name = "Enabled", desc = "Display amount of bosses needed until next rng meter drop.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean enabled = true;
@Expose
- @ConfigOption(name = "Warn Empty", desc = "Warn when no item is set in the rng meter.")
+ @ConfigOption(name = "Warn Empty", desc = "Warn when no item is set in the RNG Meter.")
@ConfigEditorBoolean
public boolean warnEmpty = false;
@@ -410,6 +475,7 @@ public class SlayerConfig {
@Expose
@ConfigOption(name = "Enabled", desc = "Send a title when your boss is about to spawn.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean enabled = false;
@Expose
@@ -426,20 +492,30 @@ public class SlayerConfig {
@Expose
@ConfigOption(name = "Miniboss Highlight", desc = "Highlight slayer miniboss in blue color.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean slayerMinibossHighlight = false;
@Expose
+ @ConfigOption(name = "Line to Miniboss", desc = "Adds a line to every slayer miniboss around you.")
+ @ConfigEditorBoolean
+ @FeatureToggle
+ public boolean slayerMinibossLine = false;
+
+ @Expose
@ConfigOption(name = "Hide Mob Names", desc = "Hide the name of the mobs you need to kill in order for the Slayer boss to spawn. Exclude mobs that are damaged, corrupted, runic or semi rare.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean hideMobNames = false;
@Expose
@ConfigOption(name = "Quest Warning", desc = "Warning when wrong slayer quest is selected, or killing mobs for the wrong slayer.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean questWarning = true;
@Expose
@ConfigOption(name = "Quest Warning Title", desc = "Sends a Title when warning.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean questWarningTitle = true;
}
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/SummoningsConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/SummoningsConfig.java
index 20e8aaa45..9881c2afa 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/SummoningsConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/SummoningsConfig.java
@@ -1,5 +1,6 @@
package at.hannibal2.skyhanni.config.features;
+import at.hannibal2.skyhanni.config.FeatureToggle;
import at.hannibal2.skyhanni.config.core.config.Position;
import com.google.gson.annotations.Expose;
import io.github.moulberry.moulconfig.annotations.ConfigAccordionId;
@@ -13,6 +14,7 @@ public class SummoningsConfig {
@ConfigOption(name = "Summoning Soul Display", desc = "Show the name of dropped summoning souls laying on the ground. " +
"§cNot working in dungeons if Skytils' 'Hide Non-Starred Mobs Nametags' feature is enabled!")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean summoningSoulDisplay = false;
@Expose
@@ -24,6 +26,7 @@ public class SummoningsConfig {
@ConfigOption(name = "Summoning Mob Display", desc = "Show the health of your spawned summons.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 0)
+ @FeatureToggle
public boolean summoningMobDisplay = false;
@Expose
@@ -33,11 +36,13 @@ public class SummoningsConfig {
@ConfigOption(name = "Summoning Mob Nametag", desc = "Hide the nametag of your spawned summons.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 0)
+ @FeatureToggle
public boolean summoningMobHideNametag = false;
@Expose
@ConfigOption(name = "Summoning Mob Color", desc = "Marks own summons green.")
@ConfigEditorBoolean
@ConfigAccordionId(id = 0)
+ @FeatureToggle
public boolean summoningMobColored = false;
}
diff --git a/src/main/java/at/hannibal2/skyhanni/data/ChatManager.kt b/src/main/java/at/hannibal2/skyhanni/data/ChatManager.kt
index 4954d2caf..c7ddf1777 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/ChatManager.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/ChatManager.kt
@@ -156,8 +156,8 @@ object ChatManager {
val chatGUI = Minecraft.getMinecraft().ingameGUI.chatGUI
@Suppress("UNCHECKED_CAST")
- val chatLines = chatLinesField.invokeExact(chatGUI) as MutableList<ChatLine>
- if (!chatLines.removeIf { it.chatComponent === message }) return
+ val chatLines = chatLinesField.invokeExact(chatGUI) as MutableList<ChatLine?>? ?: return
+ if (!chatLines.removeIf { it?.chatComponent === message }) return
chatGUI.refreshChat()
val history = messageHistory[IdentityCharacteristics(message)] ?: return
diff --git a/src/main/java/at/hannibal2/skyhanni/data/EntityData.kt b/src/main/java/at/hannibal2/skyhanni/data/EntityData.kt
index dad4a1bf3..40cada194 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/EntityData.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/EntityData.kt
@@ -3,6 +3,7 @@ package at.hannibal2.skyhanni.data
import at.hannibal2.skyhanni.events.*
import at.hannibal2.skyhanni.utils.EntityUtils
import at.hannibal2.skyhanni.utils.LorenzUtils.baseMaxHealth
+import at.hannibal2.skyhanni.utils.LorenzUtils.derpy
import net.minecraft.client.Minecraft
import net.minecraft.client.entity.EntityOtherPlayerMP
import net.minecraft.client.entity.EntityPlayerSP
@@ -26,7 +27,7 @@ class EntityData {
val oldMaxHealth = maxHealthMap.getOrDefault(entity, -1)
if (oldMaxHealth != maxHealth) {
maxHealthMap[entity] = maxHealth
- EntityMaxHealthUpdateEvent(entity, maxHealth).postAndCatch()
+ EntityMaxHealthUpdateEvent(entity, maxHealth.derpy()).postAndCatch()
}
}
}
@@ -70,7 +71,7 @@ class EntityData {
}
if (entity is EntityLivingBase) {
- EntityHealthUpdateEvent(entity, health).postAndCatch()
+ EntityHealthUpdateEvent(entity, health.derpy()).postAndCatch()
}
}
}
diff --git a/src/main/java/at/hannibal2/skyhanni/data/GardenCropMilestones.kt b/src/main/java/at/hannibal2/skyhanni/data/GardenCropMilestones.kt
index 0742fae1e..277fdb56c 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/GardenCropMilestones.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/GardenCropMilestones.kt
@@ -2,159 +2,104 @@ package at.hannibal2.skyhanni.data
import at.hannibal2.skyhanni.events.CropMilestoneUpdateEvent
import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent
+import at.hannibal2.skyhanni.events.RepositoryReloadEvent
import at.hannibal2.skyhanni.features.garden.CropType
import at.hannibal2.skyhanni.features.garden.GardenAPI
import at.hannibal2.skyhanni.utils.ItemUtils.getLore
import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher
+import at.hannibal2.skyhanni.utils.jsonobjects.GardenJson
+import net.minecraft.item.ItemStack
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
-class GardenCropMilestones {
+object GardenCropMilestones {
private val cropPattern = "§7Harvest §f(?<name>.*) §7on .*".toPattern()
private val totalPattern = "§7Total: §a(?<name>.*)".toPattern()
- // Add when api support is there
-// @SubscribeEvent
-// fun onProfileDataLoad(event: ProfileApiDataLoadedEvent) {
-// val profileData = event.profileData
-// for ((key, value) in profileData.entrySet()) {
-// if (key.startsWith("experience_skill_")) {
-// val label = key.substring(17)
-// val exp = value.asLong
-// gardenExp[label] = exp
-// }
-// }
-// }
+ fun getCropTypeByLore(itemStack: ItemStack): CropType? {
+ for (line in itemStack.getLore()) {
+ cropPattern.matchMatcher(line) {
+ val name = group("name")
+ return CropType.getByNameOrNull(name)
+ }
+ }
+ return null
+ }
@SubscribeEvent
fun onInventoryOpen(event: InventoryFullyOpenedEvent) {
if (event.inventoryName != "Crop Milestones") return
for ((_, stack) in event.inventoryItems) {
- var crop: CropType? = null
+ val crop = getCropTypeByLore(stack) ?: continue
for (line in stack.getLore()) {
- cropPattern.matchMatcher(line) {
- val name = group("name")
- crop = CropType.getByNameOrNull(name)
- }
totalPattern.matchMatcher(line) {
val amount = group("name").replace(",", "").toLong()
- crop?.setCounter(amount)
+ crop.setCounter(amount)
}
}
}
CropMilestoneUpdateEvent().postAndCatch()
}
- companion object {
- val cropCounter: MutableMap<CropType, Long>? get() = GardenAPI.config?.cropCounter
+ private var cropMilestoneData: Map<CropType, List<Int>>? = null
- // TODO make nullable
- fun CropType.getCounter() = cropCounter?.get(this) ?: 0
+ val cropCounter: MutableMap<CropType, Long>? get() = GardenAPI.config?.cropCounter
- fun CropType.setCounter(counter: Long) {
- cropCounter?.set(this, counter)
- }
+ // TODO make nullable
+ fun CropType.getCounter() = cropCounter?.get(this) ?: 0
- fun CropType.isMaxed() = getCounter() >= 1_000_000_000
+ fun CropType.setCounter(counter: Long) {
+ cropCounter?.set(this, counter)
+ }
- fun getTierForCrops(crops: Long): Int {
- var tier = 0
- var totalCrops = 0L
- for (tierCrops in cropMilestone) {
- totalCrops += tierCrops
- if (totalCrops > crops) {
- return tier
- }
- tier++
- }
+ fun CropType.isMaxed(): Boolean {
+ val maxValue = cropMilestoneData?.get(this)?.sum() ?: 1_000_000_000 // 1 bil for now
+ return getCounter() >= maxValue
+ }
- return tier
+ fun getTierForCropCount(count: Long, crop: CropType): Int {
+ var tier = 0
+ var totalCrops = 0L
+ val cropMilestone = cropMilestoneData?.get(crop) ?: return 0
+ for (tierCrops in cropMilestone) {
+ totalCrops += tierCrops
+ if (totalCrops > count) {
+ return tier
+ }
+ tier++
}
- fun getCropsForTier(requestedTier: Int): Long {
- var totalCrops = 0L
- var tier = 0
- for (tierCrops in cropMilestone) {
- totalCrops += tierCrops
- tier++
- if (tier == requestedTier) {
- return totalCrops
- }
- }
+ return tier
+ }
- return 0
+ fun getMaxTier() = cropMilestoneData?.values?.firstOrNull()?.size ?: 0
+
+ fun getCropsForTier(requestedTier: Int, crop: CropType): Long {
+ var totalCrops = 0L
+ var tier = 0
+ val cropMilestone = cropMilestoneData?.get(crop) ?: return 0
+ for (tierCrops in cropMilestone) {
+ totalCrops += tierCrops
+ tier++
+ if (tier == requestedTier) {
+ return totalCrops
+ }
}
- fun CropType.progressToNextLevel(): Double {
- val progress = getCounter()
- val startTier = getTierForCrops(progress)
- val startCrops = getCropsForTier(startTier)
- val end = getCropsForTier(startTier + 1).toDouble()
- return (progress - startCrops) / (end - startCrops)
- }
+ return 0
+ }
+
+ fun CropType.progressToNextLevel(): Double {
+ val progress = getCounter()
+ val startTier = getTierForCropCount(progress, this)
+ val startCrops = getCropsForTier(startTier, this)
+ val end = getCropsForTier(startTier + 1, this).toDouble()
+ return (progress - startCrops) / (end - startCrops)
+ }
- // TODO use repo
- private val cropMilestone = listOf(
- 100,
- 150,
- 250,
- 500,
- 1500,
- 2500,
- 5000,
- 5000,
- 10000,
- 25000,
- 25000,
- 25000,
- 30000,
- 70000,
- 100000,
- 200000,
- 250000,
- 250000,
- 500000,
- 1000000,
- 1500000,
- 2000000,
- 3000000,
- 4000000,
- 7000000,
- 10000000,
- 20000000,
- 25000000,
- 25000000,
- 50000000,
- 50000000,
- 50000000,
- 50000000,
- 50000000,
- 50000000,
- 50000000,
- 50000000,
- 50000000,
- 50000000,
- 50000000,
- 50000000,
- 50000000,
- 50000000,
- 50000000,
- 50000000,
- 100000000,
- )
+ @SubscribeEvent
+ fun onRepoReload(event: RepositoryReloadEvent) {
+ val data = event.getConstant<GardenJson>("Garden") ?: return
+ cropMilestoneData = data.crop_milestones
}
-}
-
-// TODO delete?
-private fun String.formatNumber(): Long {
- var text = replace(",", "")
- val multiplier = if (text.endsWith("k")) {
- text = text.substring(0, text.length - 1)
- 1_000
- } else if (text.endsWith("m")) {
- text = text.substring(0, text.length - 1)
- 1_000_000
- } else 1
- val d = text.toDouble()
- return (d * multiplier).toLong()
-}
+} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/data/MayorElection.kt b/src/main/java/at/hannibal2/skyhanni/data/MayorElection.kt
index 92f7bebb3..0681b8632 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/MayorElection.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/MayorElection.kt
@@ -21,12 +21,9 @@ class MayorElection {
var candidates = mapOf<Int, MayorJson.Candidate>()
var currentCandidate: MayorJson.Candidate? = null
- fun isPerkActive(mayor: String, perk: String): Boolean {
- return currentCandidate?.let { currentCandidate ->
- currentCandidate.name == mayor && currentCandidate.perks.any { it.name == perk }
- } ?: false
- }
-
+ fun isPerkActive(mayor: String, perk: String) = currentCandidate?.let { currentCandidate ->
+ currentCandidate.name == mayor && currentCandidate.perks.any { it.name == perk }
+ } ?: false
}
@SubscribeEvent
diff --git a/src/main/java/at/hannibal2/skyhanni/data/ProfileStorageData.kt b/src/main/java/at/hannibal2/skyhanni/data/ProfileStorageData.kt
index b69afe21a..f9eb6b024 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/ProfileStorageData.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/ProfileStorageData.kt
@@ -107,8 +107,6 @@ object ProfileStorageData {
val oldHidden = SkyHanniMod.feature.hidden
if (oldHidden.isMigrated) return
- SkyHanniMod.feature.storage.apiKey = oldHidden.apiKey
-
SkyHanniMod.feature.storage?.let {
it.gardenJacobFarmingContestTimes = oldHidden.gardenJacobFarmingContestTimes
}
diff --git a/src/main/java/at/hannibal2/skyhanni/data/SackAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/SackAPI.kt
new file mode 100644
index 000000000..3990e13d6
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/data/SackAPI.kt
@@ -0,0 +1,48 @@
+package at.hannibal2.skyhanni.data
+
+import at.hannibal2.skyhanni.events.LorenzChatEvent
+import at.hannibal2.skyhanni.events.SackChangeEvent
+import at.hannibal2.skyhanni.utils.NEUInternalName
+import at.hannibal2.skyhanni.utils.StringUtils.removeColor
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+
+
+class SackAPI {
+
+ data class SackChange(val delta: Int, val internalName: NEUInternalName, val sacks: List<String>)
+
+ private val sackChangeRegex = Regex("""([+-][\d,]+) (.+) \((.+)\)""")
+
+ @SubscribeEvent
+ fun onChat(event: LorenzChatEvent) {
+ if (!event.message.removeColor().startsWith("[Sacks]")) return
+
+ val sackAddText = event.chatComponent.siblings.firstNotNullOfOrNull { sibling ->
+ sibling.chatStyle?.chatHoverEvent?.value?.formattedText?.removeColor()?.takeIf {
+ it.startsWith("Added")
+ }
+ } ?: ""
+ val sackRemoveText = event.chatComponent.siblings.firstNotNullOfOrNull { sibling ->
+ sibling.chatStyle?.chatHoverEvent?.value?.formattedText?.removeColor()?.takeIf {
+ it.startsWith("Removed")
+ }
+ } ?: ""
+
+ val sackChangeText = sackAddText + sackRemoveText
+ if (sackChangeText.isEmpty()) return
+
+ val otherItemsAdded = sackAddText.contains("other items")
+ val otherItemsRemoved = sackRemoveText.contains("other items")
+
+ val sackChanges = ArrayList<SackChange>()
+ for (match in sackChangeRegex.findAll(sackChangeText)) {
+ val delta = match.groups[1]!!.value.replace(",", "").toInt()
+ val item = match.groups[2]!!.value
+ val sacks = match.groups[3]!!.value.split(", ")
+
+ val internalName = NEUInternalName.fromItemName(item)
+ sackChanges.add(SackChange(delta, internalName, sacks))
+ }
+ SackChangeEvent(sackChanges, otherItemsAdded, otherItemsRemoved).postAndCatch()
+ }
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/data/SlayerAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/SlayerAPI.kt
index 62e151d2f..3a3bd8b33 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/SlayerAPI.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/SlayerAPI.kt
@@ -1,7 +1,6 @@
package at.hannibal2.skyhanni.data
import at.hannibal2.skyhanni.events.*
-import at.hannibal2.skyhanni.features.bazaar.BazaarApi.Companion.getBazaarData
import at.hannibal2.skyhanni.features.slayer.SlayerType
import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName
import at.hannibal2.skyhanni.utils.ItemUtils.nameWithEnchantment
@@ -9,6 +8,7 @@ import at.hannibal2.skyhanni.utils.LorenzUtils
import at.hannibal2.skyhanni.utils.LorenzUtils.nextAfter
import at.hannibal2.skyhanni.utils.NEUInternalName
import at.hannibal2.skyhanni.utils.NEUItems.getItemStack
+import at.hannibal2.skyhanni.utils.NEUItems.getNpcPriceOrNull
import at.hannibal2.skyhanni.utils.NEUItems.getPrice
import at.hannibal2.skyhanni.utils.NumberUtil
import at.hannibal2.skyhanni.utils.StringUtils.removeColor
@@ -67,7 +67,7 @@ object SlayerAPI {
val displayName = getNameWithEnchantmentFor(internalName)
val price = internalName.getPrice()
- val npcPrice = internalName.getBazaarData()?.npcPrice ?: 0.0
+ val npcPrice = internalName.getNpcPriceOrNull() ?: 0.0
val maxPrice = npcPrice.coerceAtLeast(price)
val totalPrice = maxPrice * amount
diff --git a/src/main/java/at/hannibal2/skyhanni/data/TitleUtils.kt b/src/main/java/at/hannibal2/skyhanni/data/TitleUtils.kt
index d66a321b2..2004a1ed1 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/TitleUtils.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/TitleUtils.kt
@@ -2,34 +2,36 @@ package at.hannibal2.skyhanni.data
import at.hannibal2.skyhanni.events.GuiRenderEvent
import at.hannibal2.skyhanni.events.PreProfileSwitchEvent
+import at.hannibal2.skyhanni.utils.SimpleTimeMark
import io.github.moulberry.moulconfig.internal.TextRenderUtils
import net.minecraft.client.Minecraft
import net.minecraft.client.gui.ScaledResolution
import net.minecraft.client.renderer.GlStateManager
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import kotlin.time.Duration
class TitleUtils {
companion object {
private var display = ""
- private var endTime = 0L
+ private var endTime = SimpleTimeMark.farPast()
private var heightModifier = 1.8
- fun sendTitle(text: String, duration: Int, height: Double = 1.8) {
+ fun sendTitle(text: String, duration: Duration, height: Double = 1.8) {
display = "§f$text"
- endTime = System.currentTimeMillis() + duration
+ endTime = SimpleTimeMark.now() + duration
heightModifier = height
}
}
@SubscribeEvent
fun onPreProfileSwitch(event: PreProfileSwitchEvent) {
- sendTitle("", 1)
+ endTime = SimpleTimeMark.farPast()
}
@SubscribeEvent
fun onRenderOverlay(event: GuiRenderEvent.GameOverlayRenderEvent) {
- if (System.currentTimeMillis() > endTime) return
+ if (endTime.isInPast()) return
val scaledResolution = ScaledResolution(Minecraft.getMinecraft())
val width = scaledResolution.scaledWidth
diff --git a/src/main/java/at/hannibal2/skyhanni/events/SackChangeEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/SackChangeEvent.kt
new file mode 100644
index 000000000..b2006bc0d
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/events/SackChangeEvent.kt
@@ -0,0 +1,9 @@
+package at.hannibal2.skyhanni.events
+
+import at.hannibal2.skyhanni.data.SackAPI
+
+class SackChangeEvent(
+ val sackChanged: List<SackAPI.SackChange>,
+ val otherItemsAdded: Boolean,
+ val otherItemsRemoved: Boolean
+) : LorenzEvent()
diff --git a/src/main/java/at/hannibal2/skyhanni/features/bazaar/BazaarData.kt b/src/main/java/at/hannibal2/skyhanni/features/bazaar/BazaarData.kt
index 3562be68a..daed03152 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/bazaar/BazaarData.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/bazaar/BazaarData.kt
@@ -4,5 +4,4 @@ data class BazaarData(
val displayName: String,
val sellPrice: Double,
val buyPrice: Double,
- val npcPrice: Double,
) \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/features/bazaar/BazaarDataHolder.kt b/src/main/java/at/hannibal2/skyhanni/features/bazaar/BazaarDataHolder.kt
index 039b57540..61f19a630 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/bazaar/BazaarDataHolder.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/bazaar/BazaarDataHolder.kt
@@ -18,6 +18,8 @@ class BazaarDataHolder {
companion object {
private val bazaarData = mutableMapOf<NEUInternalName, BazaarData>()
private var npcPrices = mapOf<NEUInternalName, Double>()
+
+ fun getNpcPrice(internalName: NEUInternalName) = npcPrices[internalName]
}
private fun loadNpcPrices(): MutableMap<NEUInternalName, Double> {
@@ -66,29 +68,9 @@ class BazaarDataHolder {
val displayName = stack.name!!.removeColor()
val sellPrice = internalName.getPrice(true)
val buyPrice = internalName.getPrice(false)
- val npcPrice = npcPrices[internalName].let {
- if (it == null) {
- if (!ignoreNoNpcPrice(internalName)) {
- LorenzUtils.debug("NPC price not found for '$internalName'")
- }
- 0.0
- } else it
- }
- val data = BazaarData(displayName, sellPrice, buyPrice, npcPrice)
+ val data = BazaarData(displayName, sellPrice, buyPrice)
bazaarData[internalName] = data
return data
}
-
- private fun ignoreNoNpcPrice(internalName: NEUInternalName): Boolean {
- if (internalName.startsWith("TURBO_")) return true
- if (internalName.equals("PURPLE_CANDY")) return true
- if (internalName.equals("JACOBS_TICKET")) return true
- if (internalName.equals("RAW_SOULFLOW")) return true
- if (internalName.equals("DERELICT_ASHE")) return true
-
- if (internalName.contains(";")) return true
-
- return false
- }
} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/features/bingo/MinionCraftHelper.kt b/src/main/java/at/hannibal2/skyhanni/features/bingo/MinionCraftHelper.kt
index ae956f2d8..4ebdc1ffa 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/bingo/MinionCraftHelper.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/bingo/MinionCraftHelper.kt
@@ -16,6 +16,7 @@ import io.github.moulberry.notenoughupdates.recipes.CraftingRecipe
import net.minecraft.client.Minecraft
import net.minecraft.item.ItemStack
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import kotlin.time.Duration.Companion.seconds
class MinionCraftHelper {
private var minionNamePattern = "(?<name>.*) Minion (?<number>.*)".toPattern()
@@ -248,7 +249,7 @@ class MinionCraftHelper {
private fun notify(minionName: String) {
if (alreadyNotified.contains(minionName)) return
- TitleUtils.sendTitle("Can craft $minionName", 3_000)
+ TitleUtils.sendTitle("Can craft $minionName", 3.seconds)
alreadyNotified.add(minionName)
}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/chat/ChatFilter.kt b/src/main/java/at/hannibal2/skyhanni/features/chat/ChatFilter.kt
index a8733abff..e5ba401eb 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/chat/ChatFilter.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/chat/ChatFilter.kt
@@ -25,7 +25,6 @@ class ChatFilter {
warping(message) && config.warping -> "warping"
welcome(message) && config.welcome -> "welcome"
isGuildExp(message) && config.guildExp -> "guild_exp"
- friendJoin(message) && config.friendJoinLeft -> "friend_join"
killCombo(message) && config.killCombo -> "kill_combo"
profileJoin(message) && config.profileJoin -> "profile_join"
@@ -65,16 +64,6 @@ class ChatFilter {
return false
}
- private fun friendJoin(message: String): Boolean {
- return when {
- message.matchRegex("§aFriend > §r(.*) §r§e(joined|left).") -> {
- true
- }
-
- else -> false
- }
- }
-
private fun uselessNotification(message: String): Boolean {
if (message.matchRegex("§aYou tipped (\\d+) (player|players)!")) return true
diff --git a/src/main/java/at/hannibal2/skyhanni/features/chat/Translator.kt b/src/main/java/at/hannibal2/skyhanni/features/chat/Translator.kt
new file mode 100644
index 000000000..f39905876
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/chat/Translator.kt
@@ -0,0 +1,218 @@
+package at.hannibal2.skyhanni.features.chat
+
+import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.test.command.CopyErrorCommand
+import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.OSUtils
+import at.hannibal2.skyhanni.utils.StringUtils.removeColor
+import com.google.gson.*
+import net.minecraft.event.ClickEvent
+import net.minecraft.event.HoverEvent
+import net.minecraft.util.ChatComponentText
+import net.minecraft.util.ChatStyle
+import net.minecraftforge.client.event.ClientChatReceivedEvent
+import net.minecraftforge.fml.common.eventhandler.EventPriority
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import org.apache.http.client.config.RequestConfig
+import org.apache.http.client.methods.HttpGet
+import org.apache.http.impl.client.HttpClientBuilder
+import org.apache.http.impl.client.HttpClients
+import org.apache.http.message.BasicHeader
+import org.apache.http.util.EntityUtils
+import java.net.URLDecoder
+import java.net.URLEncoder
+
+class Translator {
+
+ private val messageContentRegex = Regex(".*: (.*)")
+
+ // Logic for listening for a user click on a chat message is from NotEnoughUpdates
+
+ @SubscribeEvent(priority = EventPriority.LOWEST, receiveCanceled = true)
+ fun onGuiChat(e: ClientChatReceivedEvent) {
+ if (!SkyHanniMod.feature.chat.translator) return
+ if (e.type != 0.toByte()) return // If this is not a player-sent message, return
+
+ val chatComponent = e.message
+ // If you want to help me debug, experience the bug while this line is uncommented (spams logs)
+// consoleLog(chatComponent.toString())
+ val message = chatComponent.unformattedText
+ if (!messageContentRegex.matches(message.removeColor())) return
+
+ val clickStyle = createClickStyle(message)
+ chatComponent.setChatStyle(clickStyle)
+ }
+
+ private fun createClickStyle(message: String): ChatStyle {
+ val style = ChatStyle()
+ style.setChatClickEvent(
+ ClickEvent(
+ ClickEvent.Action.RUN_COMMAND,
+ "/shsendtranslation ${messageContentRegex.find(message.removeColor())!!.groupValues[1]}"
+ )
+ )
+ style.setChatHoverEvent(
+ HoverEvent(
+ HoverEvent.Action.SHOW_TEXT,
+ ChatComponentText("§bClick to translate!")
+ )
+ )
+ return style
+ }
+
+
+ companion object {
+ // Using my own getJSONResponse because of 1 line of difference.
+ private val parser = JsonParser()
+ private val builder: HttpClientBuilder =
+ HttpClients.custom().setUserAgent("SkyHanni/${SkyHanniMod.version}")
+ .setDefaultHeaders(
+ mutableListOf(
+ BasicHeader("Pragma", "no-cache"),
+ BasicHeader("Cache-Control", "no-cache")
+ )
+ )
+ .setDefaultRequestConfig(
+ RequestConfig.custom()
+ .build()
+ )
+ .useSystemProperties()
+
+ /*
+ * Simplified version of the JSON response:
+ * [
+ * [
+ * [
+ * 'translated sentence one with a space after the punctuation. '
+ * 'original sentence one without a space after the punctuation.'
+ * ],
+ * [
+ * 'translated sentence two without punctuation bc it's last'
+ * 'original sentence two without punctuation'
+ * ]
+ * ],
+ * null,
+ * 'target language as a two letter code following ISO 639-1',
+ * ]
+ */
+
+ private fun getJSONResponse(urlString: String, silentError: Boolean = false): JsonElement {
+ val client = builder.build()
+ try {
+ client.execute(HttpGet(urlString)).use { response ->
+ val entity = response.entity
+ if (entity != null) {
+ val retSrc = EntityUtils.toString(entity)
+ try {
+ return parser.parse(retSrc)
+ } catch (e: JsonSyntaxException) {
+ if (e.message?.contains("Use JsonReader.setLenient(true)") == true) {
+ println("MalformedJsonException: Use JsonReader.setLenient(true)")
+ println(" - getJSONResponse: '$urlString'")
+ LorenzUtils.debug("MalformedJsonException: Use JsonReader.setLenient(true)")
+ } else if (retSrc.contains("<center><h1>502 Bad Gateway</h1></center>")) {
+ e.printStackTrace()
+
+ } else {
+ CopyErrorCommand.logError(
+ Error("Hypixel API error for url: '$urlString'", e),
+ "Failed to load data from Hypixel API"
+ )
+ }
+ }
+ }
+ }
+ } catch (throwable: Throwable) {
+ if (silentError) {
+ throw throwable
+ } else {
+ CopyErrorCommand.logError(
+ Error("Hypixel API error for url: '$urlString'", throwable),
+ "Failed to load data from Hypixel API"
+ )
+ }
+ } finally {
+ client.close()
+ }
+ return JsonObject()
+ }
+
+ private fun getTranslationToEnglish(message: String): String {
+ val url =
+ "https://translate.googleapis.com/translate_a/single?client=gtx&sl=auto&tl=en&dt=t&q=" + URLEncoder.encode(
+ message,
+ "UTF-8"
+ )
+
+ var messageToSend = ""
+ val layer1 = getJSONResponse(url).asJsonArray
+ val language = layer1[2].toString()
+ if (language == "en") return "Unable to translate!"
+
+ val layer2 = layer1[0] as JsonArray
+
+ for (layer3 in layer2) {
+ val arrayLayer3 = layer3 as JsonArray
+ val sentence = arrayLayer3[0].toString()
+ val sentenceWithoutQuotes = sentence.substring(1, sentence.length - 1)
+ messageToSend = "$messageToSend$sentenceWithoutQuotes"
+ }
+ messageToSend = "$messageToSend §7(Language: $language)"
+
+ return URLDecoder.decode(messageToSend, "UTF-8").replace("\\", "")
+
+ }
+
+ private fun getTranslationFromEnglish(message: String, lang: String): String {
+ val url =
+ "https://translate.googleapis.com/translate_a/single?client=gtx&sl=en&tl=$lang&dt=t&q=" + URLEncoder.encode(
+ message,
+ "UTF-8"
+ )
+
+ val layer1 = getJSONResponse(url).asJsonArray
+ val layer2 = layer1[0] as JsonArray
+
+ val firstSentence = (layer2[0] as JsonArray).get(0).toString()
+ var messageToSend = firstSentence.substring(0, firstSentence.length - 1)
+ for (sentenceIndex in 1..<layer2.size()) {
+ val sentence = (layer2[sentenceIndex] as JsonArray).get(0).toString()
+ val sentenceWithoutQuotes = sentence.substring(1, sentence.length - 1)
+ messageToSend = "$messageToSend$sentenceWithoutQuotes"
+ } // The first translated sentence only has 1 extra char at the end, but sentences after it need 1 at the front and 1 at the end removed in the substring
+ messageToSend = messageToSend.substring(1, messageToSend.length - 1)
+ return URLDecoder.decode(messageToSend, "UTF-8").replace("\\", "")
+ }
+
+ fun toEnglish(args: Array<String>) {
+ if (!SkyHanniMod.feature.chat.translator) return
+ var message = ""
+ for (i in args) {
+ message = "$message$i "
+ }
+
+ val translation = getTranslationToEnglish(message)
+
+ if (translation == "Unable to translate!") LorenzUtils.chat("§c[SkyHanni] Unable to translate message :(")
+ else LorenzUtils.chat("§e[SkyHanni] Found translation: §f$translation")
+ }
+
+ fun fromEnglish(args: Array<String>) {
+ if (!SkyHanniMod.feature.chat.translator) return
+ if (args.size < 2 || args[0].length != 2) { // args[0] is the language code
+ LorenzUtils.chat("§cUsage: /shcopytranslation <two letter language code (at the end of a translation)> <message>")
+ return
+ }
+ val language = args[0]
+ var message = ""
+ for (i in 1..<args.size) {
+ message = "$message${args[i]} "
+ }
+
+ val translation = getTranslationFromEnglish(message, language)
+ LorenzUtils.chat("§6[SkyHanni] §eCopied translation to clipboard: $translation")
+ OSUtils.copyToClipboard(translation)
+ }
+ }
+
+} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/features/cosmetics/CosmeticFollowingLine.kt b/src/main/java/at/hannibal2/skyhanni/features/cosmetics/CosmeticFollowingLine.kt
new file mode 100644
index 000000000..1f84e9e7b
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/cosmetics/CosmeticFollowingLine.kt
@@ -0,0 +1,129 @@
+package at.hannibal2.skyhanni.features.cosmetics
+
+import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.events.LorenzTickEvent
+import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent
+import at.hannibal2.skyhanni.utils.LocationUtils
+import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.LorenzUtils.editCopy
+import at.hannibal2.skyhanni.utils.LorenzUtils.toChromaColor
+import at.hannibal2.skyhanni.utils.LorenzVec
+import at.hannibal2.skyhanni.utils.RenderUtils.draw3DLine
+import at.hannibal2.skyhanni.utils.RenderUtils.exactLocation
+import at.hannibal2.skyhanni.utils.SimpleTimeMark
+import net.minecraft.client.Minecraft
+import net.minecraftforge.client.event.RenderWorldLastEvent
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import java.awt.Color
+import kotlin.time.Duration.Companion.milliseconds
+import kotlin.time.Duration.Companion.seconds
+
+class CosmeticFollowingLine {
+ private val config get() = SkyHanniMod.feature.misc.cosmeticConfig.followingLineConfig
+
+ private var locations = mapOf<LorenzVec, LocationSpot>()
+ private var latestLocations = mapOf<LorenzVec, LocationSpot>()
+
+ class LocationSpot(val time: SimpleTimeMark, val onGround: Boolean)
+
+ @SubscribeEvent
+ fun onWorldChange(event: LorenzWorldChangeEvent) {
+ locations = emptyMap()
+ }
+
+ @SubscribeEvent
+ fun onRenderWorld(event: RenderWorldLastEvent) {
+ if (!LorenzUtils.inSkyBlock) return
+ if (!config.enabled) return
+
+ updateClose(event)
+
+ val firstPerson = Minecraft.getMinecraft().gameSettings.thirdPersonView == 0
+ val color = config.lineColor.toChromaColor()
+
+ renderClose(event, firstPerson, color)
+ renderFar(event, firstPerson, color)
+ }
+
+ private fun renderFar(
+ event: RenderWorldLastEvent,
+ firstPerson: Boolean,
+ color: Color
+ ) {
+ val last7 = locations.keys.toList().takeLast(7)
+ val last2 = locations.keys.toList().takeLast(2)
+
+ for ((a, b) in locations.keys.zipWithNext()) {
+ val locationSpot = locations[b]!!
+ if (firstPerson) {
+ if (!locationSpot.onGround) {
+ if (b in last7) {
+ // Do not render the line in the face, keep more distance while the line is in the air
+ continue
+ }
+ }
+ }
+ if (b in last2) {
+ if (locationSpot.time.passedSince() < 400.milliseconds) {
+ // Do not render the line directly next to the player, prevent laggy design
+ continue
+ }
+ }
+ event.draw3DLine(a, b, color, locationSpot.getWidth(), !config.behindBlocks)
+ }
+ }
+
+ private fun updateClose(event: RenderWorldLastEvent) {
+ val playerLocation = event.exactLocation(Minecraft.getMinecraft().thePlayer).add(0.0, 0.3, 0.0)
+
+ latestLocations = latestLocations.editCopy {
+ val locationSpot = LocationSpot(SimpleTimeMark.now(), Minecraft.getMinecraft().thePlayer.onGround)
+ this[playerLocation] = locationSpot
+ values.removeIf { it.time.passedSince() > 600.milliseconds }
+ }
+ }
+
+ private fun renderClose(event: RenderWorldLastEvent, firstPerson: Boolean, color: Color) {
+ if (firstPerson && latestLocations.any { !it.value.onGround }) return
+
+ for ((a, b) in latestLocations.keys.zipWithNext()) {
+ val locationSpot = latestLocations[b]!!
+ event.draw3DLine(a, b, color, locationSpot.getWidth(), !config.behindBlocks)
+ }
+ }
+
+ private fun LocationSpot.getWidth(): Int {
+ val millis = time.passedSince().inWholeMilliseconds
+ val percentage = millis.toDouble() / (config.secondsAlive * 1000.0)
+ val maxWidth = config.lineWidth
+ val lineWidth = 1 + maxWidth - percentage * maxWidth
+ return lineWidth.toInt().coerceAtLeast(1)
+ }
+
+ @SubscribeEvent
+ fun onTick(event: LorenzTickEvent) {
+ if (!LorenzUtils.inSkyBlock) return
+ if (!config.enabled) return
+
+ if (event.isMod(5)) {
+ locations = locations.editCopy { values.removeIf { it.time.passedSince() > config.secondsAlive.seconds } }
+
+ // Safety check to not cause lags
+ while (locations.size > 5_000) {
+ locations = locations.editCopy { remove(keys.first()) }
+ }
+ }
+
+ if (event.isMod(2)) {
+ val playerLocation = LocationUtils.playerLocation().add(0.0, 0.3, 0.0)
+
+ locations.keys.lastOrNull()?.let {
+ if (it.distance(playerLocation) < 0.1) return
+ }
+
+ locations = locations.editCopy {
+ this[playerLocation] = LocationSpot(SimpleTimeMark.now(), Minecraft.getMinecraft().thePlayer.onGround)
+ }
+ }
+ }
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/damageindicator/BossType.kt b/src/main/java/at/hannibal2/skyhanni/features/damageindicator/BossType.kt
index 4755d7dd1..264c8700a 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/damageindicator/BossType.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/damageindicator/BossType.kt
@@ -1,6 +1,11 @@
package at.hannibal2.skyhanni.features.damageindicator
-enum class BossType(val fullName: String, val bossTypeToggle: Int, val shortName: String = fullName, val showDeathTime: Boolean = false) {
+enum class BossType(
+ val fullName: String,
+ val bossTypeToggle: Int,
+ val shortName: String = fullName,
+ val showDeathTime: Boolean = false
+) {
GENERIC_DUNGEON_BOSS("Generic Dungeon boss", 0),//TODO split into different bosses
//Nether Mini Bosses
@@ -83,6 +88,8 @@ enum class BossType(val fullName: String, val bossTypeToggle: Int, val shortName
LEECH_SUPREME("§cLeech Supreme", 22),
BACTE("§aBacte", 22),
+ WINTER_REINDRAKE("Reindrake", 24),//TODO fix totally
+
//TODO arachne
//TODO corelone
diff --git a/src/main/java/at/hannibal2/skyhanni/features/damageindicator/DamageIndicatorManager.kt b/src/main/java/at/hannibal2/skyhanni/features/damageindicator/DamageIndicatorManager.kt
index 157883909..e27de7249 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/damageindicator/DamageIndicatorManager.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/damageindicator/DamageIndicatorManager.kt
@@ -637,16 +637,18 @@ class DamageIndicatorManager {
}
//Laser phase
- if (entity.ridingEntity != null) {
- val ticksAlive = entity.ridingEntity.ticksExisted.toLong()
- //TODO more tests, more exact values, better logic? idk make this working perfectly pls
- //val remainingTicks = 8 * 20 - ticksAlive
- val remainingTicks = (8.9 * 20).toLong() - ticksAlive
-
- if (config.showHealthDuringLaser) {
- entityData.nameSuffix = " §f" + formatDelay(remainingTicks * 50)
- } else {
- return formatDelay(remainingTicks * 50)
+ if (config.enderSlayer.laserPhaseTimer) {
+ if (entity.ridingEntity != null) {
+ val ticksAlive = entity.ridingEntity.ticksExisted.toLong()
+ //TODO more tests, more exact values, better logic? idk make this working perfectly pls
+ //val remainingTicks = 8 * 20 - ticksAlive
+ val remainingTicks = (7.4 * 20).toLong() - ticksAlive
+
+ if (config.enderSlayer.showHealthDuringLaser) {
+ entityData.nameSuffix = " §f" + formatDelay(remainingTicks * 50)
+ } else {
+ return formatDelay(remainingTicks * 50)
+ }
}
}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/damageindicator/MobFinder.kt b/src/main/java/at/hannibal2/skyhanni/features/damageindicator/MobFinder.kt
index c981beac3..5e660510e 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/damageindicator/MobFinder.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/damageindicator/MobFinder.kt
@@ -1,5 +1,6 @@
package at.hannibal2.skyhanni.features.damageindicator
+import at.hannibal2.skyhanni.data.IslandType
import at.hannibal2.skyhanni.features.dungeon.DungeonData
import at.hannibal2.skyhanni.features.dungeon.DungeonLividFinder
import at.hannibal2.skyhanni.features.rift.RiftAPI
@@ -10,6 +11,8 @@ import at.hannibal2.skyhanni.utils.EntityUtils.hasNameTagWith
import at.hannibal2.skyhanni.utils.LocationUtils.distanceToPlayer
import at.hannibal2.skyhanni.utils.LorenzUtils
import at.hannibal2.skyhanni.utils.LorenzUtils.baseMaxHealth
+import at.hannibal2.skyhanni.utils.LorenzUtils.derpy
+import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland
import at.hannibal2.skyhanni.utils.LorenzVec
import at.hannibal2.skyhanni.utils.StringUtils.matchRegex
import at.hannibal2.skyhanni.utils.getLorenzVec
@@ -257,7 +260,11 @@ class MobFinder {
}
if (entity is EntityDragon) {
//TODO testing and use sidebar data
- return EntityResult(bossType = BossType.END_ENDER_DRAGON)
+ if (IslandType.THE_END.isInIsland()) {
+ return EntityResult(bossType = BossType.END_ENDER_DRAGON)
+ } else if (IslandType.WINTER.isInIsland()) {
+ return EntityResult(bossType = BossType.WINTER_REINDRAKE)
+ }
}
if (entity is EntityIronGolem) {
if (entity.hasNameTagWith(3, "§e﴾ §8[§7Lv100§8] §lEndstone Protector§r ")) {
@@ -374,11 +381,16 @@ class MobFinder {
if (entity.hasNameTagWith(1, "[§7Lv300§8] §cArachne") ||
entity.hasNameTagWith(1, "[§7Lv300§8] §lArachne")
) {
+ val maxHealth = entity.baseMaxHealth
+ // Ignore the minis
+ if (maxHealth == 12 || maxHealth.derpy() == 4000) return null
return EntityResult(bossType = BossType.ARACHNE_SMALL)
}
if (entity.hasNameTagWith(1, "[§7Lv500§8] §cArachne") ||
entity.hasNameTagWith(1, "[§7Lv500§8] §lArachne")
) {
+ val maxHealth = entity.baseMaxHealth
+ if (maxHealth == 12 || maxHealth.derpy() == 20_000) return null
return EntityResult(bossType = BossType.ARACHNE_BIG)
}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/diana/BurrowWarpHelper.kt b/src/main/java/at/hannibal2/skyhanni/features/event/diana/BurrowWarpHelper.kt
index c58ff7d90..fe9efd09a 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/event/diana/BurrowWarpHelper.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/event/diana/BurrowWarpHelper.kt
@@ -12,6 +12,7 @@ import net.minecraftforge.fml.common.gameevent.InputEvent.KeyInputEvent
import org.lwjgl.input.Keyboard
class BurrowWarpHelper {
+ private val config get() = SkyHanniMod.feature.diana
private var lastWarpTime = 0L
private var lastWarp: WarpPoint? = null
@@ -20,11 +21,11 @@ class BurrowWarpHelper {
fun onKeyBindPressed(event: KeyInputEvent) {
if (!LorenzUtils.inSkyBlock) return
if (LorenzUtils.skyBlockIsland != IslandType.HUB) return
- if (!SkyHanniMod.feature.diana.burrowNearestWarp) return
+ if (!config.burrowNearestWarp) return
if (!Keyboard.getEventKeyState()) return
val key = if (Keyboard.getEventKey() == 0) Keyboard.getEventCharacter().code + 256 else Keyboard.getEventKey()
- if (SkyHanniMod.feature.diana.keyBindWarp == key) {
+ if (config.keyBindWarp == key) {
currentWarp?.let {
if (System.currentTimeMillis() > lastWarpTime + 5_000) {
lastWarpTime = System.currentTimeMillis()
@@ -43,7 +44,7 @@ class BurrowWarpHelper {
val time = System.currentTimeMillis() - lastWarpTime
if (time < 1_000) {
lastWarp?.let {
- it.enabled = false
+ it.unlocked = false
LorenzUtils.chat(
"§e[SkyHanni] Detected not having access to warp point §b${it.displayName}§e!\n" +
"§e[SkyHanni] Use §c/shresetburrowwarps §eonce you have activated this travel scroll."
@@ -73,13 +74,12 @@ class BurrowWarpHelper {
}
}
- private fun getNearestWarpPoint(location: LorenzVec): WarpPoint {
- val map = WarpPoint.entries.filter { it.enabled }.map { it to it.distance(location) }
- return map.sorted().first().first
- }
+ private fun getNearestWarpPoint(location: LorenzVec) =
+ WarpPoint.entries.filter { it.unlocked && !it.ignored() }.map { it to it.distance(location) }
+ .sorted().first().first
fun resetDisabledWarps() {
- WarpPoint.entries.forEach { it.enabled = true }
+ WarpPoint.entries.forEach { it.unlocked = true }
LorenzUtils.chat("§e[SkyHanni] Reset disabled burrow warps.")
}
}
@@ -88,15 +88,15 @@ class BurrowWarpHelper {
val displayName: String,
private val location: LorenzVec,
private val extraBlocks: Int,
- var enabled: Boolean = true,
+ val ignored: () -> Boolean = { false },
+ var unlocked: Boolean = true,
) {
HUB("Hub", LorenzVec(-3, 70, -70), 2),
CASTLE("Castle", LorenzVec(-250, 130, 45), 10),
-
- // CRYPT("Crypt", LorenzVec(-190, 74, -88), 25),
+ CRYPT("Crypt", LorenzVec(-190, 74, -88), 15, { SkyHanniMod.feature.diana.ignoredWarps.crypt }),
DA("Dark Auction", LorenzVec(91, 74, 173), 2),
MUSEUM("Museum", LorenzVec(-75, 76, 81), 2),
- WIZARD("Wizard", LorenzVec(42.5, 122.0, 69.0), 5),
+ WIZARD("Wizard", LorenzVec(42.5, 122.0, 69.0), 5, { SkyHanniMod.feature.diana.ignoredWarps.wizard }),
;
fun distance(other: LorenzVec): Double = other.distance(location) + extraBlocks
diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/diana/GriffinPetWarning.kt b/src/main/java/at/hannibal2/skyhanni/features/event/diana/GriffinPetWarning.kt
index f979894c4..5a578590f 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/event/diana/GriffinPetWarning.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/event/diana/GriffinPetWarning.kt
@@ -24,7 +24,7 @@ class GriffinPetWarning {
if (!DianaAPI.hasGriffinPet()) {
if (lastWarnTime.passedSince() > 30.seconds) {
lastWarnTime = SimpleTimeMark.now()
- TitleUtils.sendTitle("§cGriffin Pet!", 3_000)
+ TitleUtils.sendTitle("§cGriffin Pet!", 3.seconds)
LorenzUtils.chat("§e[SkyHanni] Reminder to use a Griffin pet for Mythological Ritual!")
}
}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/diana/InquisitorWaypointShare.kt b/src/main/java/at/hannibal2/skyhanni/features/event/diana/InquisitorWaypointShare.kt
index 9347d1580..7a8ea5d2b 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/event/diana/InquisitorWaypointShare.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/event/diana/InquisitorWaypointShare.kt
@@ -9,7 +9,6 @@ import at.hannibal2.skyhanni.utils.*
import at.hannibal2.skyhanni.utils.LorenzUtils.editCopy
import at.hannibal2.skyhanni.utils.StringUtils.cleanPlayerName
import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher
-import io.github.moulberry.moulconfig.internal.KeybindHelper
import net.minecraft.client.Minecraft
import net.minecraft.client.entity.EntityOtherPlayerMP
import net.minecraft.network.play.server.S02PacketChat
@@ -86,13 +85,15 @@ object InquisitorWaypointShare {
foundInquisitor(lastInquisitor)
}
- if (message.endsWith("§r§eYou dug out §r§2a Minos Champion§r§e!")) {
- time = System.currentTimeMillis()
- logger.log("found Champion/Inquisitor")
+ // TODO: Change the check to only one line once we have a confirmed inquis message line
+ if (message.contains("§r§eYou dug out ")) {
+ if (message.contains("Inquis")) {
+ time = System.currentTimeMillis()
+ logger.log("found Inquisitor")
+ }
}
}
-
@SubscribeEvent
fun onJoinWorld(event: EntityJoinWorldEvent) {
if (!isEnabled()) return
@@ -133,7 +134,7 @@ object InquisitorWaypointShare {
// add repo kill switch
sendInquisitor()
} else {
- val keyName = KeybindHelper.getKeyName(config.keyBindShare)
+ val keyName = OSUtils.getKeyName(config.keyBindShare)
val message =
"§e[SkyHanni] §l§bYou found a Inquisitor! Press §l§chere §l§bor §c$keyName to share the location!"
LorenzUtils.clickableChat(message, "shshareinquis")
@@ -225,7 +226,7 @@ object InquisitorWaypointShare {
if (!waypoints.containsKey(cleanName)) {
LorenzUtils.chat("§e[SkyHanni] $playerName §l§efound an inquisitor at §l§c$x $y $z!")
if (cleanName != LorenzUtils.getPlayerName()) {
- TitleUtils.sendTitle("§dINQUISITOR §efrom §b$cleanName", 5_000)
+ TitleUtils.sendTitle("§dINQUISITOR §efrom §b$cleanName", 5.seconds)
SoundUtils.playBeepSound()
}
}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/fame/AccountUpgradeReminder.kt b/src/main/java/at/hannibal2/skyhanni/features/fame/AccountUpgradeReminder.kt
index 5ededb3ee..3690d8ea3 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/fame/AccountUpgradeReminder.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/fame/AccountUpgradeReminder.kt
@@ -72,9 +72,10 @@ class AccountUpgradeReminder {
if (!inInventory) return
val clickedItemLore = event.slot?.stack?.getLore() ?: return
if (clickedItemLore.getOrNull(0) != "§8Account Upgrade") return
- duration = clickedItemLore.firstNotNullOf {
+ val result = clickedItemLore.firstNotNullOfOrNull {
durationRegex.matchEntire(it)
- }.groups[1]!!.value.toInt().days
+ } ?: return
+ duration = result.groups[1]!!.value.toInt().days
}
@SubscribeEvent
diff --git a/src/main/java/at/hannibal2/skyhanni/features/fame/CityProjectFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/fame/CityProjectFeatures.kt
index 8e2c2e13a..706de6807 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/fame/CityProjectFeatures.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/fame/CityProjectFeatures.kt
@@ -4,7 +4,6 @@ import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.data.ProfileStorageData
import at.hannibal2.skyhanni.events.*
import at.hannibal2.skyhanni.features.bazaar.BazaarApi
-import at.hannibal2.skyhanni.features.garden.contest.FarmingContestAPI
import at.hannibal2.skyhanni.utils.*
import at.hannibal2.skyhanni.utils.ItemUtils.getLore
import at.hannibal2.skyhanni.utils.ItemUtils.name
@@ -150,12 +149,10 @@ class CityProjectFeatures {
if (line == "") break
if (line.contains("Bits")) break
- val (name, amount) = ItemUtils.readItemAmount(line)
- if (name != null) {
- val internalName = NEUItems.getRawInternalName(name)
- val old = materials.getOrPut(internalName) { 0 }
- materials[internalName] = old + amount
- }
+ val (name, amount) = ItemUtils.readItemAmount(line) ?: continue
+ val internalName = NEUItems.getRawInternalName(name)
+ val old = materials.getOrPut(internalName) { 0 }
+ materials[internalName] = old + amount
}
}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/fishing/FishingTimer.kt b/src/main/java/at/hannibal2/skyhanni/features/fishing/FishingTimer.kt
index 2935b77ab..f5f87ee2c 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/fishing/FishingTimer.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/fishing/FishingTimer.kt
@@ -9,7 +9,6 @@ import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland
import at.hannibal2.skyhanni.utils.RenderUtils.renderString
import net.minecraft.entity.item.EntityArmorStand
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
-import org.lwjgl.input.Keyboard
class FishingTimer {
private val config get() = SkyHanniMod.feature.fishing
@@ -33,7 +32,7 @@ class FishingTimer {
if (event.isMod(5)) checkMobs()
if (event.isMod(7)) tryPlaySound()
- if (Keyboard.isKeyDown(config.manualResetTimer)) startTime = System.currentTimeMillis()
+ if (OSUtils.isKeyHeld(config.manualResetTimer)) startTime = System.currentTimeMillis()
}
private fun tryPlaySound() {
@@ -64,7 +63,12 @@ class FishingTimer {
}
private fun countMobs() = EntityUtils.getEntities<EntityArmorStand>()
- .count { entity -> SeaCreatureManager.allFishingMobNames.any { entity.name.contains(it) } }
+ .map { entity ->
+ val name = entity.name
+ if (SeaCreatureManager.allFishingMobNames.any { name.contains(it) }) {
+ if (name == "Sea Emperor" || name == "Rider of the Deep") 2 else 1
+ } else 0
+ }.sum()
private fun isRightLocation(): Boolean {
if (config.barnTimerCrystalHollows && IslandType.CRYSTAL_HOLLOWS.isInIsland()) {
diff --git a/src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/TrophyFishFillet.kt b/src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/TrophyFishFillet.kt
index 18dfc5d7d..edb9d9fd1 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/TrophyFishFillet.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/TrophyFishFillet.kt
@@ -7,6 +7,7 @@ import at.hannibal2.skyhanni.utils.LorenzUtils
import at.hannibal2.skyhanni.utils.NEUItems
import at.hannibal2.skyhanni.utils.NumberUtil
import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators
+import at.hannibal2.skyhanni.utils.OSUtils
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import org.lwjgl.input.Keyboard
@@ -22,7 +23,7 @@ class TrophyFishFillet {
val trophyRarityName = internalName.substringAfterLast("_")
val info = TrophyFishManager.getInfo(trophyFishName) ?: return
val rarity = TrophyRarity.getByName(trophyRarityName) ?: return
- val multiplier = if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) event.itemStack.stackSize else 1
+ val multiplier = if (OSUtils.isKeyHeld(Keyboard.KEY_LSHIFT)) event.itemStack.stackSize else 1
val filletValue = info.getFilletValue(rarity) * multiplier
val filletPrice = filletValue * NEUItems.getPrice("MAGMA_FISH")
event.toolTip.add("§7Fillet: §8${filletValue.addSeparators()} Magmafish §7(§6${NumberUtil.format(filletPrice)}§7)")
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/AnitaMedalProfit.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/AnitaMedalProfit.kt
index 0fb0be6ff..dcc645f5e 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/AnitaMedalProfit.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/AnitaMedalProfit.kt
@@ -72,8 +72,7 @@ class AnitaMedalProfit {
val fullCost = getFullCost(getRequiredItems(item))
if (fullCost < 0) return
- val (name, amount) = ItemUtils.readItemAmount(itemName)
- if (name == null) return
+ val (name, amount) = ItemUtils.readItemAmount(itemName) ?: return
var internalName = NEUItems.getInternalNameOrNull(name)
if (internalName == null) {
@@ -93,12 +92,13 @@ class AnitaMedalProfit {
val jacobTicketPrice = "JACOBS_TICKET".asInternalName().getPrice()
var otherItemsPrice = 0.0
for (rawItemName in requiredItems) {
- val (name, amount) = ItemUtils.readItemAmount(rawItemName)
- if (name == null) {
+ val pair = ItemUtils.readItemAmount(rawItemName)
+ if (pair == null) {
LorenzUtils.error("§c[SkyHanni] Could not read item '$rawItemName'")
continue
}
+ val (name, amount) = pair
val medal = getMedal(name)
otherItemsPrice += if (medal != null) {
val bronze = medal.factorBronze * amount
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/FarmingFortuneDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/FarmingFortuneDisplay.kt
index 4b64ce4fc..d2c1b2c4d 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/FarmingFortuneDisplay.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/FarmingFortuneDisplay.kt
@@ -3,7 +3,7 @@ package at.hannibal2.skyhanni.features.garden
import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.data.CropAccessoryData
import at.hannibal2.skyhanni.data.GardenCropMilestones
-import at.hannibal2.skyhanni.data.GardenCropMilestones.Companion.getCounter
+import at.hannibal2.skyhanni.data.GardenCropMilestones.getCounter
import at.hannibal2.skyhanni.data.GardenCropUpgrades.Companion.getUpgradeLevel
import at.hannibal2.skyhanni.events.*
import at.hannibal2.skyhanni.features.garden.CropType.Companion.getTurboCrop
@@ -194,17 +194,18 @@ class FarmingFortuneDisplay {
}
fun getDedicationFortune(tool: ItemStack?, cropType: CropType?): Double {
+ if (cropType == null) return 0.0
val dedicationLevel = tool?.getEnchantments()?.get("dedication") ?: 0
val dedicationMultiplier = listOf(0.0, 0.5, 0.75, 1.0, 2.0)[dedicationLevel]
- val cropMilestone = GardenCropMilestones.getTierForCrops(
- cropType?.getCounter() ?: 0
+ val cropMilestone = GardenCropMilestones.getTierForCropCount(
+ cropType.getCounter(), cropType
)
return dedicationMultiplier * cropMilestone
}
fun getSunderFortune(tool: ItemStack?): Double { return (tool?.getEnchantments()?.get("sunder") ?: 0) * 12.5 }
fun getHarvestingFortune(tool: ItemStack?): Double { return (tool?.getEnchantments()?.get("harvesting") ?: 0) * 12.5 }
- fun getCultivatingFortune(tool: ItemStack?): Double { return (tool?.getEnchantments()?.get("cultivating") ?: 0).toDouble()}
+ fun getCultivatingFortune(tool: ItemStack?): Double { return (tool?.getEnchantments()?.get("cultivating") ?: 0) * 2.0}
fun getAbilityFortune(item: ItemStack?): Double {
val lotusAbilityPattern = "§7Piece Bonus: §6+(?<bonus>.*)☘".toPattern()
@@ -253,7 +254,14 @@ class FarmingFortuneDisplay {
val accessoryFortune = accessoryFortune ?: 0.0
val baseFortune = if (alwaysBaseFortune) 100.0 else baseFortune
- return baseFortune + upgradeFortune + tabFortune + toolFortune + accessoryFortune
+ var carrotFortune = 0.0
+
+ if (currentCrop == CropType.CARROT) {
+ GardenAPI.config?.fortune?.let {
+ if (it.carrotFortune) carrotFortune = 12.0
+ }
+ }
+ return baseFortune + upgradeFortune + tabFortune + toolFortune + accessoryFortune + carrotFortune
}
fun CropType.getLatestTrueFarmingFortune() = latestFF?.get(this)
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenAPI.kt
index 083770c6f..05e407781 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenAPI.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenAPI.kt
@@ -19,6 +19,7 @@ import at.hannibal2.skyhanni.utils.LorenzVec
import at.hannibal2.skyhanni.utils.MinecraftDispatcher
import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getCultivatingCounter
import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getHoeCounter
+import at.hannibal2.skyhanni.utils.jsonobjects.GardenJson
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@@ -191,6 +192,14 @@ object GardenAPI {
return totalExp
}
}
+
+ while (tier < requestedLevel) {
+ totalExp += gardenOverflowExp
+ tier++
+ if (tier == requestedLevel) {
+ return totalExp
+ }
+ }
return 0
}
@@ -204,51 +213,21 @@ object GardenAPI {
}
tier++
}
+ totalExp += gardenOverflowExp
+
+ while (totalExp < gardenExp) {
+ tier++
+ totalExp += gardenOverflowExp
+ }
return tier
}
- private val gardenExperience = listOf(
- 0,
- 70,
- 100,
- 140,
- 240,
- 600,
- 1500,
- 2000,
- 2500,
- 3000,
- 10_000,
- 10_000,
- 10_000,
- 10_000,
- 10_000, // level 15
-
- // overflow levels till 40 for now, in 10k steps
- 10_000,
- 10_000,
- 10_000,
- 10_000,
- 10_000,
- 10_000,
- 10_000,
- 10_000,
- 10_000,
- 10_000,
- 10_000,
- 10_000,
- 10_000,
- 10_000,
- 10_000,
- 10_000,
- 10_000,
- 10_000,
- 10_000,
- 10_000,
- 10_000,
- 10_000,
- 10_000,
- 10_000,
- 10_000,
- )
+ @SubscribeEvent
+ fun onRepoReload(event: RepositoryReloadEvent) {
+ val data = event.getConstant<GardenJson>("Garden") ?: return
+ gardenExperience = data.garden_exp
+ }
+
+ private var gardenExperience = listOf<Int>()
+ private const val gardenOverflowExp = 10000 // can be changed I guess
} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenCropMilestoneFix.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenCropMilestoneFix.kt
index b643e5771..39ca5e7af 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenCropMilestoneFix.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenCropMilestoneFix.kt
@@ -1,8 +1,8 @@
package at.hannibal2.skyhanni.features.garden
import at.hannibal2.skyhanni.data.GardenCropMilestones
-import at.hannibal2.skyhanni.data.GardenCropMilestones.Companion.getCounter
-import at.hannibal2.skyhanni.data.GardenCropMilestones.Companion.setCounter
+import at.hannibal2.skyhanni.data.GardenCropMilestones.getCounter
+import at.hannibal2.skyhanni.data.GardenCropMilestones.setCounter
import at.hannibal2.skyhanni.data.ProfileStorageData
import at.hannibal2.skyhanni.events.LorenzChatEvent
import at.hannibal2.skyhanni.events.TabListUpdateEvent
@@ -28,7 +28,7 @@ class GardenCropMilestoneFix {
val tier = group("tier").romanToDecimalIfNeeded()
- val crops = GardenCropMilestones.getCropsForTier(tier)
+ val crops = GardenCropMilestones.getCropsForTier(tier, crop)
changedValue(crop, crops, "level up chat message", 0)
}
}
@@ -49,12 +49,6 @@ class GardenCropMilestoneFix {
private fun check(cropName: String, tier: Int, percentage: Double) {
if (!ProfileStorageData.loaded) return
- val baseCrops = GardenCropMilestones.getCropsForTier(tier)
- val next = GardenCropMilestones.getCropsForTier(tier + 1)
- val progressCrops = next - baseCrops
-
- val progress = progressCrops * (percentage / 100)
- val smallestPercentage = progressCrops * 0.0005
val crop = CropType.getByNameOrNull(cropName)
if (crop == null) {
@@ -62,6 +56,13 @@ class GardenCropMilestoneFix {
return
}
+ val baseCrops = GardenCropMilestones.getCropsForTier(tier, crop)
+ val next = GardenCropMilestones.getCropsForTier(tier + 1, crop)
+ val progressCrops = next - baseCrops
+
+ val progress = progressCrops * (percentage / 100)
+ val smallestPercentage = progressCrops * 0.0005
+
val tabListValue = baseCrops + progress - smallestPercentage
val newValue = tabListValue.toLong()
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenLevelDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenLevelDisplay.kt
index 5f2b50e82..38e1c319e 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenLevelDisplay.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenLevelDisplay.kt
@@ -14,6 +14,7 @@ import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher
import at.hannibal2.skyhanni.utils.StringUtils.removeColor
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import kotlin.math.roundToInt
+import kotlin.time.Duration.Companion.milliseconds
class GardenLevelDisplay {
private val config get() = SkyHanniMod.feature.garden
@@ -48,10 +49,12 @@ class GardenLevelDisplay {
val newLevel = GardenAPI.getLevelForExp(gardenExp.toLong())
if (newLevel == oldLevel + 1) {
if (newLevel > 15) {
- LorenzUtils.chat(
- " \n§b§lGARDEN LEVEL UP §8$oldLevel ➜ §b$newLevel\n" +
- " §8+§aRespect from Elite Farmers and SkyHanni members :)\n "
- )
+ LorenzUtils.runDelayed(50.milliseconds) {
+ LorenzUtils.chat(
+ " \n§b§lGARDEN LEVEL UP §8$oldLevel ➜ §b$newLevel\n" +
+ " §8+§aRespect from Elite Farmers and SkyHanni members :)\n "
+ )
+ }
}
}
update()
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenNextJacobContest.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenNextJacobContest.kt
index 1525a2209..1c02e4cc8 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenNextJacobContest.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenNextJacobContest.kt
@@ -4,6 +4,7 @@ import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.data.TitleUtils
import at.hannibal2.skyhanni.events.*
import at.hannibal2.skyhanni.features.garden.GardenAPI.addCropIcon
+import at.hannibal2.skyhanni.utils.APIUtil
import at.hannibal2.skyhanni.utils.ItemUtils.getLore
import at.hannibal2.skyhanni.utils.ItemUtils.name
import at.hannibal2.skyhanni.utils.LorenzUtils
@@ -13,8 +14,11 @@ import at.hannibal2.skyhanni.utils.SoundUtils
import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher
import at.hannibal2.skyhanni.utils.StringUtils.removeColor
import at.hannibal2.skyhanni.utils.TimeUtils
+import com.google.gson.Gson
import io.github.moulberry.notenoughupdates.util.SkyBlockTime
+import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
import net.minecraft.item.ItemStack
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import org.lwjgl.opengl.Display
@@ -25,8 +29,9 @@ import javax.swing.JButton
import javax.swing.JFrame
import javax.swing.JOptionPane
import javax.swing.UIManager
+import kotlin.time.Duration.Companion.seconds
-class GardenNextJacobContest {
+object GardenNextJacobContest {
private var display = emptyList<Any>()
private var simpleDisplay = emptyList<String>()
private var contests = mutableMapOf<Long, FarmingContest>()
@@ -35,9 +40,16 @@ class GardenNextJacobContest {
private val patternMonth = "(?<month>.*), Year (?<year>.*)".toPattern()
private val patternCrop = "§e○ §7(?<crop>.*)".toPattern()
- private val maxContestsPerYear = 124
- private val contestDuration = 1_000 * 60 * 20
+ private const val maxContestsPerYear = 124
+ private const val contestDuration = 1_000 * 60 * 20
private var lastWarningTime = 0L
+ private var loadedContestsYear = -1
+ private var nextContestsAvailableAt = -1L
+
+ private var lastFetchAttempted = 0L
+ private var isFetchingContests = false
+ private var fetchedFromElite = false
+ private var isSendingContests = false
@SubscribeEvent
fun onTabListUpdate(event: TabListUpdateEvent) {
@@ -102,38 +114,63 @@ class GardenNextJacobContest {
}
private fun readCalendar(items: Collection<ItemStack>, year: Int, month: Int) {
- if (contests.isNotEmpty()) {
- val contest = contests.values.first()
- val endTime = contest.endTime
+ if (contests.isNotEmpty() && loadedContestsYear != year) {
+ val endTime = contests.values.first().endTime
val lastYear = SkyBlockTime.fromInstant(Instant.ofEpochMilli(endTime)).year
if (year != lastYear) {
contests.clear()
- LorenzUtils.chat("§e[SkyHanni] New year detected, open all calendar months again!")
+ }
+ // Contests are available now, make sure system knows this
+ if (nextContestsAvailableAt > System.currentTimeMillis()) {
+ nextContestsAvailableAt = System.currentTimeMillis() - 1
+ fetchContestsIfAble()
+ }
+ if (nextContestsAvailableAt == -1L) {
+ nextContestsAvailableAt = System.currentTimeMillis() - 1
+ fetchContestsIfAble()
}
}
- if (contests.size < maxContestsPerYear) {
- for (item in items) {
- val lore = item.getLore()
- if (!lore.any { it.contains("§6§eJacob's Farming Contest") }) continue
-
- val name = item.name ?: continue
- val matcherDay = patternDay.matcher(name)
- if (!matcherDay.matches()) continue
-
- val day = matcherDay.group("day").toInt()
- val startTime = SkyBlockTime(year, month, day).toMillis()
- val crops = mutableListOf<CropType>()
- for (line in lore) {
- val matcherCrop = patternCrop.matcher(line)
- if (!matcherCrop.matches()) continue
- crops.add(CropType.getByName(matcherCrop.group("crop")))
- }
- val contest = FarmingContest(startTime + contestDuration, crops)
- contests[startTime] = contest
+ // Skip if contests are already loaded for this year
+ if (contests.size == maxContestsPerYear) return
+
+ // Manually loading contests
+ for (item in items) {
+ val lore = item.getLore()
+ if (!lore.any { it.contains("§6§eJacob's Farming Contest") }) continue
+
+ val name = item.name ?: continue
+ val matcherDay = patternDay.matcher(name)
+ if (!matcherDay.matches()) continue
+
+ val day = matcherDay.group("day").toInt()
+ val startTime = SkyBlockTime(year, month, day).toMillis()
+
+ val crops = mutableListOf<CropType>()
+ for (line in lore) {
+ val matcherCrop = patternCrop.matcher(line)
+ if (!matcherCrop.matches()) continue
+ crops.add(CropType.getByName(matcherCrop.group("crop")))
}
+
+ contests[startTime] = FarmingContest(startTime + contestDuration, crops)
}
+ // If contests were just fully saved
+ if (contests.size == maxContestsPerYear) {
+ nextContestsAvailableAt = SkyBlockTime(SkyBlockTime.now().year + 1, 1, 2).toMillis()
+
+ if (isSendEnabled()) {
+ if (!askToSendContests()) {
+ sendContests()
+ } else {
+ LorenzUtils.clickableChat(
+ "§e[SkyHanni] §2Click here to submit this years farming contests, thank you for helping everyone out!",
+ "shsendcontests"
+ )
+ }
+ }
+ }
update()
saveConfig()
}
@@ -141,15 +178,53 @@ class GardenNextJacobContest {
private fun saveConfig() {
val map = SkyHanniMod.feature.storage.gardenJacobFarmingContestTimes
map.clear()
+
+ val currentYear = SkyBlockTime.now().year
for (contest in contests.values) {
+ val contestYear = (SkyBlockTime.fromInstant(Instant.ofEpochMilli(contest.endTime))).year
+ // Ensure all stored contests are really from the current year
+ if (contestYear != currentYear) continue
+
map[contest.endTime] = contest.crops
}
}
@SubscribeEvent
fun onConfigLoad(event: ConfigLoadEvent) {
- for ((time, crops) in SkyHanniMod.feature.storage.gardenJacobFarmingContestTimes) {
- contests[time] = FarmingContest(time, crops)
+ val savedContests = SkyHanniMod.feature.storage.gardenJacobFarmingContestTimes
+ val year = savedContests.firstNotNullOfOrNull {
+ val endTime = it.key
+
+ SkyBlockTime.fromInstant(Instant.ofEpochMilli(endTime)).year
+ }
+
+ // Clear contests if from previous year
+ if (year != SkyBlockTime.now().year) {
+ savedContests.clear()
+ } else {
+ for ((time, crops) in savedContests) {
+ contests[time] = FarmingContest(time, crops)
+ }
+ }
+ }
+
+ fun shareContestConfirmed(array: Array<String>) {
+ if (array.size == 1) {
+ if (array[0] == "enable") {
+ config.nextJacobContestsShareAutomatically = 1
+ SkyHanniMod.feature.storage.contestSendingAsked = true
+ LorenzUtils.chat("§e[SkyHanni] §2Enabled automatic sharing of future contests!")
+ }
+ return
+ }
+ if (contests.size == maxContestsPerYear) {
+ sendContests()
+ }
+ if (!SkyHanniMod.feature.storage.contestSendingAsked && config.nextJacobContestsShareAutomatically == 0) {
+ LorenzUtils.clickableChat(
+ "§e[SkyHanni] §2Click here to automatically share future contests!",
+ "shsendcontests enable"
+ )
}
}
@@ -157,7 +232,20 @@ class GardenNextJacobContest {
private fun update() {
nextContestCrops.clear()
- display = drawDisplay()
+
+ if (nextContestsAvailableAt == -1L) {
+ val currentDate = SkyBlockTime.now()
+ if (currentDate.month <= 1 && currentDate.day <= 1) {
+ nextContestsAvailableAt = SkyBlockTime(SkyBlockTime.now().year + 1, 1, 1).toMillis()
+ }
+ }
+
+ display = if (isFetchingContests) {
+ listOf("§cFetching this years jacob contests...")
+ } else {
+ fetchContestsIfAble() // Will only run when needed/enabled
+ drawDisplay()
+ }
}
private fun drawDisplay(): List<Any> {
@@ -173,22 +261,26 @@ class GardenNextJacobContest {
}
if (contests.isEmpty()) {
- return emptyList()
+ list.add("§cOpen calendar to read jacob contest times!")
+ return list
}
val nextContest =
contests.filter { it.value.endTime > System.currentTimeMillis() }.toSortedMap()
.firstNotNullOfOrNull { it.value }
- if (nextContest == null) {
- if (contests.size == maxContestsPerYear) {
- list.add("§cNew SkyBlock Year! Open calendar again!")
- } else {
- list.add("§cOpen calendar to read jacob contest times!")
- }
- return list
+ // Show next contest
+ if (nextContest != null) return drawNextContest(nextContest, list)
+
+ if (contests.size == maxContestsPerYear) {
+ list.add("§cNew SkyBlock Year! Open calendar again!")
+ } else {
+ list.add("§cOpen calendar to read jacob contest times!")
}
- return drawNextContest(nextContest, list)
+ fetchedFromElite = false
+ contests.clear()
+
+ return list
}
private fun drawNextContest(
@@ -223,7 +315,7 @@ class GardenNextJacobContest {
val cropText = crops.joinToString("§7, ") { "§a${it.cropName}" }
LorenzUtils.chat("§e[SkyHanni] Next farming contest: $cropText")
- TitleUtils.sendTitle("§eFarming Contest!", 5_000)
+ TitleUtils.sendTitle("§eFarming Contest!", 5.seconds)
SoundUtils.playBeepSound()
if (config.nextJacobContestWarnPopup && !Display.isActive()) {
@@ -301,10 +393,105 @@ class GardenNextJacobContest {
private fun isEnabled() = LorenzUtils.inSkyBlock && config.nextJacobContestDisplay
&& (GardenAPI.inGarden() || config.nextJacobContestEverywhere)
- companion object {
- private val config get() = SkyHanniMod.feature.garden
- private val nextContestCrops = mutableListOf<CropType>()
+ private fun isFetchEnabled() = isEnabled() && config.nextJacobContestsFetchAutomatically
+ private fun isSendEnabled() = isFetchEnabled() && config.nextJacobContestsShareAutomatically != 2 // 2 = Disabled
+ private fun askToSendContests() =
+ config.nextJacobContestsShareAutomatically == 0 // 0 = Ask, 1 = Send (Only call if isSendEnabled())
+
+ private fun fetchContestsIfAble() {
+ if (isFetchingContests || contests.size == maxContestsPerYear || !isFetchEnabled()) return
+ // Allows retries every 10 minutes when it's after 1 day into the new year
+ val currentMills = System.currentTimeMillis()
+ if (lastFetchAttempted + 600_000 > currentMills || currentMills < nextContestsAvailableAt) return
+
+ isFetchingContests = true
+
+ SkyHanniMod.coroutineScope.launch {
+ fetchUpcomingContests()
+ lastFetchAttempted = System.currentTimeMillis()
+ isFetchingContests = false
+ }
+ }
+
+ private suspend fun fetchUpcomingContests() {
+ try {
+ val url = "https://api.elitebot.dev/contests/at/now"
+ val result = withContext(Dispatchers.IO) { APIUtil.getJSONResponse(url) }.asJsonObject
+
+ val newContests = mutableMapOf<Long, FarmingContest>()
+
+ val complete = result["complete"].asBoolean
+ if (complete) {
+ for (entry in result["contests"].asJsonObject.entrySet()) {
+ var timestamp = entry.key.toLongOrNull() ?: continue
+ timestamp *= 1_000 // Seconds to milliseconds
+
+ val crops = entry.value.asJsonArray.map {
+ CropType.getByName(it.asString)
+ }
+
+ if (crops.size != 3) continue
+
+ newContests[timestamp + contestDuration] = FarmingContest(timestamp + contestDuration, crops)
+ }
+ } else {
+ LorenzUtils.chat("§e[SkyHanni] This years contests aren't available to fetch automatically yet, please load them from your calender or wait 10 minutes!")
+ }
+
+ if (newContests.count() == maxContestsPerYear) {
+ LorenzUtils.chat("§e[SkyHanni] Successfully loaded this year's contests from elitebot.dev automatically!")
+
+ contests = newContests
+ fetchedFromElite = true
+ nextContestsAvailableAt = SkyBlockTime(SkyBlockTime.now().year + 1, 1, 2).toMillis()
+ loadedContestsYear = SkyBlockTime.now().year
+
+ saveConfig()
+ }
+ } catch (e: Exception) {
+ e.printStackTrace()
+ LorenzUtils.error("[SkyHanni] Failed to fetch upcoming contests. Please report this error if it continues to occur.")
+ }
+ }
+
+ private fun sendContests() {
+ if (isSendingContests || contests.size != maxContestsPerYear) return
- fun isNextCrop(cropName: CropType) = nextContestCrops.contains(cropName) && config.nextJacobContestOtherGuis
+ isSendingContests = true
+
+ SkyHanniMod.coroutineScope.launch {
+ submitContestsToElite()
+ isSendingContests = false
+ }
}
+
+ private suspend fun submitContestsToElite() = try {
+ val formatted = mutableMapOf<Long, List<String>>()
+
+ for ((endTime, contest) in contests) {
+ formatted[endTime / 1000] = contest.crops.map {
+ it.cropName
+ }
+ }
+
+ val url = "https://api.elitebot.dev/contests/at/now"
+ val body = Gson().toJson(formatted)
+
+ val result = withContext(Dispatchers.IO) { APIUtil.postJSONIsSuccessful(url, body) }
+
+ if (result) {
+ LorenzUtils.chat("§e[SkyHanni] Successfully submitted this years upcoming contests, thank you for helping everyone out!")
+ } else {
+ LorenzUtils.error("[SkyHanni] Something went wrong submitting upcoming contests!")
+ }
+ } catch (e: Exception) {
+ e.printStackTrace()
+ LorenzUtils.error("[SkyHanni] Failed to submit upcoming contests. Please report this error if it continues to occur.")
+ null
+ }
+
+ private val config get() = SkyHanniMod.feature.garden
+ private val nextContestCrops = mutableListOf<CropType>()
+
+ fun isNextCrop(cropName: CropType) = nextContestCrops.contains(cropName) && config.nextJacobContestOtherGuis
} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenOptimalSpeed.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenOptimalSpeed.kt
index 6f5e9abe0..71ac8b321 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenOptimalSpeed.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenOptimalSpeed.kt
@@ -16,6 +16,7 @@ import net.minecraft.client.gui.inventory.GuiEditSign
import net.minecraftforge.client.event.GuiOpenEvent
import net.minecraftforge.client.event.GuiScreenEvent.DrawScreenEvent
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import kotlin.time.Duration.Companion.seconds
class GardenOptimalSpeed {
private val config get() = SkyHanniMod.feature.garden
@@ -100,7 +101,7 @@ class GardenOptimalSpeed {
if (System.currentTimeMillis() < lastWarnTime + 20_000) return
lastWarnTime = System.currentTimeMillis()
- TitleUtils.sendTitle("§cWrong speed!", 3_000)
+ TitleUtils.sendTitle("§cWrong speed!", 3.seconds)
cropInHand?.let {
LorenzUtils.chat("§e[SkyHanni] Wrong speed for ${it.cropName}: §f$currentSpeed §e(§f$optimalSpeed §eis optimal)")
}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenPlotBorders.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenPlotBorders.kt
new file mode 100644
index 000000000..00d3461e3
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenPlotBorders.kt
@@ -0,0 +1,120 @@
+package at.hannibal2.skyhanni.features.garden
+
+import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.events.LorenzTickEvent
+import at.hannibal2.skyhanni.utils.LorenzColor
+import at.hannibal2.skyhanni.utils.LorenzVec
+import at.hannibal2.skyhanni.utils.RenderUtils.draw3DLine
+import net.minecraft.client.Minecraft
+import net.minecraftforge.client.event.RenderWorldLastEvent
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import org.lwjgl.input.Keyboard
+import java.awt.Color
+import kotlin.math.floor
+
+class GardenPlotBorders {
+
+ private val config get() = SkyHanniMod.feature.garden.plotBorders
+ private var showBorders = false
+ private val LINE_COLOR = LorenzColor.YELLOW.toColor()
+
+ private fun LorenzVec.addX(x: Int) = add(x, 0, 0)
+ private fun LorenzVec.addZ(z: Int) = add(0, 0, z)
+ private fun LorenzVec.addXZ(x: Int, z: Int) = add(x, 0, z)
+
+ @SubscribeEvent
+ fun onTick(event: LorenzTickEvent) {
+ if (!isEnabled()) return
+
+ val keyPressed = if (Keyboard.getEventKey() == 0) Keyboard.getEventCharacter() else Keyboard.getEventKey()
+
+ if (keyPressed == Keyboard.KEY_G && Keyboard.isKeyDown(Keyboard.KEY_F3)) {
+ showBorders = !showBorders
+ }
+ }
+
+ @SubscribeEvent
+ fun render(event: RenderWorldLastEvent) {
+ if (!isEnabled()) return
+ if (!showBorders) return
+
+ val entity = Minecraft.getMinecraft().renderViewEntity
+
+ // Lowest point in garden
+ val minHeight = 66
+ val maxHeight = 256
+
+ // These don't refer to Minecraft chunks but rather garden plots, but I use
+ // the word chunk as the logic closely represents how chunk borders are rendered in latter mc versions
+ val chunkX = floor((entity.posX + 48) / 96).toInt()
+ val chunkZ = floor((entity.posZ + 48) / 96).toInt()
+ val chunkMinX = (chunkX * 96) - 48
+ val chunkMinZ = (chunkZ * 96) - 48
+
+ // Render 4 vertical corners
+ for (i in 0..96 step 96) {
+ for (j in 0..96 step 96) {
+ val start = LorenzVec(chunkMinX + i, minHeight, chunkMinZ + j)
+ val end = LorenzVec(chunkMinX + i, maxHeight, chunkMinZ + j)
+ event.tryDraw3DLine(start, end, LorenzColor.DARK_BLUE.toColor(), 2, true)
+ }
+ }
+
+ // Render vertical on X-Axis
+ for (x in 4..<96 step 4) {
+ val start = LorenzVec(chunkMinX + x, minHeight, chunkMinZ)
+ val end = LorenzVec(chunkMinX + x, maxHeight, chunkMinZ)
+ // Front lines
+ event.tryDraw3DLine(start, end, LINE_COLOR, 1, true)
+ // Back lines
+ event.tryDraw3DLine(start.addZ(96), end.addZ(96), LINE_COLOR, 1, true)
+ }
+
+ // Render vertical on Z-Axis
+ for (z in 4..<96 step 4) {
+ val start = LorenzVec(chunkMinX, minHeight, chunkMinZ + z)
+ val end = LorenzVec(chunkMinX, maxHeight, chunkMinZ + z)
+ // Left lines
+ event.tryDraw3DLine(start, end, LINE_COLOR, 1, true)
+ // Right lines
+ event.tryDraw3DLine(start.addX(96), end.addX(96), LINE_COLOR, 1, true)
+ }
+
+ // Render horizontal
+ for (y in minHeight..maxHeight step 4) {
+ val start = LorenzVec(chunkMinX, y, chunkMinZ)
+ // (minX, minZ) -> (minX, minZ + 96)
+ event.tryDraw3DLine(start, start.addZ(96), LINE_COLOR, 1, true)
+ // (minX, minZ + 96) -> (minX + 96, minZ + 96)
+ event.tryDraw3DLine(start.addZ(96), start.addXZ(96, 96), LINE_COLOR, 1, true)
+ // (minX + 96, minZ + 96) -> (minX + 96, minZ)
+ event.tryDraw3DLine(start.addXZ(96, 96), start.addX(96), LINE_COLOR, 1, true)
+ // (minX + 96, minZ) -> (minX, minZ)
+ event.tryDraw3DLine(start.addX(96), start, LINE_COLOR, 1, true)
+ }
+ }
+
+ private fun RenderWorldLastEvent.tryDraw3DLine(
+ p1: LorenzVec,
+ p2: LorenzVec,
+ color: Color,
+ lineWidth: Int,
+ depth: Boolean
+ ) {
+ if (isOutOfBorders(p1)) return
+ if (isOutOfBorders(p2)) return
+ draw3DLine(p1, p2, color, lineWidth, depth)
+ }
+
+
+ private fun isOutOfBorders(location: LorenzVec) = when {
+ location.x > 240 -> true
+ location.x < -240 -> true
+ location.z > 240 -> true
+ location.z < -240 -> true
+
+ else -> false
+ }
+
+ fun isEnabled() = GardenAPI.inGarden() && config
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenYawAndPitch.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenYawAndPitch.kt
index f569a0f21..342812c39 100755
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenYawAndPitch.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenYawAndPitch.kt
@@ -6,12 +6,14 @@ import at.hannibal2.skyhanni.events.GuiRenderEvent
import at.hannibal2.skyhanni.utils.LorenzUtils
import at.hannibal2.skyhanni.utils.LorenzUtils.round
import at.hannibal2.skyhanni.utils.RenderUtils.renderStrings
+import at.hannibal2.skyhanni.utils.SimpleTimeMark
import net.minecraft.client.Minecraft
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import kotlin.time.Duration.Companion.seconds
class GardenYawAndPitch {
private val config get() = SkyHanniMod.feature.garden.yawPitchDisplay
- private var lastChange = 0L
+ private var lastChange = SimpleTimeMark.farPast()
private var lastYaw = 0f
private var lastPitch = 0f
@@ -30,16 +32,16 @@ class GardenYawAndPitch {
val pitch = player.rotationPitch
if (yaw != lastYaw || pitch != lastPitch) {
- lastChange = System.currentTimeMillis()
+ lastChange = SimpleTimeMark.now()
}
lastYaw = yaw
lastPitch = pitch
- if (!config.showAlways && System.currentTimeMillis() > lastChange + (config.timeout * 1000)) return
+ if (!config.showAlways && lastChange.passedSince() > config.timeout.seconds) return
val displayList = listOf(
- "§aYaw: §f${yaw.toDouble().round(config.yawPrecision)}",
- "§aPitch: §f${pitch.toDouble().round(config.pitchPrecision)}",
+ "§aYaw: §f${yaw.round(config.yawPrecision)}",
+ "§aPitch: §f${pitch.round(config.pitchPrecision)}",
)
if (GardenAPI.inGarden()) {
config.pos.renderStrings(displayList, posLabel = "Yaw and Pitch")
@@ -50,6 +52,6 @@ class GardenYawAndPitch {
@SubscribeEvent
fun onGardenToolChange(event: GardenToolChangeEvent) {
- lastChange = System.currentTimeMillis()
+ lastChange = SimpleTimeMark.farPast()
}
} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/ToolTooltipTweaks.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/ToolTooltipTweaks.kt
index 86b7f5251..e0931cd4c 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/ToolTooltipTweaks.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/ToolTooltipTweaks.kt
@@ -7,12 +7,12 @@ import at.hannibal2.skyhanni.features.garden.GardenAPI.getCropType
import at.hannibal2.skyhanni.features.garden.fortuneguide.FFGuideGUI
import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName
import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.OSUtils
import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getFarmingForDummiesCount
import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getReforgeName
import at.hannibal2.skyhanni.utils.StringUtils.firstLetterUppercase
import at.hannibal2.skyhanni.utils.StringUtils.removeColor
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
-import org.lwjgl.input.Keyboard
import java.text.DecimalFormat
import kotlin.math.roundToInt
@@ -82,7 +82,7 @@ class ToolTooltipTweaks {
}
iterator.set(fortuneLine)
- if (Keyboard.isKeyDown(config.fortuneTooltipKeybind)) {
+ if (OSUtils.isKeyHeld(config.fortuneTooltipKeybind)) {
iterator.addStat(" §7Base: §6+", baseFortune)
iterator.addStat(" §7Tool: §6+", toolFortune)
iterator.addStat(" §7${reforgeName?.removeColor()}: §9+", reforgeFortune)
@@ -104,9 +104,7 @@ class ToolTooltipTweaks {
if (removingFarmhandDescription) {
iterator.remove()
removingFarmhandDescription = line != "§5§o"
- }
-
- if (removingCounterDescription && !line.startsWith("§5§o§7You have")) {
+ } else if (removingCounterDescription && !line.startsWith("§5§o§7You have")) {
iterator.remove()
} else {
removingCounterDescription = false
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/composter/ComposterDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/composter/ComposterDisplay.kt
index 38132e8b6..2f88c52de 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/composter/ComposterDisplay.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/composter/ComposterDisplay.kt
@@ -14,6 +14,7 @@ import at.hannibal2.skyhanni.utils.TimeUtils
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import java.util.*
import kotlin.time.Duration
+import kotlin.time.Duration.Companion.seconds
import kotlin.time.DurationUnit
class ComposterDisplay {
@@ -142,7 +143,7 @@ class ComposterDisplay {
if (ComposterAPI.getOrganicMatter() <= config.composterNotifyLowOrganicMatter) {
if (System.currentTimeMillis() >= hidden.informedAboutLowMatter) {
if (config.composterNotifyLowTitle) {
- TitleUtils.sendTitle("§cYour Organic Matter is low", 4_000)
+ TitleUtils.sendTitle("§cYour Organic Matter is low", 4.seconds)
}
LorenzUtils.chat("§e[SkyHanni] §cYour Organic Matter is low!")
hidden.informedAboutLowMatter = System.currentTimeMillis() + 60_000 * 5
@@ -153,7 +154,7 @@ class ComposterDisplay {
System.currentTimeMillis() >= hidden.informedAboutLowFuel
) {
if (config.composterNotifyLowTitle) {
- TitleUtils.sendTitle("§cYour Fuel is low", 4_000)
+ TitleUtils.sendTitle("§cYour Fuel is low", 4.seconds)
}
LorenzUtils.chat("§e[SkyHanni] §cYour Fuel is low!")
hidden.informedAboutLowFuel = System.currentTimeMillis() + 60_000 * 5
@@ -203,6 +204,6 @@ class ComposterDisplay {
if (System.currentTimeMillis() < storage.lastComposterEmptyWarningTime + 1000 * 60 * 2) return
storage.lastComposterEmptyWarningTime = System.currentTimeMillis()
LorenzUtils.chat("§e[SkyHanni] $warningMessage")
- TitleUtils.sendTitle("§eComposter Warning!", 3_000)
+ TitleUtils.sendTitle("§eComposter Warning!", 3.seconds)
}
} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/composter/GardenComposterInventoryFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/composter/GardenComposterInventoryFeatures.kt
index cde25d493..0ed673431 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/composter/GardenComposterInventoryFeatures.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/composter/GardenComposterInventoryFeatures.kt
@@ -40,11 +40,12 @@ class GardenComposterInventoryFeatures {
if (next) {
if (line.endsWith(" Copper")) continue
if (line == "") break
- val (itemName, amount) = ItemUtils.readItemAmount(line)
- if (itemName == null) {
+ val pair = ItemUtils.readItemAmount(line)
+ if (pair == null) {
LorenzUtils.error("§c[SkyHanni] Could not read item '$line'")
continue
}
+ val (itemName, amount) = pair
val internalName = NEUItems.getInternalNameOrNull(itemName)
if (internalName == null) {
LorenzUtils.chat(
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/CropMoneyDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/CropMoneyDisplay.kt
index f33ae9070..31eea71e2 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/CropMoneyDisplay.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/CropMoneyDisplay.kt
@@ -14,6 +14,7 @@ import at.hannibal2.skyhanni.features.garden.GardenAPI
import at.hannibal2.skyhanni.features.garden.GardenNextJacobContest
import at.hannibal2.skyhanni.features.garden.farming.GardenCropSpeed.getSpeed
import at.hannibal2.skyhanni.features.garden.farming.GardenCropSpeed.isSpeedDataEmpty
+import at.hannibal2.skyhanni.test.command.CopyErrorCommand
import at.hannibal2.skyhanni.utils.*
import at.hannibal2.skyhanni.utils.ItemUtils.getItemNameOrNull
import at.hannibal2.skyhanni.utils.LorenzUtils.addAsSingletonList
@@ -21,6 +22,8 @@ import at.hannibal2.skyhanni.utils.LorenzUtils.moveEntryToTop
import at.hannibal2.skyhanni.utils.LorenzUtils.sortedDesc
import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName
import at.hannibal2.skyhanni.utils.NEUItems.getItemStack
+import at.hannibal2.skyhanni.utils.NEUItems.getNpcPrice
+import at.hannibal2.skyhanni.utils.NEUItems.getNpcPriceOrNull
import at.hannibal2.skyhanni.utils.NEUItems.getPrice
import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators
import at.hannibal2.skyhanni.utils.RenderUtils.renderStringsAndItems
@@ -116,8 +119,8 @@ object CropMoneyDisplay {
val redMushroom = "ENCHANTED_RED_MUSHROOM".asInternalName()
val brownMushroom = "ENCHANTED_BROWN_MUSHROOM".asInternalName()
val (redPrice, brownPrice) = if (LorenzUtils.noTradeMode) {
- val redPrice = (redMushroom.getBazaarData()?.npcPrice ?: 160.0) / 160
- val brownPrice = (brownMushroom.getBazaarData()?.npcPrice ?: 160.0) / 160
+ val redPrice = (redMushroom.getNpcPriceOrNull() ?: 160.0) / 160
+ val brownPrice = (brownMushroom.getNpcPriceOrNull() ?: 160.0) / 160
redPrice to brownPrice
} else {
val redPrice = redMushroom.getPrice() / 160
@@ -131,21 +134,16 @@ object CropMoneyDisplay {
}
if (InventoryUtils.itemInHandId.contains("DICER") && config.moneyPerHourDicer) {
- var dicerDrops = 0.0
- var bazaarData: BazaarData? = null
- if (it == CropType.MELON) {
- dicerDrops = GardenCropSpeed.latestMelonDicer
- bazaarData = "ENCHANTED_MELON".asInternalName().getBazaarData()
- }
- if (it == CropType.PUMPKIN) {
- dicerDrops = GardenCropSpeed.latestPumpkinDicer
- bazaarData = "ENCHANTED_PUMPKIN".asInternalName().getBazaarData()
- }
- if (bazaarData != null) {
- val price =
- if (LorenzUtils.noTradeMode) bazaarData.npcPrice / 160 else (bazaarData.sellPrice + bazaarData.buyPrice) / 320
- extraDicerCoins = 60 * 60 * GardenCropSpeed.getRecentBPS() * dicerDrops * price
+ val (dicerDrops, internalName) = when (it) {
+ CropType.MELON -> GardenCropSpeed.latestMelonDicer to "ENCHANTED_MELON".asInternalName()
+ CropType.PUMPKIN -> GardenCropSpeed.latestPumpkinDicer to "ENCHANTED_PUMPKIN".asInternalName()
+
+ else -> CopyErrorCommand.skyHanniError("Unknown dicer: $it")
}
+ val bazaarData = internalName.getBazaarData()
+ val price =
+ if (LorenzUtils.noTradeMode || bazaarData == null) internalName.getNpcPrice() / 160 else (bazaarData.sellPrice + bazaarData.buyPrice) / 320
+ extraDicerCoins = 60 * 60 * GardenCropSpeed.getRecentBPS() * dicerDrops * price
}
}
@@ -312,7 +310,7 @@ object CropMoneyDisplay {
val bazaarData = internalName.getBazaarData() ?: continue
- var npcPrice = bazaarData.npcPrice * cropsPerHour
+ var npcPrice = internalName.getNpcPrice() * cropsPerHour
var sellOffer = bazaarData.buyPrice * cropsPerHour
var instantSell = bazaarData.sellPrice * cropsPerHour
if (debug) {
@@ -331,7 +329,8 @@ object CropMoneyDisplay {
if (debug) {
debugList.addAsSingletonList(" added seedsPerHour: $seedsPerHour")
}
- npcPrice += it.npcPrice * seedsPerHour
+ val factor = NEUItems.getMultiplier(internalName).second
+ npcPrice += internalName.getNpcPrice() * seedsPerHour / factor
sellOffer += it.buyPrice * seedsPerHour
instantSell += it.sellPrice * seedsPerHour
}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/CropSpeedMeter.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/CropSpeedMeter.kt
index 08882db71..afeee870b 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/CropSpeedMeter.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/CropSpeedMeter.kt
@@ -1,7 +1,7 @@
package at.hannibal2.skyhanni.features.garden.farming
import at.hannibal2.skyhanni.SkyHanniMod
-import at.hannibal2.skyhanni.data.GardenCropMilestones.Companion.getCounter
+import at.hannibal2.skyhanni.data.GardenCropMilestones.getCounter
import at.hannibal2.skyhanni.events.CropClickEvent
import at.hannibal2.skyhanni.events.CropMilestoneUpdateEvent
import at.hannibal2.skyhanni.events.GuiRenderEvent
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/FarmingWeightDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/FarmingWeightDisplay.kt
index cbf4596c4..71b69107b 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/FarmingWeightDisplay.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/FarmingWeightDisplay.kt
@@ -2,14 +2,14 @@ package at.hannibal2.skyhanni.features.garden.farming
import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.data.HypixelData
+import at.hannibal2.skyhanni.data.ProfileStorageData
import at.hannibal2.skyhanni.events.*
import at.hannibal2.skyhanni.features.garden.CropType
import at.hannibal2.skyhanni.features.garden.GardenAPI
import at.hannibal2.skyhanni.features.garden.farming.GardenCropSpeed.getSpeed
-import at.hannibal2.skyhanni.utils.APIUtil
-import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.*
+import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators
import at.hannibal2.skyhanni.utils.RenderUtils.renderStrings
-import at.hannibal2.skyhanni.utils.TimeUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@@ -21,7 +21,9 @@ class FarmingWeightDisplay {
@SubscribeEvent
fun onRenderOverlay(event: GuiRenderEvent.GameOverlayRenderEvent) {
if (isEnabled()) {
- config.eliteFarmingWeightPos.renderStrings(display, posLabel = "Farming Weight Display")
+ if (config.eliteFarmingWeightIgnoreLow || weight >= 200) {
+ config.eliteFarmingWeightPos.renderStrings(display, posLabel = "Farming Weight Display")
+ }
}
}
@@ -147,9 +149,7 @@ class FarmingWeightDisplay {
val format = LorenzUtils.formatInteger(leaderboardPosition)
" §7[§b#$format§7]"
} else {
- if (isLoadingLeaderboard) {
- " §7[§b#?§7]"
- } else ""
+ if (isLoadingLeaderboard) " §7[§b#?§7]" else ""
}
}
@@ -192,15 +192,15 @@ class FarmingWeightDisplay {
if (weight < 0) return ""
var nextPlayer = nextPlayer ?: return ""
- var nextName = if (leaderboardPosition == -1 || leaderboardPosition > rankGoal) "#$rankGoal" else nextPlayer.name
+ var nextName =
+ if (leaderboardPosition == -1 || leaderboardPosition > rankGoal) "#$rankGoal" else nextPlayer.name
val totalWeight = (localWeight + weight)
var weightUntilOvertake = nextPlayer.weight - totalWeight
if (weightUntilOvertake < 0) {
if (weightPerSecond > 0) {
- LorenzUtils.debug("weightPerSecond: '$weightPerSecond'")
- LorenzUtils.chat("§e[SkyHanni] You passed §b$nextName §ein the Farming Weight Leaderboard!")
+ farmingChatMessage("§e[SkyHanni] You passed §b$nextName §ein the Farming Weight Leaderboard!")
}
// Lower leaderboard position
@@ -209,6 +209,8 @@ class FarmingWeightDisplay {
} else {
leaderboardPosition--
}
+ ProfileStorageData.profileSpecific?.garden?.farmingWeight?.lastFarmingWeightLeaderboard =
+ leaderboardPosition
// Remove passed player to present the next one
nextPlayers.removeFirst()
@@ -234,6 +236,17 @@ class FarmingWeightDisplay {
return "§e$weightFormat$timeFormat §7behind §b$nextName"
}
+ private fun farmingChatMessage(message: String) {
+ LorenzUtils.hoverableChat(
+ message,
+ listOf(
+ "§eClick to open your Farming Weight",
+ "§eprofile on §celitebot.dev",
+ ),
+ "shfarmingprofile ${LorenzUtils.getPlayerName()}"
+ )
+ }
+
private fun isEnabled() = GardenAPI.inGarden() && config.eliteFarmingWeightDisplay
private fun isEtaEnabled() = config.eliteFarmingWeightOvertakeETA
@@ -265,12 +278,41 @@ class FarmingWeightDisplay {
isLoadingLeaderboard = true
SkyHanniMod.coroutineScope.launch {
+ val wasNotLoaded = leaderboardPosition == -1
leaderboardPosition = loadLeaderboardPosition()
+ if (wasNotLoaded && config.eliteFarmingWeightoffScreenDropMessage) {
+ checkOffScreenLeaderboardChanges()
+ }
+ ProfileStorageData.profileSpecific?.garden?.farmingWeight?.lastFarmingWeightLeaderboard =
+ leaderboardPosition
lastLeaderboardUpdate = System.currentTimeMillis()
isLoadingLeaderboard = false
}
}
+ private fun checkOffScreenLeaderboardChanges() {
+ val profileSpecific = ProfileStorageData.profileSpecific ?: return
+ val oldPosition = profileSpecific.garden.farmingWeight.lastFarmingWeightLeaderboard
+ if (oldPosition == -1) return
+
+ val diff = leaderboardPosition - oldPosition
+ if (diff == 0) return
+
+ if (diff > 0) {
+ chatOffScreenChange("§cdropped ${StringUtils.optionalPlural(diff, "place", "places")}", oldPosition)
+ } else {
+ chatOffScreenChange("§arisen ${StringUtils.optionalPlural(-diff, "place", "places")}", oldPosition)
+ }
+ }
+
+ private fun chatOffScreenChange(direction: String, oldPosition: Int) {
+ farmingChatMessage(
+ "§e[SkyHanni] §7Since your last visit to the §aGarden§7, " +
+ "you have $direction §7on the §dFarming Leaderboard§7. " +
+ "§7(§e#${oldPosition.addSeparators()} §7-> §e#${leaderboardPosition.addSeparators()}§7)"
+ )
+ }
+
private suspend fun loadLeaderboardPosition() = try {
val uuid = LorenzUtils.getPlayerUuid()
@@ -331,7 +373,7 @@ class FarmingWeightDisplay {
private fun error() {
apiError = true
LorenzUtils.error("[SkyHanni] Loading the farming weight data from elitebot.dev failed!")
- LorenzUtils.chat("§eYou can re-enter the garden to try to fix the problem. If this message repeats itself, please report it on Discord!")
+ LorenzUtils.chat("§eYou can re-enter the garden to try to fix the problem. If this message repeats, please report it on Discord!")
}
private fun calculateCollectionWeight(): MutableMap<CropType, Double> {
@@ -363,6 +405,12 @@ class FarmingWeightDisplay {
private fun CropType.getFactor() = factorPerCrop[this]!!
+ fun lookUpCommand(it: Array<String>) {
+ val name = if (it.size == 1) it[0] else LorenzUtils.getPlayerName()
+ OSUtils.openBrowser("https://elitebot.dev/@$name/")
+ LorenzUtils.chat("§e[SkyHanni] Opening Farming Profile from §b$name")
+ }
+
private val factorPerCrop by lazy {
mapOf(
CropType.WHEAT to 100_000.0,
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenBestCropTime.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenBestCropTime.kt
index efdf267ef..30afb0418 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenBestCropTime.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenBestCropTime.kt
@@ -2,8 +2,8 @@ package at.hannibal2.skyhanni.features.garden.farming
import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.data.GardenCropMilestones
-import at.hannibal2.skyhanni.data.GardenCropMilestones.Companion.getCounter
-import at.hannibal2.skyhanni.data.GardenCropMilestones.Companion.isMaxed
+import at.hannibal2.skyhanni.data.GardenCropMilestones.getCounter
+import at.hannibal2.skyhanni.data.GardenCropMilestones.isMaxed
import at.hannibal2.skyhanni.features.garden.CropType
import at.hannibal2.skyhanni.features.garden.GardenAPI.addCropIcon
import at.hannibal2.skyhanni.features.garden.GardenNextJacobContest
@@ -31,11 +31,11 @@ class GardenBestCropTime {
if (crop.isMaxed()) continue
val counter = crop.getCounter()
- val currentTier = GardenCropMilestones.getTierForCrops(counter)
+ val currentTier = GardenCropMilestones.getTierForCropCount(counter, crop)
- val cropsForCurrentTier = GardenCropMilestones.getCropsForTier(currentTier)
+ val cropsForCurrentTier = GardenCropMilestones.getCropsForTier(currentTier, crop)
val nextTier = if (config.cropMilestoneBestShowMaxedNeeded.get()) 46 else currentTier + 1
- val cropsForNextTier = GardenCropMilestones.getCropsForTier(nextTier)
+ val cropsForNextTier = GardenCropMilestones.getCropsForTier(nextTier, crop)
val have = counter - cropsForCurrentTier
val need = cropsForNextTier - cropsForCurrentTier
@@ -59,7 +59,7 @@ class GardenBestCropTime {
val helpMap = mutableMapOf<CropType, Long>()
for ((crop, time) in timeTillNextCrop) {
if (crop.isMaxed()) continue
- val currentTier = GardenCropMilestones.getTierForCrops(crop.getCounter())
+ val currentTier = GardenCropMilestones.getTierForCropCount(crop.getCounter(), crop)
val gardenExpForTier = getGardenExpForTier(currentTier + 1)
val fakeTime = time / gardenExpForTier
helpMap[crop] = fakeTime
@@ -107,7 +107,7 @@ class GardenBestCropTime {
val color = if (isCurrent) "§e" else "§7"
val contestFormat = if (GardenNextJacobContest.isNextCrop(crop)) "§n" else ""
- val currentTier = GardenCropMilestones.getTierForCrops(crop.getCounter())
+ val currentTier = GardenCropMilestones.getTierForCropCount(crop.getCounter(), crop)
val nextTier = if (config.cropMilestoneBestShowMaxedNeeded.get()) 46 else currentTier + 1
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenBurrowingSporesNotifier.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenBurrowingSporesNotifier.kt
index 73d5bcaea..8d67434de 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenBurrowingSporesNotifier.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenBurrowingSporesNotifier.kt
@@ -5,6 +5,7 @@ import at.hannibal2.skyhanni.data.TitleUtils
import at.hannibal2.skyhanni.events.LorenzChatEvent
import at.hannibal2.skyhanni.features.garden.GardenAPI
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import kotlin.time.Duration.Companion.seconds
class GardenBurrowingSporesNotifier {
@@ -14,7 +15,7 @@ class GardenBurrowingSporesNotifier {
if (!SkyHanniMod.feature.garden.burrowingSporesNotification) return
if (event.message.endsWith("§6§lVERY RARE CROP! §r§f§r§9Burrowing Spores")) {
- TitleUtils.sendTitle("§9Burrowing Spores!", 5_000)
+ TitleUtils.sendTitle("§9Burrowing Spores!", 5.seconds)
// would be sent too often, nothing special then
// ItemBlink.setBlink(NEUItems.getItemStackOrNull("BURROWING_SPORES"), 5_000)
}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenCropMilestoneDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenCropMilestoneDisplay.kt
index f6d0fe0b4..03b9ea809 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenCropMilestoneDisplay.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenCropMilestoneDisplay.kt
@@ -2,9 +2,9 @@ package at.hannibal2.skyhanni.features.garden.farming
import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.data.GardenCropMilestones
-import at.hannibal2.skyhanni.data.GardenCropMilestones.Companion.getCounter
-import at.hannibal2.skyhanni.data.GardenCropMilestones.Companion.isMaxed
-import at.hannibal2.skyhanni.data.GardenCropMilestones.Companion.setCounter
+import at.hannibal2.skyhanni.data.GardenCropMilestones.getCounter
+import at.hannibal2.skyhanni.data.GardenCropMilestones.isMaxed
+import at.hannibal2.skyhanni.data.GardenCropMilestones.setCounter
import at.hannibal2.skyhanni.data.TitleUtils
import at.hannibal2.skyhanni.events.*
import at.hannibal2.skyhanni.features.garden.CropType
@@ -23,6 +23,7 @@ import at.hannibal2.skyhanni.utils.TimeUtils
import net.minecraftforge.fml.common.eventhandler.EventPriority
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import java.util.*
+import kotlin.time.Duration.Companion.seconds
object GardenCropMilestoneDisplay {
private var progressDisplay = emptyList<List<Any>>()
@@ -35,15 +36,6 @@ object GardenCropMilestoneDisplay {
private var needsInventory = false
@SubscribeEvent
- fun onChatMessage(event: LorenzChatEvent) {
- if (!isEnabled()) return
- // TODO remove this once hypixel counts 64x pumpkin drops to cultivating
- if (event.message == "§a§lUNCOMMON DROP! §r§eDicer dropped §r§f64x §r§fPumpkin§r§e!") {
- CropType.PUMPKIN.setCounter(CropType.PUMPKIN.getCounter() + 64)
- }
- }
-
- @SubscribeEvent
fun onConfigLoad(event: ConfigLoadEvent) {
LorenzUtils.onToggle(
config.cropMilestoneBestShowMaxedNeeded,
@@ -138,7 +130,7 @@ object GardenCropMilestoneDisplay {
val lineMap = HashMap<Int, List<Any>>()
lineMap[0] = Collections.singletonList("§6Crop Milestones")
- val currentTier = GardenCropMilestones.getTierForCrops(counter)
+ val currentTier = GardenCropMilestones.getTierForCropCount(counter, crop)
val nextTier = if (config.cropMilestoneBestShowMaxedNeeded.get()) 46 else currentTier + 1
val list = mutableListOf<Any>()
@@ -150,11 +142,11 @@ object GardenCropMilestoneDisplay {
}
lineMap[1] = list
- val cropsForNextTier = GardenCropMilestones.getCropsForTier(nextTier)
+ val cropsForNextTier = GardenCropMilestones.getCropsForTier(nextTier, crop)
val (have, need) = if (config.cropMilestoneBestShowMaxedNeeded.get()) {
Pair(counter, cropsForNextTier)
} else {
- val cropsForCurrentTier = GardenCropMilestones.getCropsForTier(currentTier)
+ val cropsForCurrentTier = GardenCropMilestones.getCropsForTier(currentTier, crop)
val have = counter - cropsForCurrentTier
val need = cropsForNextTier - cropsForCurrentTier
Pair(have, need)
@@ -224,7 +216,7 @@ object GardenCropMilestoneDisplay {
SoundUtils.playBeepSound()
}
if (!needsInventory) {
- TitleUtils.sendTitle(title, 1_500)
+ TitleUtils.sendTitle(title, 1.5.seconds)
}
}
@@ -247,11 +239,11 @@ object GardenCropMilestoneDisplay {
val lineMap = HashMap<Int, List<Any>>()
val counter = CropType.MUSHROOM.getCounter()
- val currentTier = GardenCropMilestones.getTierForCrops(counter)
+ val currentTier = GardenCropMilestones.getTierForCropCount(counter, CropType.MUSHROOM)
val nextTier = currentTier + 1
- val cropsForCurrentTier = GardenCropMilestones.getCropsForTier(currentTier)
- val cropsForNextTier = GardenCropMilestones.getCropsForTier(nextTier)
+ val cropsForCurrentTier = GardenCropMilestones.getCropsForTier(currentTier, CropType.MUSHROOM)
+ val cropsForNextTier = GardenCropMilestones.getCropsForTier(nextTier, CropType.MUSHROOM)
val have = counter - cropsForCurrentTier
val need = cropsForNextTier - cropsForCurrentTier
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenCropSpeed.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenCropSpeed.kt
index c6ecce63c..c7817066e 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenCropSpeed.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenCropSpeed.kt
@@ -2,8 +2,8 @@ package at.hannibal2.skyhanni.features.garden.farming
import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.data.ClickType
-import at.hannibal2.skyhanni.data.GardenCropMilestones.Companion.getCounter
-import at.hannibal2.skyhanni.data.GardenCropMilestones.Companion.setCounter
+import at.hannibal2.skyhanni.data.GardenCropMilestones.getCounter
+import at.hannibal2.skyhanni.data.GardenCropMilestones.setCounter
import at.hannibal2.skyhanni.data.MayorElection
import at.hannibal2.skyhanni.events.CropClickEvent
import at.hannibal2.skyhanni.events.GardenToolChangeEvent
@@ -14,6 +14,7 @@ import at.hannibal2.skyhanni.features.garden.GardenAPI
import at.hannibal2.skyhanni.utils.InventoryUtils
import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName_old
import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.LorenzUtils.editCopy
import com.google.gson.JsonObject
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import kotlin.concurrent.fixedRateTimer
@@ -28,7 +29,7 @@ object GardenCropSpeed {
var averageBlocksPerSecond = 0.0
- private val blocksSpeedList = mutableListOf<Int>()
+ private var blocksSpeedList = listOf<Int>()
private var blocksBroken = 0
private var secondsStopped = 0
@@ -81,20 +82,22 @@ object GardenCropSpeed {
this.blocksBroken = 0
if (blocksBroken == 0) {
- if (blocksSpeedList.size == 0) return
+ if (blocksSpeedList.isEmpty()) return
secondsStopped++
} else {
if (secondsStopped >= config.blocksBrokenResetTime) {
resetSpeed()
}
- while (secondsStopped > 0) {
- blocksSpeedList.add(0)
- secondsStopped -= 1
- }
- blocksSpeedList.add(blocksBroken)
- if (blocksSpeedList.size == 2) {
- blocksSpeedList.removeFirst()
- blocksSpeedList.add(blocksBroken)
+ blocksSpeedList = blocksSpeedList.editCopy {
+ while (secondsStopped > 0) {
+ this.add(0)
+ secondsStopped -= 1
+ }
+ this.add(blocksBroken)
+ if (this.size == 2) {
+ this.removeFirst()
+ this.add(blocksBroken)
+ }
}
averageBlocksPerSecond = if (blocksSpeedList.size > 1) {
blocksSpeedList.dropLast(1).average()
@@ -170,7 +173,7 @@ object GardenCropSpeed {
private fun resetSpeed() {
averageBlocksPerSecond = 0.0
- blocksSpeedList.clear()
+ blocksSpeedList = emptyList()
secondsStopped = 0
}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenCustomKeybinds.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenCustomKeybinds.kt
index 41d88190f..40a2aa12e 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenCustomKeybinds.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenCustomKeybinds.kt
@@ -3,11 +3,10 @@ package at.hannibal2.skyhanni.features.garden.farming
import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.features.garden.GardenAPI
import at.hannibal2.skyhanni.mixins.transformers.AccessorKeyBinding
+import at.hannibal2.skyhanni.utils.OSUtils
import net.minecraft.client.Minecraft
import net.minecraft.client.gui.inventory.GuiEditSign
import net.minecraft.client.settings.KeyBinding
-import org.lwjgl.input.Keyboard
-import org.lwjgl.input.Mouse
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable
import java.util.*
@@ -49,21 +48,12 @@ object GardenCustomKeybinds {
return true
}
- private fun isHeld(keyCode: Int): Boolean {
- if (keyCode == 0) return false
- return if (keyCode < 0) {
- Mouse.isButtonDown(keyCode + 100)
- } else {
- Keyboard.isKeyDown(keyCode)
- }
- }
-
@JvmStatic
fun isKeyDown(keyBinding: KeyBinding, cir: CallbackInfoReturnable<Boolean>) {
if (!isActive()) return
val override = map[keyBinding] ?: return
val keyCode = override()
- cir.returnValue = isHeld(keyCode)
+ cir.returnValue = OSUtils.isKeyHeld(keyCode)
}
@JvmStatic
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/WildStrawberryDyeNotification.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/WildStrawberryDyeNotification.kt
index 9c2d38e4b..171f3c989 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/WildStrawberryDyeNotification.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/WildStrawberryDyeNotification.kt
@@ -13,6 +13,7 @@ import at.hannibal2.skyhanni.utils.NEUItems
import at.hannibal2.skyhanni.utils.SoundUtils
import io.github.moulberry.notenoughupdates.util.MinecraftExecutor
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import kotlin.time.Duration.Companion.seconds
class WildStrawberryDyeNotification {
var lastCloseTime = 0L
@@ -36,7 +37,7 @@ class WildStrawberryDyeNotification {
val internalName = event.itemStack.getInternalName_old()
if (internalName == "DYE_WILD_STRAWBERRY") {
val name = event.itemStack.name!!
- TitleUtils.sendTitle(name, 5_000)
+ TitleUtils.sendTitle(name, 5.seconds)
LorenzUtils.chat("§e[SkyHanni] You found a $name§e!")
SoundUtils.playBeepSound()
ItemBlink.setBlink(NEUItems.getItemStackOrNull("DYE_WILD_STRAWBERRY"), 5_000)
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/WrongFungiCutterWarning.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/WrongFungiCutterWarning.kt
index 76a5b50ad..916c31524 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/WrongFungiCutterWarning.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/WrongFungiCutterWarning.kt
@@ -11,6 +11,7 @@ import at.hannibal2.skyhanni.utils.ItemUtils.getLore
import at.hannibal2.skyhanni.utils.SoundUtils
import net.minecraft.item.ItemStack
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import kotlin.time.Duration.Companion.seconds
class WrongFungiCutterWarning {
private var mode = FungiMode.UNKNOWN
@@ -48,7 +49,7 @@ class WrongFungiCutterWarning {
private fun notifyWrong() {
if (!SkyHanniMod.feature.garden.fungiCutterWarn) return
- TitleUtils.sendTitle("§cWrong Fungi Cutter Mode!", 2_000)
+ TitleUtils.sendTitle("§cWrong Fungi Cutter Mode!", 2.seconds)
if (System.currentTimeMillis() > lastPlaySoundTime + 3_00) {
lastPlaySoundTime = System.currentTimeMillis()
SoundUtils.playBeepSound()
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/CaptureFarmingGear.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/CaptureFarmingGear.kt
index 33846d630..f90fbd625 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/CaptureFarmingGear.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/CaptureFarmingGear.kt
@@ -8,6 +8,7 @@ import at.hannibal2.skyhanni.features.garden.FarmingFortuneDisplay
import at.hannibal2.skyhanni.features.garden.GardenAPI
import at.hannibal2.skyhanni.features.garden.GardenAPI.getCropType
import at.hannibal2.skyhanni.utils.InventoryUtils
+import at.hannibal2.skyhanni.utils.ItemUtils
import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName_old
import at.hannibal2.skyhanni.utils.ItemUtils.getLore
import at.hannibal2.skyhanni.utils.LorenzUtils
@@ -28,7 +29,7 @@ class CaptureFarmingGear {
private val farmingLevelUpPattern = "SKILL LEVEL UP Farming .*➜(?<level>.*)".toPattern()
private val fortuneUpgradePattern = "You claimed the Garden Farming Fortune (?<level>.*) upgrade!".toPattern()
private val anitaBuffPattern = "You tiered up the Extra Farming Drops upgrade to [+](?<level>.*)%!".toPattern()
- private val anitaMenuPattern = "You have: [+](?<level>.*)%".toPattern()
+ private val anitaMenuPattern = "§7You have: §6\\+(?<level>.*)☘ Farming Fortune".toPattern()
private val lotusUpgradePattern = "Lotus (?<piece>.*) upgraded to [+].*☘!".toPattern()
private val petLevelUpPattern = "Your (?<pet>.*) leveled up to level .*!".toPattern()
@@ -77,6 +78,12 @@ class CaptureFarmingGear {
}
}
}
+
+ fun reverseCarrotFortune() {
+ val hidden = GardenAPI.config?.fortune ?: return
+ hidden.carrotFortune = !hidden.carrotFortune
+ LorenzUtils.chat("§2Toggled exportable carrot fortune to: ${hidden.carrotFortune}")
+ }
}
@SubscribeEvent
@@ -109,34 +116,53 @@ class CaptureFarmingGear {
}
if (event.inventoryName.contains("Pets")) {
// If they've 2 of same pet, one will be overwritten
- farmingItems[FarmingItems.ELEPHANT] = FFGuideGUI.getFallbackItem(FarmingItems.ELEPHANT)
- farmingItems[FarmingItems.MOOSHROOM_COW] = FFGuideGUI.getFallbackItem(FarmingItems.MOOSHROOM_COW)
- farmingItems[FarmingItems.RABBIT] = FFGuideGUI.getFallbackItem(FarmingItems.RABBIT)
- var highestElephantLvl = -1
- var highestMooshroomLvl = -1
- var highestRabbitLvl = -1
+ // optimize
+
+ for (pet in listOf(
+ FarmingItems.ELEPHANT,
+ FarmingItems.MOOSHROOM_COW,
+ FarmingItems.RABBIT,
+ FarmingItems.BEE
+ )) {
+ if (farmingItems[pet] == null) {
+ farmingItems[pet] = FFGuideGUI.getFallbackItem(pet)
+ }
+ }
+
+ // setting to current saved level -1 to stop later pages saving low rarity pets
+ var highestElephantRarity = ItemUtils.getPetRarityOld(farmingItems[FarmingItems.ELEPHANT])
+ var highestMooshroomRarity = ItemUtils.getPetRarityOld(farmingItems[FarmingItems.MOOSHROOM_COW])
+ var highestRabbitRarity = ItemUtils.getPetRarityOld(farmingItems[FarmingItems.RABBIT])
+ var highestBeeRarity = ItemUtils.getPetRarityOld(farmingItems[FarmingItems.BEE])
for ((_, item) in event.inventoryItems) {
val split = item.getInternalName_old().split(";")
if (split.first() == "ELEPHANT") {
- if (split.last().toInt() > highestElephantLvl) {
+ if (split.last().toInt() > highestElephantRarity) {
farmingItems[FarmingItems.ELEPHANT] = item
outdatedItems[FarmingItems.ELEPHANT] = false
- highestElephantLvl = split.last().toInt()
+ highestElephantRarity = split.last().toInt()
}
}
if (split.first() == "MOOSHROOM_COW") {
- if (split.last().toInt() > highestMooshroomLvl) {
+ if (split.last().toInt() > highestMooshroomRarity) {
farmingItems[FarmingItems.MOOSHROOM_COW] = item
outdatedItems[FarmingItems.MOOSHROOM_COW] = false
- highestMooshroomLvl = split.last().toInt()
+ highestMooshroomRarity = split.last().toInt()
}
}
if (split.first() == "RABBIT") {
- if (split.last().toInt() > highestRabbitLvl) {
+ if (split.last().toInt() > highestRabbitRarity) {
farmingItems[FarmingItems.RABBIT] = item
outdatedItems[FarmingItems.RABBIT] = false
- highestRabbitLvl = split.last().toInt()
+ highestRabbitRarity = split.last().toInt()
+ }
+ }
+ if (split.first() == "BEE") {
+ if (split.last().toInt() > highestBeeRarity) {
+ farmingItems[FarmingItems.BEE] = item
+ outdatedItems[FarmingItems.BEE] = false
+ highestBeeRarity = split.last().toInt()
}
}
}
@@ -174,11 +200,11 @@ class CaptureFarmingGear {
if (event.inventoryName.contains("Anita")) {
var level = -1
for ((_, item) in event.inventoryItems) {
- if (item.displayName.contains("Extra Farming Drops")) {
+ if (item.displayName.contains("Extra Farming Fortune")) {
level = 0
for (line in item.getLore()) {
- anitaMenuPattern.matchMatcher(line.removeColor()) {
- level = group("level").toInt() / 2
+ anitaMenuPattern.matchMatcher(line) {
+ level = group("level").toInt() / 4
}
}
}
@@ -204,7 +230,7 @@ class CaptureFarmingGear {
hidden.farmingLevel = group("level").romanToDecimalIfNeeded()
}
anitaBuffPattern.matchMatcher(msg) {
- hidden.anitaUpgrade = group("level").toInt() / 2
+ hidden.anitaUpgrade = group("level").toInt() / 4
}
lotusUpgradePattern.matchMatcher(msg) {
val piece = group("piece").uppercase()
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FFGuideGUI.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FFGuideGUI.kt
index 032c97547..76b0fda29 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FFGuideGUI.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FFGuideGUI.kt
@@ -129,30 +129,38 @@ open class FFGuideGUI : GuiScreen() {
)
GuiRenderUtils.renderItemAndTip(
- FarmingItems.ELEPHANT.getItem(), guiLeft + 152, guiTop + 130, mouseX, mouseY,
+ FarmingItems.ELEPHANT.getItem(), guiLeft + 142, guiTop + 130, mouseX, mouseY,
if (currentPet == FarmingItems.ELEPHANT) 0xFFB3FFB3.toInt() else 0xFF43464B.toInt()
)
GuiRenderUtils.renderItemAndTip(
- FarmingItems.MOOSHROOM_COW.getItem(), guiLeft + 172, guiTop + 130, mouseX, mouseY,
+ FarmingItems.MOOSHROOM_COW.getItem(), guiLeft + 162, guiTop + 130, mouseX, mouseY,
if (currentPet == FarmingItems.MOOSHROOM_COW) 0xFFB3FFB3.toInt() else 0xFF43464B.toInt()
)
GuiRenderUtils.renderItemAndTip(
- FarmingItems.RABBIT.getItem(), guiLeft + 192, guiTop + 130, mouseX, mouseY,
+ FarmingItems.RABBIT.getItem(), guiLeft + 182, guiTop + 130, mouseX, mouseY,
if (currentPet == FarmingItems.RABBIT) 0xFFB3FFB3.toInt() else 0xFF43464B.toInt()
)
+ GuiRenderUtils.renderItemAndTip(
+ FarmingItems.BEE.getItem(), guiLeft + 202, guiTop + 130, mouseX, mouseY,
+ if (currentPet == FarmingItems.BEE) 0xFFB3FFB3.toInt() else 0xFF43464B.toInt()
+ )
} else {
GuiRenderUtils.renderItemAndTip(
- FarmingItems.ELEPHANT.getItem(), guiLeft + 152, guiTop + 160, mouseX, mouseY,
+ FarmingItems.ELEPHANT.getItem(), guiLeft + 142, guiTop + 160, mouseX, mouseY,
if (currentPet == FarmingItems.ELEPHANT) 0xFFB3FFB3.toInt() else 0xFF43464B.toInt()
)
GuiRenderUtils.renderItemAndTip(
- FarmingItems.MOOSHROOM_COW.getItem(), guiLeft + 172, guiTop + 160, mouseX, mouseY,
+ FarmingItems.MOOSHROOM_COW.getItem(), guiLeft + 162, guiTop + 160, mouseX, mouseY,
if (currentPet == FarmingItems.MOOSHROOM_COW) 0xFFB3FFB3.toInt() else 0xFF43464B.toInt()
)
GuiRenderUtils.renderItemAndTip(
- FarmingItems.RABBIT.getItem(), guiLeft + 192, guiTop + 160, mouseX, mouseY,
+ FarmingItems.RABBIT.getItem(), guiLeft + 182, guiTop + 160, mouseX, mouseY,
if (currentPet == FarmingItems.RABBIT) 0xFFB3FFB3.toInt() else 0xFF43464B.toInt()
)
+ GuiRenderUtils.renderItemAndTip(
+ FarmingItems.BEE.getItem(), guiLeft + 202, guiTop + 160, mouseX, mouseY,
+ if (currentPet == FarmingItems.BEE) 0xFFB3FFB3.toInt() else 0xFF43464B.toInt()
+ )
GuiRenderUtils.renderItemAndTip(
FarmingItems.HELMET.getItem(), guiLeft + 162, guiTop + 80, mouseX, mouseY)
@@ -273,21 +281,26 @@ open class FFGuideGUI : GuiScreen() {
if (selectedPage != FortuneGuidePage.UPGRADES) {
if (currentCrop == null) {
- if (GuiRenderUtils.isPointInRect(mouseX, mouseY, guiLeft + 152, guiTop + 130,
+ if (GuiRenderUtils.isPointInRect(mouseX, mouseY, guiLeft + 142, guiTop + 130,
16, 16) && currentPet != FarmingItems.ELEPHANT) {
SoundUtils.playClickSound()
currentPet = FarmingItems.ELEPHANT
FFStats.getTotalFF()
- } else if (GuiRenderUtils.isPointInRect(mouseX, mouseY, guiLeft + 172, guiTop + 130,
+ } else if (GuiRenderUtils.isPointInRect(mouseX, mouseY, guiLeft + 162, guiTop + 130,
16, 16) && currentPet != FarmingItems.MOOSHROOM_COW) {
SoundUtils.playClickSound()
currentPet = FarmingItems.MOOSHROOM_COW
FFStats.getTotalFF()
- } else if (GuiRenderUtils.isPointInRect(mouseX, mouseY, guiLeft + 192, guiTop + 130,
+ } else if (GuiRenderUtils.isPointInRect(mouseX, mouseY, guiLeft + 182, guiTop + 130,
16, 16) && currentPet != FarmingItems.RABBIT) {
SoundUtils.playClickSound()
currentPet = FarmingItems.RABBIT
FFStats.getTotalFF()
+ } else if (GuiRenderUtils.isPointInRect(mouseX, mouseY, guiLeft + 202, guiTop + 130,
+ 16, 16) && currentPet != FarmingItems.BEE) {
+ SoundUtils.playClickSound()
+ currentPet = FarmingItems.BEE
+ FFStats.getTotalFF()
} else if (GuiRenderUtils.isPointInRect(mouseX, mouseY, guiLeft + 142, guiTop + 5, 16, 16)) {
SoundUtils.playClickSound()
currentArmor = if (currentArmor == 1) 0 else 1
@@ -314,21 +327,26 @@ open class FFGuideGUI : GuiScreen() {
currentEquipment = if (currentEquipment == 4) 0 else 4
}
} else {
- if (GuiRenderUtils.isPointInRect(mouseX, mouseY, guiLeft + 152, guiTop + 160,
+ if (GuiRenderUtils.isPointInRect(mouseX, mouseY, guiLeft + 142, guiTop + 160,
16, 16) && currentPet != FarmingItems.ELEPHANT) {
SoundUtils.playClickSound()
currentPet = FarmingItems.ELEPHANT
FFStats.getTotalFF()
- } else if (GuiRenderUtils.isPointInRect(mouseX, mouseY, guiLeft + 172, guiTop + 160,
+ } else if (GuiRenderUtils.isPointInRect(mouseX, mouseY, guiLeft + 162, guiTop + 160,
16, 16) && currentPet != FarmingItems.MOOSHROOM_COW) {
SoundUtils.playClickSound()
currentPet = FarmingItems.MOOSHROOM_COW
FFStats.getTotalFF()
- } else if (GuiRenderUtils.isPointInRect(mouseX, mouseY, guiLeft + 192, guiTop + 160,
+ } else if (GuiRenderUtils.isPointInRect(mouseX, mouseY, guiLeft + 182, guiTop + 160,
16, 16) && currentPet != FarmingItems.RABBIT) {
SoundUtils.playClickSound()
currentPet = FarmingItems.RABBIT
FFStats.getTotalFF()
+ } else if (GuiRenderUtils.isPointInRect(mouseX, mouseY, guiLeft + 202, guiTop + 160,
+ 16, 16) && currentPet != FarmingItems.BEE) {
+ SoundUtils.playClickSound()
+ currentPet = FarmingItems.BEE
+ FFStats.getTotalFF()
}
}
} else {
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FFStats.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FFStats.kt
index 5eed793aa..136917c7c 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FFStats.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FFStats.kt
@@ -13,6 +13,7 @@ import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getFarmingForDummie
import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getPetItem
import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getPetLevel
import net.minecraft.item.ItemStack
+import kotlin.math.floor
object FFStats {
private val toolHasBountiful get() = GardenAPI.config?.toolWithBountiful
@@ -42,6 +43,7 @@ object FFStats {
val elephantFF = mutableMapOf<FFTypes, Double>()
val mooshroomFF = mutableMapOf<FFTypes, Double>()
val rabbitFF = mutableMapOf<FFTypes, Double>()
+ val beeFF = mutableMapOf<FFTypes, Double>()
var currentPetItem = ""
var baseFF = mutableMapOf<FFTypes, Double>()
@@ -78,6 +80,7 @@ object FFStats {
getPetFFData(FarmingItems.ELEPHANT.getItem(), elephantFF)
getPetFFData(FarmingItems.MOOSHROOM_COW.getItem(), mooshroomFF)
getPetFFData(FarmingItems.RABBIT.getItem(), rabbitFF)
+ getPetFFData(FarmingItems.BEE.getItem(), beeFF)
getGenericFF(baseFF)
@@ -86,13 +89,13 @@ object FFStats {
fun getCropStats(crop: CropType, tool: ItemStack) {
cropPage.clear()
- cropPage[FortuneStats.BASE] = Pair(totalBaseFF[FFTypes.TOTAL] ?: 100.0, 1250.0)
+ cropPage[FortuneStats.BASE] = Pair(totalBaseFF[FFTypes.TOTAL] ?: 100.0, 1277.0)
cropPage[FortuneStats.CROP_UPGRADE] = Pair((crop.getUpgradeLevel()?.toDouble() ?: 0.0) * 5.0, 45.0)
cropPage[FortuneStats.ACCESSORY] = Pair(CropAccessoryData.cropAccessory?.getFortune(crop) ?: 0.0, 30.0)
cropPage[FortuneStats.FFD] = Pair((tool.getFarmingForDummiesCount() ?: 0).toDouble(), 5.0)
cropPage[FortuneStats.TURBO] = Pair(FarmingFortuneDisplay.getTurboCropFortune(tool, crop), 25.0)
cropPage[FortuneStats.DEDICATION] = Pair(FarmingFortuneDisplay.getDedicationFortune(tool, crop), 92.0)
- cropPage[FortuneStats.CULTIVATING] = Pair(FarmingFortuneDisplay.getCultivatingFortune(tool), 10.0)
+ cropPage[FortuneStats.CULTIVATING] = Pair(FarmingFortuneDisplay.getCultivatingFortune(tool), 20.0)
FarmingFortuneDisplay.loadFortuneLineData(tool, 0.0)
@@ -149,14 +152,15 @@ object FFStats {
else -> {}
}
+ if (crop == CropType.CARROT) {
+ val hidden = GardenAPI.config?.fortune ?: return
+ val carrotFortune = if (hidden.carrotFortune) 12.0 else 0.0
+ cropPage[FortuneStats.EXPORTED_CARROT] = Pair(carrotFortune, 12.0)
+ }
cropPage[FortuneStats.CROP_TOTAL] = Pair(
cropPage.toList().sumOf { it.second.first },
cropPage.toList().sumOf { it.second.second })
-
- if (tool.getInternalName_old().contains("DICER")) {
- cropPage[FortuneStats.DICER] = Pair(33.0, 33.0)
- }
}
private fun getEquipmentFFData(item: ItemStack, out: MutableMap<FFTypes, Double>) {
@@ -198,7 +202,7 @@ object FFStats {
out[FFTypes.FARMING_LVL] = savedStats.farmingLevel.toDouble() * 4
out[FFTypes.COMMUNITY_SHOP] = (ProfileStorageData.playerSpecific?.gardenCommunityUpgrade ?: -1).toDouble() * 4
out[FFTypes.PLOTS] = savedStats.plotsUnlocked.toDouble() * 3
- out[FFTypes.ANITA] = savedStats.anitaUpgrade.toDouble() * 2
+ out[FFTypes.ANITA] = savedStats.anitaUpgrade.toDouble() * 4
if (cakeExpireTime - System.currentTimeMillis() > 0 || cakeExpireTime == -1L) {
out[FFTypes.CAKE] = 5.0
} else {
@@ -222,6 +226,10 @@ object FFStats {
petList = rabbitFF
}
+ FarmingItems.BEE -> {
+ petList = beeFF
+ }
+
else -> {}
}
currentPetItem = FFGuideGUI.currentPet.getItem().getPetItem().toString()
@@ -238,11 +246,15 @@ object FFStats {
if (strength != null) {
val rawInternalName = pet.getInternalName()
return if (rawInternalName.contains("ELEPHANT;4")) {
- 1.8 * petLevel
+ 1.5 * petLevel
} else if (rawInternalName.contains("MOOSHROOM_COW;4")) {
- (10 + petLevel).toDouble() + strength / (40 - petLevel * .2)
+ (10 + petLevel).toDouble() + floor(floor(strength / (40 - petLevel * .2)) * .7)
} else if (rawInternalName.contains("MOOSHROOM")) {
(10 + petLevel).toDouble()
+ } else if (rawInternalName.contains("BEE;2")) {
+ 0.2 * petLevel
+ } else if (rawInternalName.contains("BEE;3") || rawInternalName.contains("BEE;4")) {
+ 0.3 * petLevel
} else 0.0
}
return 0.0
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FarmingItems.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FarmingItems.kt
index 3cd80db07..4da76872b 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FarmingItems.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FarmingItems.kt
@@ -2,5 +2,5 @@ package at.hannibal2.skyhanni.features.garden.fortuneguide
enum class FarmingItems {
WHEAT, CARROT, POTATO, NETHER_WART, PUMPKIN, MELON, COCOA_BEANS, SUGAR_CANE, CACTUS, MUSHROOM,
- HELMET, CHESTPLATE, LEGGINGS, BOOTS, NECKLACE, CLOAK, BELT, BRACELET, ELEPHANT, MOOSHROOM_COW, RABBIT
+ HELMET, CHESTPLATE, LEGGINGS, BOOTS, NECKLACE, CLOAK, BELT, BRACELET, ELEPHANT, MOOSHROOM_COW, RABBIT, BEE
} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FarmingReforges.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FarmingReforges.kt
index 672428ba7..d640d9741 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FarmingReforges.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FarmingReforges.kt
@@ -13,7 +13,7 @@ enum class FarmingReforges(
BLESSED("Blessed", "BLESSED_FRUIT", 5, 7, 9, 13, 16, 20),
BOUNTIFUL("Bountiful", "GOLDEN_BALL", 1, 2, 3, 5, 7, 10),
BLOOMING("Blooming", "FLOWERING_BOUQUET", 1, 2, 3, 4, 5, 6),
- ROOTED("Rooted", "BURROWING_SPORES", 4, 6, 8, 10, 12, 14),
+ ROOTED("Rooted", "BURROWING_SPORES", 6, 9, 12, 15, 18, 21),
BUSTLING("Bustling", "SKYMART_BROCHURE", 1, 2, 4, 6, 8, 10),
MOSSY("Mossy", "OVERGROWN_GRASS", 5, 10, 15, 20, 25, 30),
ROBUST("Robust", "", 2, 3, 4, 6, 8, 10),
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FortuneStats.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FortuneStats.kt
index 1e108a2dc..77c275973 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FortuneStats.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FortuneStats.kt
@@ -16,8 +16,8 @@ enum class FortuneStats(val label: String, val tooltip: String) {
COLLECTION("§2Collection Analyst", "§7§2Fortune from increasing crop collection\n§2You get 8☘ per digit - 4"),
HARVESTING("§2Harvesting Enchantment", "§7§2Fortune for each enchantment level\n§2You get 12.5☘ per level"),
SUNDER("§2Sunder Enchantment", "§7§2Fortune for each enchantment level\n§2You get 12.5☘ per level"),
- CULTIVATING("§2Cultivating Enchantment", "§7§2Fortune for each enchantment level\n§2You get 1☘ per level"),
+ CULTIVATING("§2Cultivating Enchantment", "§7§2Fortune for each enchantment level\n§2You get 2☘ per level"),
TURBO("§2Turbo-Crop Enchantment", "§7§2Fortune for each enchantment level\n§2You get 5☘ per level"),
DEDICATION("§2Dedication Enchantment", "§7§2Fortune for each enchantment level\n§2and crop milestone"),
- DICER("§2Dicer Ability", "§7§2Theoretical fortune from the dicer ability\n§eIs very random! and not added to total ☘")
+ EXPORTED_CARROT("§2Exported Carrot", "§7§2Gain 12☘ from exporting Carrots in the Rift!\n§eRun /shcarrot to toggle the stat")
} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FortuneUpgrades.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FortuneUpgrades.kt
index d047780c7..c4f0848fe 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FortuneUpgrades.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FortuneUpgrades.kt
@@ -2,7 +2,7 @@ package at.hannibal2.skyhanni.features.garden.fortuneguide
import at.hannibal2.skyhanni.data.CropAccessoryData
import at.hannibal2.skyhanni.data.GardenCropMilestones
-import at.hannibal2.skyhanni.data.GardenCropMilestones.Companion.getCounter
+import at.hannibal2.skyhanni.data.GardenCropMilestones.getCounter
import at.hannibal2.skyhanni.features.garden.CropAccessory
import at.hannibal2.skyhanni.features.garden.CropType
import at.hannibal2.skyhanni.features.garden.CropType.Companion.getTurboCrop
@@ -46,7 +46,7 @@ object FortuneUpgrades {
genericUpgrades.add(
FortuneUpgrade(
"§7Upgrade Anita bonus to level ${hidden.anitaUpgrade + 1}",
- null, "JACOBS_TICKET", anitaTicketsNeeded[hidden.anitaUpgrade], 2.0
+ null, "JACOBS_TICKET", anitaTicketsNeeded[hidden.anitaUpgrade], 4.0
)
)
}
@@ -198,7 +198,7 @@ object FortuneUpgrades {
)
)
}
- val cropMilestone = GardenCropMilestones.getTierForCrops(crop.getCounter())
+ val cropMilestone = GardenCropMilestones.getTierForCropCount(crop.getCounter(), crop)
if (dedicationLvl != 4 && cropMilestone > 0) {
val dedicationMultiplier = listOf(0.5, 0.75, 1.0, 2.0)[dedicationLvl]
val dedicationIncrease =
@@ -221,7 +221,7 @@ object FortuneUpgrades {
}
if (cultivatingLvl == 0) {
cropSpecificUpgrades.add(
- FortuneUpgrade("§7Enchant your ${tool.displayName} §7with Cultivating", null, "CULTIVATING;1", 1, 6.0)
+ FortuneUpgrade("§7Enchant your ${tool.displayName} §7with Cultivating", null, "CULTIVATING;1", 1, 12.0)
)
}
if (turboCropLvl != 5) {
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/TODO list b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/TODO list
deleted file mode 100644
index a34e366d7..000000000
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/TODO list
+++ /dev/null
@@ -1,66 +0,0 @@
-V2 Plans
-
-Guide for cheapest upgrades:
- - Anita buff
- - Garden plots
- - Pet Item
- - Equipment
- - Green thumb
- - Reforges
- - Recombs
- - Armor
- - Reforges
- - Recombs
- - Talisman
- - Tools
- - Farming for dummies
- - Harvesting 6
- - Reforge
- - Recomb
- - Sunder
- - Dedication
- - Crop upgrade
- - Turbo crop
-
-Big warning for missing data (pets, armor, equipment) (if it has to generate a fallback item)
-Big warnign for misisng skill level, anita, plots
-Indicator when some of your gear is outdated
- - Little sign telling you
- - Line in the tooltip of the item
-
-Changing lore on items inside the menu to reflect changes
- - Changing the amount of visitors served to reflect the real amount
- - Changing the pet level to reflect the pets actual level
-
-Max value on bars will update depending on chosen pet
- - Will be visible on all pages
-
-If you have show as drop multiplier off -100ff
-When opening the menu it will open to the tool you are currently holding
-It will also auto select the current pet you have out if that is a farming pet
-
-Add colours to the text
-
-Maybe:
-Clicking on the already selected crop up top will cycle between overview and upgrades
-
-Later on:
-GUI:
-Add a border around the edge of the display
-Make this adjust based on the selected page
-
-!!!!
-Bugs:
-Major:
-Sometimes the greenthumb visitor counter breaks?
-Sometimes the ff breakdown for equipment and armor does not work in the gui?
- - fixes by holding shift over an item in the inventory then going back into the gui
-If they sell their equipment or pets, they will be saved until a new one is bought and their stats counted : fix, don't liquidize your stuff lol
-- can fix pets, equipment is more difficult
-Minor:
-Taking off or putting equipment on inside the menu won't update it until you reopen the inventory
- - also if they sell the piece of equipment, it will always think they still have it
-!!!!
-
-Add:
-Daedalus axe for mushroom \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/pages/OverviewPage.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/pages/OverviewPage.kt
index d0ba39603..b92e63a20 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/pages/OverviewPage.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/pages/OverviewPage.kt
@@ -17,19 +17,14 @@ class OverviewPage: FFGuideGUI.FFGuidePage() {
override fun drawPage(mouseX: Int, mouseY: Int, partialTicks: Float) {
val timeUntilCakes = TimeUtils.formatDuration(FFStats.cakeExpireTime - System.currentTimeMillis())
- //todo change based on pet and based on setting
- GuiRenderUtils.drawFarmingBar(
- "§6Universal Farming Fortune",
+ GuiRenderUtils.drawFarmingBar("§6Universal Farming Fortune",
"§7§2Farming fortune in that is\n§2applied to every crop\n§eNot the same as tab FF\n" +
- "§eSee on the grass block page",
- FFStats.totalBaseFF[FFTypes.TOTAL] ?: 0,
- 1250,
- FFGuideGUI.guiLeft + 15,
- FFGuideGUI.guiTop + 5, 90, mouseX, mouseY, FFGuideGUI.tooltipToDisplay)
+ "§eSee on the grass block page", FFStats.totalBaseFF[FFTypes.TOTAL] ?: 0, 1277,
+ FFGuideGUI.guiLeft + 15, FFGuideGUI.guiTop + 5, 90, mouseX, mouseY, FFGuideGUI.tooltipToDisplay)
var line = if (FFStats.baseFF[FFTypes.ANITA]!! < 0.0) "§cAnita buff not saved\n§eVisit Anita to set it!"
- else "§7§2Fortune for levelling your Anita extra crops\n§2You get 2☘ per buff level"
- GuiRenderUtils.drawFarmingBar("§2Anita Buff", line, FFStats.baseFF[FFTypes.ANITA] ?: 0.0, 30, FFGuideGUI.guiLeft + 15,
+ else "§7§2Fortune for levelling your Anita extra crops\n§2You get 4☘ per buff level"
+ GuiRenderUtils.drawFarmingBar("§2Anita Buff", line, FFStats.baseFF[FFTypes.ANITA] ?: 0.0, 60, FFGuideGUI.guiLeft + 15,
FFGuideGUI.guiTop + 30, 90, mouseX, mouseY, FFGuideGUI.tooltipToDisplay)
line = if (FFStats.baseFF[FFTypes.FARMING_LVL]!! < 0.0) "§cFarming level not saved\n§eOpen /skills to set it!"
@@ -114,7 +109,7 @@ class OverviewPage: FFGuideGUI.FFGuidePage() {
when (currentArmor) {
0 -> 50
4 -> 0
- else -> 16.67
+ else -> 16.667
}
} else {
when (currentArmor) {
@@ -138,14 +133,26 @@ class OverviewPage: FFGuideGUI.FFGuidePage() {
value, FFGuideGUI.guiLeft + 135,
FFGuideGUI.guiTop + 105, 90, mouseX, mouseY, FFGuideGUI.tooltipToDisplay)
- val currentPet = when (FFGuideGUI.currentPet) {
- FarmingItems.ELEPHANT -> FFStats.elephantFF
- FarmingItems.MOOSHROOM_COW -> FFStats.mooshroomFF
- else -> FFStats.rabbitFF
+ var currentPet = FFStats.rabbitFF
+ var petMaxFF = 60
+ when (FFGuideGUI.currentPet) {
+ FarmingItems.ELEPHANT -> {
+ currentPet = FFStats.elephantFF
+ petMaxFF = 210
+ }
+ FarmingItems.MOOSHROOM_COW -> {
+ currentPet = FFStats.mooshroomFF
+ petMaxFF = 217
+ }
+ FarmingItems.BEE -> {
+ currentPet = FFStats.beeFF
+ petMaxFF = 90
+ }
+ else -> {}
}
GuiRenderUtils.drawFarmingBar("§2Total Pet Fortune", "§7§2The total fortune from your pet and its item",
- currentPet[FFTypes.TOTAL] ?: 0, 240, FFGuideGUI.guiLeft + 105,
+ currentPet[FFTypes.TOTAL] ?: 0, petMaxFF, FFGuideGUI.guiLeft + 105,
FFGuideGUI.guiTop + 155, 70, mouseX, mouseY, FFGuideGUI.tooltipToDisplay)
line = when (FFStats.currentPetItem) {
@@ -177,7 +184,7 @@ class OverviewPage: FFGuideGUI.FFGuidePage() {
line = if (currentEquipment == 0) "§7§2Total fortune from all your equipment\n§2Select a piece for more info"
else "§7§2Total fortune from your\n${equipmentItem.getItem().displayName}"
GuiRenderUtils.drawFarmingBar("§2Total $word Fortune", line, equipmentFF[FFTypes.TOTAL] ?: 0,
- if (currentEquipment == 0) 198 else 49.5,
+ if (currentEquipment == 0) 218 else 54.5,
FFGuideGUI.guiLeft + 255, FFGuideGUI.guiTop + 30, 90, mouseX, mouseY, FFGuideGUI.tooltipToDisplay)
line = if (currentEquipment == 0) "§7§2The base fortune from all your equipment\n§2Select a piece for more info"
@@ -195,7 +202,7 @@ class OverviewPage: FFGuideGUI.FFGuidePage() {
line = if (currentEquipment == 0) "§7§2The fortune from all of your equipment's reforges\n§2Select a piece for more info"
else "§7§2Total reforge fortune from your\n${equipmentItem.getItem().displayName}"
GuiRenderUtils.drawFarmingBar("§2$word Reforge", line, equipmentFF[FFTypes.REFORGE] ?: 0,
- if (currentEquipment == 0) 40 else 10,
+ if (currentEquipment == 0) 60 else 15,
FFGuideGUI.guiLeft + 255, FFGuideGUI.guiTop + 105, 90, mouseX, mouseY, FFGuideGUI.tooltipToDisplay)
line = if (currentEquipment == 0) "§7§2The fortune from all of your equipment's enchantments\n§2Select a piece for more info"
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/inventory/AnitaExtraFarmingFortune.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/inventory/AnitaExtraFarmingFortune.kt
new file mode 100644
index 000000000..e0e7da8e2
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/inventory/AnitaExtraFarmingFortune.kt
@@ -0,0 +1,82 @@
+package at.hannibal2.skyhanni.features.garden.inventory
+
+import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.events.RepositoryReloadEvent
+import at.hannibal2.skyhanni.features.garden.GardenAPI
+import at.hannibal2.skyhanni.utils.InventoryUtils
+import at.hannibal2.skyhanni.utils.LorenzUtils.indexOfFirst
+import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName
+import at.hannibal2.skyhanni.utils.NEUItems.getPrice
+import at.hannibal2.skyhanni.utils.NumberUtil
+import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators
+import at.hannibal2.skyhanni.utils.NumberUtil.formatNumber
+import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher
+import at.hannibal2.skyhanni.utils.jsonobjects.AnitaUpgradeCostsJson
+import net.minecraftforge.event.entity.player.ItemTooltipEvent
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+
+class AnitaExtraFarmingFortune {
+ private val config get() = SkyHanniMod.feature.garden
+ private var levelPrice = emptyMap<Int, AnitaUpgradeCostsJson.Price>()
+
+ @SubscribeEvent
+ fun onItemTooltipLow(event: ItemTooltipEvent) {
+ if (!config.extraFarmingFortune) return
+
+ if (InventoryUtils.openInventoryName() != "Anita") return
+
+ val stack = event.itemStack ?: return
+
+ if (!stack.displayName.contains("Extra Farming Fortune")) return
+
+ val anitaUpgrade = GardenAPI.config?.fortune?.anitaUpgrade ?: return
+
+ var contributionFactor = 1.0
+ val baseAmount = levelPrice[anitaUpgrade + 1]?.jacob_tickets ?: return
+ for (line in event.toolTip) {
+ "§5§o§aJacob's Ticket §8x(?<realAmount>.*)".toPattern().matchMatcher(line) {
+ val realAmount = group("realAmount").formatNumber().toDouble()
+ contributionFactor = realAmount / baseAmount
+ }
+ }
+
+ var goldMedals = 0
+ var jacobTickets = 0
+ for ((level, price) in levelPrice) {
+ if (level > anitaUpgrade) {
+ goldMedals += price.gold_medals
+ jacobTickets += price.jacob_tickets
+ }
+ }
+ jacobTickets = (contributionFactor * jacobTickets).toInt()
+
+ val index = event.toolTip.indexOfFirst("§5§o§eClick to trade!")?.let { it - 1 } ?: return
+
+ // TODO: maybe only show the price when playing classic
+// if (!LorenzUtils.noTradeMode) {
+ val price = jacobTickets * "JACOBS_TICKET".asInternalName().getPrice()
+ event.toolTip.add(index, " §7Price: §6${NumberUtil.format(price)} coins")
+// }
+ event.toolTip.add(index, "§aJacob Tickets §8x${jacobTickets.addSeparators()}")
+ event.toolTip.add(index, "§6Gold medals: §8x$goldMedals")
+ event.toolTip.add(index, "§7Cost to max out")
+ event.toolTip.add(index, "")
+
+
+ val upgradeIndex = event.toolTip.indexOfFirst { it.contains("You have") }
+ if (upgradeIndex != -1) {
+ event.toolTip.add(upgradeIndex + 1, "§7Current Tier: §e$anitaUpgrade/${levelPrice.size}")
+ }
+ }
+
+ @SubscribeEvent
+ fun onRepoReload(event: RepositoryReloadEvent) {
+ event.getConstant<AnitaUpgradeCostsJson>("AnitaUpgradeCosts")?.let {
+ val map = mutableMapOf<Int, AnitaUpgradeCostsJson.Price>()
+ for ((rawNumber, price) in it.level_price) {
+ map[rawNumber.toInt()] = price
+ }
+ levelPrice = map
+ }
+ }
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/inventory/GardenCropMilestoneAverage.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/inventory/GardenCropMilestoneAverage.kt
deleted file mode 100644
index 7ea8ff423..000000000
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/inventory/GardenCropMilestoneAverage.kt
+++ /dev/null
@@ -1,45 +0,0 @@
-package at.hannibal2.skyhanni.features.garden.inventory
-
-import at.hannibal2.skyhanni.SkyHanniMod
-import at.hannibal2.skyhanni.data.GardenCropMilestones
-import at.hannibal2.skyhanni.data.GardenCropMilestones.Companion.getCounter
-import at.hannibal2.skyhanni.events.CropMilestoneUpdateEvent
-import at.hannibal2.skyhanni.events.InventoryCloseEvent
-import at.hannibal2.skyhanni.events.RenderInventoryItemTipEvent
-import at.hannibal2.skyhanni.features.garden.CropType
-import at.hannibal2.skyhanni.utils.LorenzUtils.round
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
-
-class GardenCropMilestoneAverage {
- private var average = -1.0
-
- @SubscribeEvent
- fun onCropMilestoneUpdate(event: CropMilestoneUpdateEvent) {
- if (!SkyHanniMod.feature.garden.numberAverageCropMilestone) return
-
- val tiers = mutableListOf<Double>()
- for (cropType in CropType.entries) {
- val counter = cropType.getCounter()
- val tier = GardenCropMilestones.getTierForCrops(counter)
- tiers.add(tier.toDouble())
- }
- average = (tiers.sum() / CropType.entries.size).round(2)
- }
-
- @SubscribeEvent
- fun onInventoryClose(event: InventoryCloseEvent) {
- average = -1.0
- }
-
- @SubscribeEvent
- fun onRenderItemTip(event: RenderInventoryItemTipEvent) {
- if (average == -1.0) return
-
- if (event.slot.slotNumber == 38) {
- event.offsetY = -23
- event.offsetX = -50
- event.alignLeft = false
- event.stackTip = "§6Average Crop Milestone: §e$average"
- }
- }
-} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/inventory/GardenCropMilestoneInventory.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/inventory/GardenCropMilestoneInventory.kt
new file mode 100644
index 000000000..2c545983c
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/inventory/GardenCropMilestoneInventory.kt
@@ -0,0 +1,77 @@
+package at.hannibal2.skyhanni.features.garden.inventory
+
+import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.data.GardenCropMilestones
+import at.hannibal2.skyhanni.data.GardenCropMilestones.getCounter
+import at.hannibal2.skyhanni.events.CropMilestoneUpdateEvent
+import at.hannibal2.skyhanni.events.InventoryCloseEvent
+import at.hannibal2.skyhanni.events.RenderInventoryItemTipEvent
+import at.hannibal2.skyhanni.features.garden.CropType
+import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.LorenzUtils.indexOfFirst
+import at.hannibal2.skyhanni.utils.LorenzUtils.round
+import at.hannibal2.skyhanni.utils.NumberUtil
+import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators
+import at.hannibal2.skyhanni.utils.StringUtils
+import net.minecraftforge.event.entity.player.ItemTooltipEvent
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+
+class GardenCropMilestoneInventory {
+ private var average = -1.0
+ private val config get() = SkyHanniMod.feature.garden
+
+ @SubscribeEvent
+ fun onCropMilestoneUpdate(event: CropMilestoneUpdateEvent) {
+ if (!config.numberAverageCropMilestone) return
+
+ val tiers = mutableListOf<Double>()
+ for (cropType in CropType.entries) {
+ val counter = cropType.getCounter()
+ val tier = GardenCropMilestones.getTierForCropCount(counter, cropType)
+ tiers.add(tier.toDouble())
+ }
+ average = (tiers.sum() / CropType.entries.size).round(2)
+ }
+
+ @SubscribeEvent
+ fun onInventoryClose(event: InventoryCloseEvent) {
+ average = -1.0
+ }
+
+ @SubscribeEvent
+ fun onRenderItemTip(event: RenderInventoryItemTipEvent) {
+ if (average == -1.0) return
+
+ if (event.slot.slotNumber == 38) {
+ event.offsetY = -23
+ event.offsetX = -50
+ event.alignLeft = false
+ event.stackTip = "§6Average Crop Milestone: §e$average"
+ }
+ }
+
+ @SubscribeEvent
+ fun onItemTooltipLow(event: ItemTooltipEvent) {
+ if (!LorenzUtils.inSkyBlock) return
+ if (!config.cropMilestoneTotalProgress) return
+
+ val itemStack = event.itemStack ?: return
+ val crop = GardenCropMilestones.getCropTypeByLore(itemStack) ?: return
+
+ val maxTier = GardenCropMilestones.getMaxTier()
+ val maxCounter = GardenCropMilestones.getCropsForTier(maxTier, crop)
+
+ val index = event.toolTip.indexOfFirst(
+ "§5§o§7Rewards:",
+ ) ?: return
+
+ val counter = crop.getCounter().toDouble()
+ val percentage = counter / maxCounter
+ val percentageFormat = LorenzUtils.formatPercentage(percentage)
+
+ event.toolTip.add(index, " ")
+ val progressBar = StringUtils.progressBar(percentage)
+ event.toolTip.add(index, "$progressBar §e${counter.addSeparators()}§6/§e${NumberUtil.format(maxCounter)}")
+ event.toolTip.add(index, "§7Progress to Tier $maxTier: §e$percentageFormat")
+ }
+} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/inventory/GardenNextPlotPrice.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/inventory/GardenNextPlotPrice.kt
index 759bbaa1d..ca82b3b17 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/inventory/GardenNextPlotPrice.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/inventory/GardenNextPlotPrice.kt
@@ -31,13 +31,13 @@ class GardenNextPlotPrice {
}
if (next) {
- val (itemName, amount) = ItemUtils.readItemAmount(line)
- if (itemName != null) {
+ ItemUtils.readItemAmount(line)?.let {
+ val (itemName, amount) = it
val lowestBin = NEUItems.getPrice(NEUItems.getRawInternalName(itemName))
val price = lowestBin * amount
val format = NumberUtil.format(price)
list[i] = list[i] + " §7(§6$format§7)"
- } else {
+ } ?: {
LorenzUtils.error("§c[SkyHanni] Could not read item '$line'")
}
break
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorFeatures.kt
index e5d3a89f4..98975b61d 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorFeatures.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorFeatures.kt
@@ -11,7 +11,8 @@ import at.hannibal2.skyhanni.features.garden.farming.GardenCropSpeed.getSpeed
import at.hannibal2.skyhanni.mixins.hooks.RenderLivingEntityHelper
import at.hannibal2.skyhanni.test.command.CopyErrorCommand
import at.hannibal2.skyhanni.utils.*
-import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName_old
+import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName
+import at.hannibal2.skyhanni.utils.ItemUtils.getItemName
import at.hannibal2.skyhanni.utils.ItemUtils.getItemNameOrNull
import at.hannibal2.skyhanni.utils.ItemUtils.getLore
import at.hannibal2.skyhanni.utils.ItemUtils.name
@@ -26,7 +27,6 @@ import at.hannibal2.skyhanni.utils.RenderUtils.renderStringsAndItems
import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher
import at.hannibal2.skyhanni.utils.StringUtils.removeColor
import at.hannibal2.skyhanni.utils.renderables.Renderable
-import io.github.moulberry.moulconfig.internal.KeybindHelper
import io.github.moulberry.notenoughupdates.events.SlotClickEvent
import io.github.moulberry.notenoughupdates.util.MinecraftExecutor
import net.minecraft.client.Minecraft
@@ -44,6 +44,7 @@ import net.minecraftforge.fml.common.eventhandler.EventPriority
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import org.lwjgl.input.Keyboard
import kotlin.math.round
+import kotlin.time.Duration.Companion.seconds
private val config get() = SkyHanniMod.feature.garden
@@ -57,7 +58,7 @@ class GardenVisitorFeatures {
private val visitorChatMessagePattern = "§e\\[NPC] (§.)?(?<name>.*)§f: §r.*".toPattern()
private val logger = LorenzLogger("garden/visitors")
- private var price = 0.0
+ private var lastFullPrice = 0.0
private val offerCache = mutableListOf<String>()
companion object {
@@ -113,12 +114,13 @@ class GardenVisitorFeatures {
if (line == "§7Items Required:") continue
if (line.isEmpty()) break
- val (itemName, amount) = ItemUtils.readItemAmount(line)
- if (itemName == null) {
+ val pair = ItemUtils.readItemAmount(line)
+ if (pair == null) {
LorenzUtils.error("§c[SkyHanni] Could not read item '$line'")
continue
}
- val internalName = NEUItems.getRawInternalName(itemName)
+ val (itemName, amount) = pair
+ val internalName = NEUInternalName.fromItemName(itemName)
visitor.items[internalName] = amount
}
@@ -165,7 +167,7 @@ class GardenVisitorFeatures {
val newDisplay = mutableListOf<List<Any>>()
if (!config.visitorNeedsDisplay) return newDisplay
- val requiredItems = mutableMapOf<String, Int>()
+ val requiredItems = mutableMapOf<NEUInternalName, Int>()
val newVisitors = mutableListOf<String>()
for ((visitorName, visitor) in visitors) {
if (visitor.status == VisitorStatus.ACCEPTED || visitor.status == VisitorStatus.REFUSED) continue
@@ -183,8 +185,8 @@ class GardenVisitorFeatures {
var totalPrice = 0.0
newDisplay.addAsSingletonList("§7Visitor items needed:")
for ((internalName, amount) in requiredItems) {
- val name = NEUItems.getItemStack(internalName).name!!
- val itemStack = NEUItems.getItemStack(internalName)
+ val name = internalName.getItemName()
+ val itemStack = internalName.getItemStack()
val list = mutableListOf<Any>()
list.add(" §7- ")
@@ -199,7 +201,7 @@ class GardenVisitorFeatures {
}) { GardenAPI.inGarden() && !NEUItems.neuHasFocus() })
if (config.visitorNeedsShowPrice) {
- val price = NEUItems.getPrice(internalName) * amount
+ val price = internalName.getPrice() * amount
totalPrice += price
val format = NumberUtil.format(price)
list.add(" §7(§6$format§7)")
@@ -277,7 +279,7 @@ class GardenVisitorFeatures {
visitor.hasReward()?.let {
if (config.visitorRewardWarning.preventRefusing) {
- if (KeybindHelper.isKeyDown(config.visitorRewardWarning.bypassKey)) {
+ if (OSUtils.isKeyHeld(config.visitorRewardWarning.bypassKey)) {
LorenzUtils.chat("§e[SkyHanni] §cBypassed blocking refusal of visitor ${visitor.visitorName} §7(${it.displayName}§7)")
return
}
@@ -304,7 +306,7 @@ class GardenVisitorFeatures {
if (event.slot.stack?.getLore()?.any { it == "§eClick to give!" } == true) {
changeStatus(visitor, VisitorStatus.ACCEPTED, "accepted")
update()
- GardenVisitorDropStatistics.coinsSpent += round(price).toLong()
+ GardenVisitorDropStatistics.coinsSpent += round(lastFullPrice).toLong()
GardenVisitorDropStatistics.lastAccept = System.currentTimeMillis()
return
}
@@ -358,7 +360,7 @@ class GardenVisitorFeatures {
if (event.itemStack.name != "§aAccept Offer") return
if (offerCache.isEmpty()) {
- drawToolTip(event.toolTip.listIterator())
+ drawToolTip(event.toolTip)
val temp = event.toolTip.listIterator()
for (line in temp) {
offerCache.add(line)
@@ -372,45 +374,40 @@ class GardenVisitorFeatures {
iterator.add(line)
}
}
-
}
- private fun drawToolTip(iterator: MutableListIterator<String>) {
+ private fun drawToolTip(list: MutableList<String>) {
+
var totalPrice = 0.0
var timeRequired = -1L
- for (line in iterator) {
+ var readingItemsNeeded = true
+ lastFullPrice = 0.0
+
+ for (line in list) {
val formattedLine = line.substring(4)
- val (itemName, amount) = ItemUtils.readItemAmount(formattedLine)
- if (itemName != null) {
- var internalName = NEUItems.getInternalNameOrNull(itemName)
- if (internalName != null) {
- internalName = internalName.replace("◆_", "")
- price = internalName.getPrice() * amount
-
- if (config.visitorShowPrice) {
- val format = NumberUtil.format(price)
- iterator.set("$formattedLine §7(§6$format§7)")
- }
- if (totalPrice == 0.0) {
- totalPrice = price
- val multiplier = NEUItems.getMultiplier(internalName)
- val rawName = multiplier.first.getItemNameOrNull()?.removeColor() ?: continue
- getByNameOrNull(rawName)?.let {
- val cropAmount = multiplier.second.toLong() * amount
- val formattedAmount = LorenzUtils.formatInteger(cropAmount)
- val formattedName = "§e$formattedAmount§7x ${it.cropName} "
- val formattedSpeed = it.getSpeed()?.let { speed ->
- timeRequired = cropAmount / speed
- val duration = TimeUtils.formatDuration(timeRequired * 1000)
- "in §b$duration"
- } ?: "§cno speed data!"
- if (config.visitorExactAmountAndTime) {
- iterator.add("§7- $formattedName($formattedSpeed§7)")
- }
- }
- }
- }
+ if (formattedLine.contains("Rewards")) {
+ readingItemsNeeded = false
+ }
+
+ val (itemName, amount) = ItemUtils.readItemAmount(formattedLine) ?: continue
+ val internalName = NEUItems.getInternalNameOrNull(itemName)?.replace("◆_", "") ?: continue
+ val price = internalName.getPrice() * amount
+
+ if (readingItemsNeeded) {
+ totalPrice += price
+ lastFullPrice += price
+ } else {
+ totalPrice -= price
}
+ }
+ if (totalPrice < 0) {
+ totalPrice = 0.0
+ }
+
+ readingItemsNeeded = true
+ val iterator = list.listIterator()
+ for (line in iterator) {
+ val formattedLine = line.substring(4)
if (config.visitorExperiencePrice) {
gardenExperiencePattern.matchMatcher(formattedLine) {
@@ -431,6 +428,36 @@ class GardenVisitorFeatures {
}
iterator.set(copperLine)
}
+
+ if (formattedLine.contains("Rewards")) {
+ readingItemsNeeded = false
+ }
+
+ val (itemName, amount) = ItemUtils.readItemAmount(formattedLine) ?: continue
+ val internalName = NEUItems.getInternalNameOrNull(itemName)?.replace("◆_", "") ?: continue
+ val price = internalName.getPrice() * amount
+
+ if (config.visitorShowPrice) {
+ val format = NumberUtil.format(price)
+ iterator.set("$formattedLine §7(§6$format§7)")
+ }
+ if (!readingItemsNeeded) continue
+ val multiplier = NEUItems.getMultiplier(internalName)
+
+ val rawName = multiplier.first.getItemNameOrNull()?.removeColor() ?: continue
+ val cropType = getByNameOrNull(rawName) ?: continue
+
+ val cropAmount = multiplier.second.toLong() * amount
+ val formattedAmount = LorenzUtils.formatInteger(cropAmount)
+ val formattedName = "§e$formattedAmount§7x ${cropType.cropName} "
+ val formattedSpeed = cropType.getSpeed()?.let { speed ->
+ timeRequired = cropAmount / speed
+ val duration = TimeUtils.formatDuration(timeRequired * 1000)
+ "in §b$duration"
+ } ?: "§cno speed data!"
+ if (config.visitorExactAmountAndTime) {
+ iterator.add("§7- $formattedName($formattedSpeed§7)")
+ }
}
}
@@ -509,7 +536,7 @@ class GardenVisitorFeatures {
logger.log("New visitor detected: '$name'")
if (config.visitorNotificationTitle && System.currentTimeMillis() > LorenzUtils.lastWorldSwitch + 2_000) {
- TitleUtils.sendTitle("§eNew Visitor", 5_000)
+ TitleUtils.sendTitle("§eNew Visitor", 5.seconds)
}
if (config.visitorNotificationChat) {
val displayName = GardenVisitorColorNames.getColoredName(name)
@@ -658,7 +685,7 @@ class GardenVisitorFeatures {
private fun hasItemsInInventory(visitor: Visitor): Boolean {
var ready = true
for ((internalName, need) in visitor.items) {
- val having = InventoryUtils.countItemsInLowerInventory { it.getInternalName_old() == internalName }
+ val having = InventoryUtils.countItemsInLowerInventory { it.getInternalName() == internalName }
if (having < need) {
ready = false
}
@@ -736,7 +763,7 @@ class GardenVisitorFeatures {
var status: VisitorStatus,
var inSacks: Boolean = false,
var reward: VisitorReward? = null,
- val items: MutableMap<String, Int> = mutableMapOf(),
+ val items: MutableMap<NEUInternalName, Int> = mutableMapOf(),
) {
fun getEntity(): Entity? = Minecraft.getMinecraft().theWorld.getEntityByID(entityId)
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorTimer.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorTimer.kt
index c17ebf721..ce1ee97bc 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorTimer.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorTimer.kt
@@ -13,6 +13,7 @@ import at.hannibal2.skyhanni.utils.TimeUtils
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import kotlin.concurrent.fixedRateTimer
import kotlin.math.roundToLong
+import kotlin.time.Duration.Companion.seconds
class GardenVisitorTimer {
private val config get() = SkyHanniMod.feature.garden
@@ -111,7 +112,7 @@ class GardenVisitorTimer {
if (isSixthVisitorEnabled() && millis < 0) {
visitorsAmount++
if (!sixthVisitorReady) {
- TitleUtils.sendTitle("§a6th Visitor Ready", 5_000)
+ TitleUtils.sendTitle("§a6th Visitor Ready", 5.seconds)
sixthVisitorReady = true
if (isSixthVisitorWarningEnabled()) SoundUtils.playBeepSound()
}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/VisitorReward.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/VisitorReward.kt
index 689bd3110..123faaca7 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/VisitorReward.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/VisitorReward.kt
@@ -9,5 +9,11 @@ enum class VisitorReward(val displayName: String, val internalName: String, val
DEDICATION("§9Dedication IV", "DEDICATION;4", "Dedication (IV|4) Book".toPattern()),
MUSIC_RUNE("§9Music Rune", "MUSIC_RUNE;1", "◆ Music Rune [1I]".toPattern()),
SPACE_HELMET("§cSpace Helmet", "DCTR_SPACE_HELM", "Space Helmet".toPattern()),
+
// Pretty sure that the symbol is ◆ but not 100%
+ CULTIVATING(
+ "§9Cultivating I", "CULTIVATING;1",
+ "Cultivating ([I1]) Book".toPattern()
+ ),
+ REPLENISH("§9Replenish I", "REPLENISH;1", "Replenish ([I1]) Book".toPattern()),
} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/ItemDisplayOverlayFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/ItemDisplayOverlayFeatures.kt
index 029ca979f..bcd6783be 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/inventory/ItemDisplayOverlayFeatures.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/ItemDisplayOverlayFeatures.kt
@@ -19,9 +19,7 @@ import net.minecraft.item.ItemStack
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
class ItemDisplayOverlayFeatures {
-
- private val wishingCompassPattern = "§7Remaining Uses: §e(?<amount>.*)§8/§e3".toPattern()
- private val rangerBootsSpeedCapPattern = "§7Current Speed Cap: §a(?<cap>.*)".toPattern()
+ private val rancherBootsSpeedCapPattern = "§7Current Speed Cap: §a(?<cap>.*)".toPattern()
private val petLevelPattern = "\\[Lvl (?<level>.*)] .*".toPattern()
@SubscribeEvent
@@ -99,19 +97,6 @@ class ItemDisplayOverlayFeatures {
}
}
- if (SkyHanniMod.feature.inventory.itemNumberAsStackSize.contains(7)) {
- if (itemName.contains("Wishing Compass")) {
- for (line in item.getLore()) {
- wishingCompassPattern.matchMatcher(line) {
- val uses = group("amount")
- if (uses != "3") {
- return uses
- }
- }
- }
- }
- }
-
if (SkyHanniMod.feature.inventory.itemNumberAsStackSize.contains(8)) {
if (itemName.contains("Kuudra Key")) {
return when (itemName) {
@@ -155,7 +140,7 @@ class ItemDisplayOverlayFeatures {
if (SkyHanniMod.feature.inventory.itemNumberAsStackSize.contains(11)) {
if (itemName.contains("Rancher's Boots")) {
for (line in item.getLore()) {
- rangerBootsSpeedCapPattern.matchMatcher(line) {
+ rancherBootsSpeedCapPattern.matchMatcher(line) {
return group("cap")
}
}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/SackDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/SackDisplay.kt
index 46f28a9b0..b9cd5fdeb 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/inventory/SackDisplay.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/SackDisplay.kt
@@ -5,7 +5,6 @@ import at.hannibal2.skyhanni.events.GuiRenderEvent
import at.hannibal2.skyhanni.events.InventoryCloseEvent
import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent
import at.hannibal2.skyhanni.features.bazaar.BazaarApi
-import at.hannibal2.skyhanni.features.bazaar.BazaarApi.Companion.getBazaarData
import at.hannibal2.skyhanni.features.fishing.trophy.TrophyFishManager
import at.hannibal2.skyhanni.features.fishing.trophy.TrophyRarity
import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName
@@ -18,6 +17,7 @@ import at.hannibal2.skyhanni.utils.NEUInternalName
import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName
import at.hannibal2.skyhanni.utils.NEUItems
import at.hannibal2.skyhanni.utils.NEUItems.getItemStack
+import at.hannibal2.skyhanni.utils.NEUItems.getNpcPriceOrNull
import at.hannibal2.skyhanni.utils.NEUItems.getPrice
import at.hannibal2.skyhanni.utils.NumberUtil
import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators
@@ -344,7 +344,7 @@ class SackDisplay {
0 -> (getPrice(true) * stored.formatNumber()).toInt().let { if (it < 0) 0 else it }
1 -> try {
- val npcPrice = getBazaarData()?.npcPrice ?: 0.0
+ val npcPrice = getNpcPriceOrNull() ?: 0.0
(npcPrice * stored.formatNumber()).toInt()
} catch (e: Exception) {
0
diff --git a/src/main/java/at/hannibal2/skyhanni/features/itemabilities/abilitycooldown/ItemAbilityCooldown.kt b/src/main/java/at/hannibal2/skyhanni/features/itemabilities/abilitycooldown/ItemAbilityCooldown.kt
index c4e0cbb26..f09e86164 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/itemabilities/abilitycooldown/ItemAbilityCooldown.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/itemabilities/abilitycooldown/ItemAbilityCooldown.kt
@@ -139,7 +139,7 @@ class ItemAbilityCooldown {
}
}
if (event.soundName == "random.drink") {
- if (event.pitch.round(1) == 1.8 && event.volume == 1.0f) {
+ if (event.pitch.round(1) == 1.8f && event.volume == 1.0f) {
ItemAbility.HOLY_ICE.sound()
}
}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/BestiaryData.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/BestiaryData.kt
index 76a46b320..949a326a9 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/misc/BestiaryData.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/BestiaryData.kt
@@ -35,7 +35,6 @@ object BestiaryData {
private val catList = mutableListOf<Category>()
private val progressPattern = "(?<current>[0-9kKmMbB,.]+)/(?<needed>[0-9kKmMbB,.]+$)".toPattern()
private val titlePattern = "^(?:\\(\\d+/\\d+\\) )?(Bestiary|.+) ➜ (.+)$".toPattern()
- private var lastclicked = 0L
private var inInventory = false
private var isCategory = false
private var indexes = listOf(
@@ -65,7 +64,7 @@ object BestiaryData {
for (slot in InventoryUtils.getItemsInOpenChest()) {
val stack = slot.stack
val lore = stack.getLore()
- if (lore.any { it == "§7Overall Progress: §b100% §7(§c§lMAX!§7)" || it == "§7Families Completed: §a100§6% §7(§c§lMAX!§7)" }) {
+ if (lore.any { it == "§7Overall Progress: §b100% §7(§c§lMAX!§7)" || it == "§7Families Completed: §a100%" }) {
slot highlight LorenzColor.GREEN
}
}
@@ -241,16 +240,16 @@ object BestiaryData {
private fun getMobHover(mob: BestiaryMob) = listOf(
"§6Name: §b${mob.name}",
"§6Level: §b${mob.level} ${if (!config.replaceRoman) "§7(${mob.level.romanToDecimalIfNeeded()})" else ""}",
- "§6Total Kills: §b${mob.actualRealTotalKill.addSeparators()}",
- "§6Kills needed to max: §b${mob.killNeededToMax().addSeparators()}",
- "§6Kills needed to next lvl: §b${mob.killNeededToNextLevel().addSeparators()}",
- "§6Current kill to next level: §b${mob.currentKillToNextLevel.addSeparators()}",
- "§6Kill needed for next level: §b${mob.killNeededForNextLevel.addSeparators()}",
- "§6Current kill to max: §b${mob.killToMax.addSeparators()}",
+ "§6Total Kills: §b${mob.actualRealTotalKill.formatNumber()}",
+ "§6Kills needed to max: §b${mob.killNeededToMax().formatNumber()}",
+ "§6Kills needed to next lvl: §b${mob.killNeededToNextLevel().formatNumber()}",
+ "§6Current kill to next level: §b${mob.currentKillToNextLevel.formatNumber()}",
+ "§6Kill needed for next level: §b${mob.killNeededForNextLevel.formatNumber()}",
+ "§6Current kill to max: §b${mob.killToMax.formatNumber()}",
"§6Percent to max: §b${mob.percentToMaxFormatted()}",
"§6Percent to tier: §b${mob.percentToTierFormatted()}",
"",
- "§7More infos thing"
+ "§7More info thing"
)
private fun getMobLine(
@@ -262,7 +261,7 @@ object BestiaryData {
text += " §7- "
text += "${mob.name} ${mob.level.romanOrInt()} "
text += if (isMaxed) {
- "§c§lMAXED! §7(§b${mob.actualRealTotalKill.addSeparators()}§7 kills)"
+ "§c§lMAXED! §7(§b${mob.actualRealTotalKill.formatNumber()}§7 kills)"
} else {
when (displayType) {
0, 1 -> {
@@ -321,7 +320,7 @@ object BestiaryData {
newDisplay.addButton(
prefix = "§7Number Type: ",
- getName = NumberType.entries[if (config.replaceRoman) 1 else 0].type,
+ getName = NumberType.entries[if (config.replaceRoman) 0 else 1].type,
onChange = {
config.replaceRoman = !config.replaceRoman
update()
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/ChatPeek.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/ChatPeek.kt
index 6d3dfdb8f..efc6e3d1e 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/misc/ChatPeek.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/ChatPeek.kt
@@ -2,6 +2,7 @@ package at.hannibal2.skyhanni.features.misc
import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.utils.NEUItems
+import at.hannibal2.skyhanni.utils.OSUtils
import io.github.moulberry.moulconfig.gui.GuiScreenElementWrapper
import net.minecraft.client.Minecraft
import net.minecraft.client.gui.inventory.GuiEditSign
@@ -20,6 +21,6 @@ object ChatPeek {
if (NEUItems.neuHasFocus()) return false
- return Keyboard.isKeyDown(key)
+ return OSUtils.isKeyHeld(key)
}
} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/ChickenHeadTimer.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/ChickenHeadTimer.kt
index 8a7dc645f..3b393b624 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/misc/ChickenHeadTimer.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/ChickenHeadTimer.kt
@@ -50,7 +50,7 @@ class ChickenHeadTimer {
if (!hasChickenHead) return
val sinceLastTime = System.currentTimeMillis() - lastTime
- val cooldown = 20_000
+ val cooldown = 5_000
val remainingTime = cooldown - sinceLastTime
val displayText = if (remainingTime < 0) {
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/EnderNodeTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/EnderNodeTracker.kt
index 62cc85eae..9205b0154 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/misc/EnderNodeTracker.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/EnderNodeTracker.kt
@@ -13,6 +13,7 @@ import at.hannibal2.skyhanni.utils.LorenzUtils
import at.hannibal2.skyhanni.utils.LorenzUtils.addAsSingletonList
import at.hannibal2.skyhanni.utils.LorenzUtils.afterChange
import at.hannibal2.skyhanni.utils.LorenzUtils.editCopy
+import at.hannibal2.skyhanni.utils.NEUItems.getNpcPriceOrNull
import at.hannibal2.skyhanni.utils.NEUItems.getPrice
import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators
import at.hannibal2.skyhanni.utils.NumberUtil.format
@@ -119,12 +120,13 @@ class EnderNodeTracker {
10_000.0
} else {
val internalName = key.internalName
- val bzData = internalName.getBazaarData()
- if (LorenzUtils.noTradeMode) {
- bzData?.npcPrice ?: georgePrice(key) ?: 0.0
+ val npcPrice = internalName.getNpcPriceOrNull()
+ val bazaarData = internalName.getBazaarData()
+ if (LorenzUtils.noTradeMode || bazaarData == null) {
+ npcPrice ?: georgePrice(key) ?: 0.0
} else {
- bzData?.npcPrice
- ?.coerceAtLeast(bzData.sellPrice)
+ npcPrice
+ ?.coerceAtLeast(bazaarData.sellPrice)
?.coerceAtLeast(georgePrice(key) ?: 0.0)
?: internalName.getPrice()
}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/HarpFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/HarpFeatures.kt
index 3c3911f9a..b05908f9d 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/misc/HarpFeatures.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/HarpFeatures.kt
@@ -4,6 +4,7 @@ import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.events.RenderItemTipEvent
import at.hannibal2.skyhanni.utils.InventoryUtils.openInventoryName
import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.OSUtils
import at.hannibal2.skyhanni.utils.SimpleTimeMark
import net.minecraft.client.Minecraft
import net.minecraft.client.gui.inventory.GuiChest
@@ -38,7 +39,7 @@ class HarpFeatures {
val chest = event.gui as? GuiChest ?: return
for (key in keys) {
- if (Keyboard.isKeyDown(key)) {
+ if (OSUtils.isKeyHeld(key)) {
if (lastClick.passedSince() > 200.milliseconds) {
Minecraft.getMinecraft().playerController.windowClick(
chest.inventorySlots.windowId,
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/NonGodPotEffectDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/NonGodPotEffectDisplay.kt
index c0c5e08bc..19d57946a 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/misc/NonGodPotEffectDisplay.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/NonGodPotEffectDisplay.kt
@@ -218,7 +218,6 @@ class NonGodPotEffectDisplay {
)
}
- private fun isEnabled(): Boolean {
- return LorenzUtils.inSkyBlock && config.nonGodPotEffectDisplay && !LorenzUtils.inDungeons && !LorenzUtils.inKuudraFight
- }
+ private fun isEnabled() =
+ LorenzUtils.inSkyBlock && config.nonGodPotEffectDisplay && !LorenzUtils.inDungeons && !LorenzUtils.inKuudraFight
} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/PasteIntoSigns.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/PasteIntoSigns.kt
index ba797ff74..bdddcc3a7 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/misc/PasteIntoSigns.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/PasteIntoSigns.kt
@@ -15,7 +15,7 @@ class PasteIntoSigns {
if (!LorenzUtils.onHypixel) return
if (!SkyHanniMod.feature.misc.pasteIntoSigns) return
- if (LorenzUtils.isControlKeyDown() && Keyboard.isKeyDown(Keyboard.KEY_V)) {
+ if (LorenzUtils.isControlKeyDown() && OSUtils.isKeyHeld(Keyboard.KEY_V)) {
SkyHanniMod.coroutineScope.launch {
OSUtils.readFromClipboard()?.let {
LorenzUtils.setTextIntoSign(it.take(15))
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/PetExpTooltip.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/PetExpTooltip.kt
new file mode 100644
index 000000000..7b54d9d95
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/PetExpTooltip.kt
@@ -0,0 +1,51 @@
+package at.hannibal2.skyhanni.features.misc
+
+import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.utils.ItemUtils
+import at.hannibal2.skyhanni.utils.ItemUtils.name
+import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.LorenzUtils.indexOfFirst
+import at.hannibal2.skyhanni.utils.LorenzUtils.round
+import at.hannibal2.skyhanni.utils.NumberUtil
+import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators
+import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getPetExp
+import at.hannibal2.skyhanni.utils.StringUtils
+import net.minecraftforge.event.entity.player.ItemTooltipEvent
+import net.minecraftforge.fml.common.eventhandler.EventPriority
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+
+class PetExpTooltip {
+ private val config get() = SkyHanniMod.feature.misc.petExperienceToolTip
+
+ @SubscribeEvent(priority = EventPriority.LOWEST)
+ fun onItemTooltipLow(event: ItemTooltipEvent) {
+ if (!LorenzUtils.inSkyBlock) return
+ if (!config.petDisplay) return
+ if (!LorenzUtils.isShiftKeyDown() && !config.showAlways) return
+
+ val itemStack = event.itemStack ?: return
+ val petExperience = itemStack.getPetExp()?.round(1) ?: return
+ val name = itemStack.name ?: return
+
+ val index = event.toolTip.indexOfFirst(
+ "§5§o§7§eClick to summon!",
+ "§5§o§7§cClick to despawn!",
+ "§5§o§7§eRight-click to add this pet to",
+ ) ?: return
+
+ val maxLevel = ItemUtils.maxPetLevel(name)
+ val maxXp = if (maxLevel == 200) 210255385 else 25353230L
+
+ val percentage = petExperience / maxXp
+ val percentageFormat = LorenzUtils.formatPercentage(percentage)
+
+ event.toolTip.add(index, " ")
+ if (percentage >= 1) {
+ event.toolTip.add(index, "§7Total experience: §e${NumberUtil.format(petExperience)}")
+ } else {
+ val progressBar = StringUtils.progressBar(percentage)
+ event.toolTip.add(index, "$progressBar §e${petExperience.addSeparators()}§6/§e${NumberUtil.format(maxXp)}")
+ event.toolTip.add(index, "§7Progress to Level $maxLevel: §e$percentageFormat")
+ }
+ }
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/RealTime.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/RealTime.kt
deleted file mode 100644
index c5bda78c8..000000000
--- a/src/main/java/at/hannibal2/skyhanni/features/misc/RealTime.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-package at.hannibal2.skyhanni.features.misc
-
-import at.hannibal2.skyhanni.SkyHanniMod
-import at.hannibal2.skyhanni.events.GuiRenderEvent
-import at.hannibal2.skyhanni.utils.LorenzUtils
-import at.hannibal2.skyhanni.utils.RenderUtils.renderString
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
-import java.text.SimpleDateFormat
-
-class RealTime {
-
- private val format = SimpleDateFormat("HH:mm:ss")
-
- @SubscribeEvent
- fun onRenderOverlay(event: GuiRenderEvent.GameOverlayRenderEvent) {
- if (!isEnabled()) return
-
- SkyHanniMod.feature.misc.realTimePos.renderString(format.format(System.currentTimeMillis()), posLabel = "Real Time")
- }
-
- private fun isEnabled(): Boolean {
- return LorenzUtils.inSkyBlock && SkyHanniMod.feature.misc.realTime
- }
-} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/ServerRestartTitle.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/ServerRestartTitle.kt
index 2272cdd62..610acc9a2 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/misc/ServerRestartTitle.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/ServerRestartTitle.kt
@@ -8,6 +8,7 @@ import at.hannibal2.skyhanni.utils.LorenzUtils
import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher
import at.hannibal2.skyhanni.utils.TimeUtils
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import kotlin.time.Duration.Companion.seconds
class ServerRestartTitle {
private val config get() = SkyHanniMod.feature.misc
@@ -29,7 +30,7 @@ class ServerRestartTitle {
if (totalSeconds % 30 != 0) return
}
val time = TimeUtils.formatDuration(totalSeconds.toLong() * 1000)
- TitleUtils.sendTitle("§cServer Restart in §b$time", 2_000)
+ TitleUtils.sendTitle("§cServer Restart in §b$time", 2.seconds)
}
}
}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/SuperpairsClicksAlert.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/SuperpairsClicksAlert.kt
new file mode 100644
index 000000000..c8882a1b8
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/SuperpairsClicksAlert.kt
@@ -0,0 +1,60 @@
+package at.hannibal2.skyhanni.features.misc
+
+import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.events.InventoryOpenEvent
+import at.hannibal2.skyhanni.events.InventoryUpdatedEvent
+import at.hannibal2.skyhanni.utils.ItemUtils.getLore
+import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.SoundUtils
+import at.hannibal2.skyhanni.utils.StringUtils.removeColor
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+
+class SuperpairsClicksAlert {
+ private val config get() = SkyHanniMod.feature.misc
+
+ private var roundsNeeded = -1
+ private val roundsNeededRegex = Regex("""(?:Chain|Series) of (\d+):""")
+ private val currentRoundRegex = Regex("""Round: (\d+)""")
+ private val targetInventoryNames = arrayOf("Chronomatron", "Ultrasequencer")
+
+ @SubscribeEvent
+ fun onInventoryOpen(event: InventoryOpenEvent) {
+ if (!config.superpairsClicksAlert) return
+ if (!targetInventoryNames.any { event.inventoryName.contains(it) }) return
+
+ // player may have drank Metaphysical Serum which reduces clicks needed by up to 3, so need to parse it
+ for (i in 24 downTo 20) {
+ val lore = event.inventoryItems[i]?.getLore() ?: continue
+ if (lore.any { it.contains("Practice mode has no rewards") }) {
+ roundsNeeded = -1
+ break
+ }
+ val match = lore.asReversed().firstNotNullOfOrNull { roundsNeededRegex.find(it.removeColor()) } ?: continue
+ roundsNeeded = match.groups[1]!!.value.toInt()
+ break
+ }
+ }
+
+ @SubscribeEvent
+ fun onInventoryUpdate(event: InventoryUpdatedEvent) {
+ if (!config.superpairsClicksAlert) return
+ if (roundsNeeded == -1) return
+ if (!targetInventoryNames.any { event.inventoryName.contains(it) }) return
+
+ if ( // checks if we have succeeded in either minigame
+ (event.inventoryName.contains("Chronomatron")
+ && ((event.inventoryItems[4]?.displayName?.removeColor()
+ ?.let { currentRoundRegex.find(it) }
+ ?.groups?.get(1)?.value?.toInt() ?: -1) > roundsNeeded))
+
+ || (event.inventoryName.contains("Ultrasequencer")
+ && event.inventoryItems.entries
+ .filter { it.key < 45 }
+ .any { it.value.stackSize > roundsNeeded })
+ ) {
+ SoundUtils.playBeepSound()
+ LorenzUtils.chat("§e[SkyHanni] You have reached the maximum possible clicks!")
+ roundsNeeded = -1
+ }
+ }
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/TimeFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/TimeFeatures.kt
new file mode 100644
index 000000000..b8f41204b
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/TimeFeatures.kt
@@ -0,0 +1,46 @@
+package at.hannibal2.skyhanni.features.misc
+
+import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.data.IslandType
+import at.hannibal2.skyhanni.events.GuiRenderEvent
+import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland
+import at.hannibal2.skyhanni.utils.RecalculatingValue
+import at.hannibal2.skyhanni.utils.RenderUtils.renderString
+import at.hannibal2.skyhanni.utils.SimpleTimeMark.Companion.asTimeMark
+import at.hannibal2.skyhanni.utils.TimeUtils.format
+import io.github.moulberry.notenoughupdates.util.SkyBlockTime
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import java.text.SimpleDateFormat
+import kotlin.time.Duration.Companion.days
+import kotlin.time.Duration.Companion.seconds
+
+class TimeFeatures {
+ private val config get() = SkyHanniMod.feature.misc.timeConfigs
+
+ private val format = SimpleDateFormat("HH:mm:ss")
+
+ private val startOfNextYear = RecalculatingValue(1.seconds) {
+ SkyBlockTime(year = SkyBlockTime.now().year + 1).asTimeMark()
+ }
+
+ @SubscribeEvent
+ fun onRenderOverlay(event: GuiRenderEvent.GameOverlayRenderEvent) {
+ if (!LorenzUtils.inSkyBlock) return
+
+ if (config.realTime) {
+ config.realTimePos.renderString(format.format(System.currentTimeMillis()), posLabel = "Real Time")
+ }
+
+ if (config.winterTime && IslandType.WINTER.isInIsland()) {
+ val timeTillNextYear = startOfNextYear.getValue().timeUntil()
+ val alreadyInNextYear = timeTillNextYear > 5.days
+ val text = if (alreadyInNextYear) {
+ "§fJerry's Workshop §cis closing!"
+ } else {
+ "§fJerry's Workshop §ecloses in §b${timeTillNextYear.format()}"
+ }
+ config.winterTimePos.renderString(text, posLabel = "Winter Time")
+ }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/discordrpc/DiscordStatus.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/discordrpc/DiscordStatus.kt
index 5b4102a15..e50a845da 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/misc/discordrpc/DiscordStatus.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/discordrpc/DiscordStatus.kt
@@ -4,9 +4,9 @@ package at.hannibal2.skyhanni.features.misc.discordrpc
import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.data.*
-import at.hannibal2.skyhanni.data.GardenCropMilestones.Companion.getCounter
-import at.hannibal2.skyhanni.data.GardenCropMilestones.Companion.getTierForCrops
-import at.hannibal2.skyhanni.data.GardenCropMilestones.Companion.progressToNextLevel
+import at.hannibal2.skyhanni.data.GardenCropMilestones.getCounter
+import at.hannibal2.skyhanni.data.GardenCropMilestones.getTierForCropCount
+import at.hannibal2.skyhanni.data.GardenCropMilestones.progressToNextLevel
import at.hannibal2.skyhanni.features.garden.GardenAPI.getCropType
import at.hannibal2.skyhanni.features.rift.RiftAPI
import at.hannibal2.skyhanni.utils.InventoryUtils
@@ -264,7 +264,7 @@ enum class DiscordStatus(private val displayMessageSupplier: Supplier<String>?)
CROP_MILESTONES({
val crop = InventoryUtils.getItemInHand()?.getCropType()
val cropCounter = crop?.getCounter()
- val tier = cropCounter?.let { getTierForCrops(it) }
+ val tier = cropCounter?.let { getTierForCropCount(it, crop) }
val progress = tier?.let {
LorenzUtils.formatPercentage(crop.progressToNextLevel())
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValue.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValue.kt
index d6886200e..464b45762 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValue.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValue.kt
@@ -1,6 +1,7 @@
package at.hannibal2.skyhanni.features.misc.items
import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.events.ConfigLoadEvent
import at.hannibal2.skyhanni.events.GuiRenderEvent
import at.hannibal2.skyhanni.events.InventoryCloseEvent
import at.hannibal2.skyhanni.events.RenderItemTooltipEvent
@@ -11,6 +12,7 @@ import at.hannibal2.skyhanni.utils.ItemUtils.getItemName
import at.hannibal2.skyhanni.utils.ItemUtils.getLore
import at.hannibal2.skyhanni.utils.LorenzUtils
import at.hannibal2.skyhanni.utils.LorenzUtils.addAsSingletonList
+import at.hannibal2.skyhanni.utils.LorenzUtils.onToggle
import at.hannibal2.skyhanni.utils.LorenzUtils.sortedDesc
import at.hannibal2.skyhanni.utils.NEUInternalName
import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName
@@ -19,6 +21,7 @@ import at.hannibal2.skyhanni.utils.NEUItems.getPrice
import at.hannibal2.skyhanni.utils.NEUItems.getPriceOrNull
import at.hannibal2.skyhanni.utils.NumberUtil
import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators
+import at.hannibal2.skyhanni.utils.OSUtils
import at.hannibal2.skyhanni.utils.RenderUtils.renderStringsAndItems
import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getAbilityScrolls
import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getArmorDye
@@ -46,7 +49,6 @@ import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.hasWoodSingularity
import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.isRecombobulated
import at.hannibal2.skyhanni.utils.StringUtils.firstLetterUppercase
import at.hannibal2.skyhanni.utils.StringUtils.removeColor
-import io.github.moulberry.moulconfig.internal.KeybindHelper
import io.github.moulberry.notenoughupdates.util.Constants
import net.minecraft.init.Items
import net.minecraft.item.ItemStack
@@ -63,7 +65,7 @@ object EstimatedItemValue {
fun onRenderOverlay(event: GuiRenderEvent.ChestBackgroundRenderEvent) {
if (!LorenzUtils.inSkyBlock) return
if (!config.estimatedIemValueEnabled) return
- if (!KeybindHelper.isKeyDown(config.estimatedItemValueHotkey) && !config.estimatedIemValueAlwaysEnabled) return
+ if (!OSUtils.isKeyHeld(config.estimatedItemValueHotkey) && !config.estimatedIemValueAlwaysEnabled) return
if (System.currentTimeMillis() > lastToolTipTime + 200) return
config.itemPriceDataPos.renderStringsAndItems(display, posLabel = "Estimated Item Value")
@@ -74,6 +76,14 @@ object EstimatedItemValue {
cache.clear()
}
+
+ @SubscribeEvent
+ fun onConfigLoad(event: ConfigLoadEvent) {
+ config.estimatedIemValueEnchantmentsCap.onToggle {
+ cache.clear()
+ }
+ }
+
@SubscribeEvent
fun onRenderItemTooltip(event: RenderItemTooltipEvent) {
if (!LorenzUtils.inSkyBlock) return
@@ -580,13 +590,13 @@ object EstimatedItemValue {
map[" $name §7(§6$format§7)"] = price
}
+ val enchantmentsCap: Int = config.estimatedIemValueEnchantmentsCap.get().toInt()
if (map.isNotEmpty()) {
list.add("§7Enchantments: §6" + NumberUtil.format(totalPrice))
var i = 0
- val size = map.size
for (entry in map.sortedDesc().keys) {
- if (i == 7) {
- val missing = size - i
+ if (i == enchantmentsCap) {
+ val missing = map.size - enchantmentsCap
list.add(" §7§o$missing more enchantments..")
break
}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/Category.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/Category.kt
new file mode 100644
index 000000000..3172df6e0
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/Category.kt
@@ -0,0 +1,3 @@
+package at.hannibal2.skyhanni.features.misc.massconfiguration
+
+data class Category(val name: String, val description: String) \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/DefaultConfigFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/DefaultConfigFeatures.kt
new file mode 100644
index 000000000..ef9bd1e75
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/DefaultConfigFeatures.kt
@@ -0,0 +1,99 @@
+package at.hannibal2.skyhanni.features.misc.massconfiguration
+
+import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.events.LorenzTickEvent
+import at.hannibal2.skyhanni.utils.LorenzUtils
+import io.github.moulberry.moulconfig.processor.ConfigProcessorDriver
+import net.minecraft.client.Minecraft
+import net.minecraft.command.CommandBase
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+
+object DefaultConfigFeatures {
+ private var didNotifyOnce = false
+
+ @SubscribeEvent
+ fun onTick(event: LorenzTickEvent) {
+ if (didNotifyOnce) return
+ Minecraft.getMinecraft().thePlayer ?: return
+ didNotifyOnce = true
+
+ val knownToggles = SkyHanniMod.feature.storage.knownFeatureToggles
+ val updated = SkyHanniMod.version !in knownToggles
+ val processor = FeatureToggleProcessor()
+ ConfigProcessorDriver.processConfig(SkyHanniMod.feature.javaClass, SkyHanniMod.feature, processor)
+ knownToggles[SkyHanniMod.version] = processor.allOptions.map { it.path }
+ SkyHanniMod.configManager.saveConfig("Updated known feature flags")
+ if (!SkyHanniMod.feature.storage.hasPlayedBefore) {
+ SkyHanniMod.feature.storage.hasPlayedBefore = true
+ LorenzUtils.clickableChat(
+ "§e[SkyHanni] Looks like this is the first time you are using SkyHanni. " +
+ "Click here to configure default options, or run /shdefaultoptions.",
+ "shdefaultoptions"
+ )
+ } else if (updated) {
+ val mostFeatureFulOldVersion =
+ knownToggles.maxByOrNull { if (it.key != SkyHanniMod.version) it.value.size else -1 }
+ val command = "/shdefaultoptions ${mostFeatureFulOldVersion?.key} ${SkyHanniMod.version}"
+ LorenzUtils.clickableChat(
+ "§e[SkyHanni] Looks like you updated SkyHanni. " +
+ "Click here to configure the newly introduced options, or run $command.",
+ command
+ )
+ }
+ }
+
+ fun onCommand(old: String, new: String) {
+ val processor = FeatureToggleProcessor()
+ ConfigProcessorDriver.processConfig(SkyHanniMod.feature.javaClass, SkyHanniMod.feature, processor)
+ var optionList = processor.orderedOptions
+ val knownToggles = SkyHanniMod.feature.storage.knownFeatureToggles
+ val togglesInNewVersion = knownToggles[new]
+ if (new != "null" && togglesInNewVersion == null) {
+ LorenzUtils.chat("§e[SkyHanni] Unknown version $new")
+ return
+ }
+ val togglesInOldVersion = knownToggles[old]
+ if (old != "null" && togglesInOldVersion == null) {
+ LorenzUtils.chat("§e[SkyHanni] Unknown version $old")
+ return
+ }
+ optionList = optionList
+ .mapValues { it ->
+ it.value.filter {
+ (togglesInNewVersion == null || it.path in togglesInNewVersion) &&
+ (togglesInOldVersion == null || it.path !in togglesInOldVersion)
+ }
+ }
+ .filter { (_, filteredOptions) -> filteredOptions.isNotEmpty() }
+
+ SkyHanniMod.screenToOpen = DefaultConfigOptionGui(optionList, old, new)
+ }
+
+ fun applyCategorySelections(
+ resetSuggestionState: MutableMap<Category, ResetSuggestionState>,
+ orderedOptions: Map<Category, List<FeatureToggleableOption>>
+ ) {
+ orderedOptions.forEach { (cat, options) ->
+ for (option in options) {
+ val resetState = option.toggleOverride ?: resetSuggestionState[cat]!!
+ if (resetState == ResetSuggestionState.LEAVE_DEFAULTS) continue
+ val onState = option.isTrueEnabled
+ val setTo = if (resetState == ResetSuggestionState.TURN_ALL_ON) {
+ onState
+ } else {
+ !onState
+ }
+ option.setter(setTo)
+ }
+ }
+ }
+
+ fun onComplete(strings: Array<String>): List<String> {
+ if (strings.size <= 2)
+ return CommandBase.getListOfStringsMatchingLastWord(
+ strings,
+ SkyHanniMod.feature.storage.knownFeatureToggles.keys + listOf("null")
+ )
+ return listOf()
+ }
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/DefaultConfigOptionGui.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/DefaultConfigOptionGui.kt
new file mode 100644
index 000000000..ac1a497fe
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/DefaultConfigOptionGui.kt
@@ -0,0 +1,197 @@
+package at.hannibal2.skyhanni.features.misc.massconfiguration
+
+import io.github.moulberry.moulconfig.internal.GlScissorStack
+import io.github.moulberry.moulconfig.internal.RenderUtils
+import io.github.moulberry.moulconfig.internal.TextRenderUtils
+import io.github.moulberry.notenoughupdates.util.Utils
+import net.minecraft.client.gui.GuiScreen
+import net.minecraft.client.gui.ScaledResolution
+import net.minecraft.client.renderer.GlStateManager
+import org.lwjgl.input.Mouse
+import kotlin.math.max
+import kotlin.math.min
+
+class DefaultConfigOptionGui(
+ private val orderedOptions: Map<Category, List<FeatureToggleableOption>>,
+ old: String,
+ new: String
+) :
+ GuiScreen() {
+ val title = if (old == "null") {
+ if (new == "null")
+ "§5SkyHanni Default Options"
+ else
+ "§5SkyHanni Options In Version $new"
+ } else {
+ if (new == "null")
+ "§5SkyHanni Options since $old"
+ else
+ "§5SkyHanni Options $old → $new"
+ }
+
+ private val xSize = 400
+ private val ySize = 300
+ private val barSize = 40
+ private val padding = 10
+ private var wasMouseDown = false
+ private val cardHeight = 30
+
+ private var currentScrollOffset = 0
+
+ private val resetSuggestionState =
+ orderedOptions.keys.associateWith { ResetSuggestionState.LEAVE_DEFAULTS }.toMutableMap()
+
+ override fun drawScreen(mouseX: Int, mouseY: Int, partialTicks: Float) {
+ super.drawScreen(mouseX, mouseY, partialTicks)
+ drawDefaultBackground()
+ RenderUtils.drawFloatingRectDark((width - xSize) / 2, (height - ySize) / 2, xSize, ySize)
+ val scaledResolution = ScaledResolution(mc)
+ var hoveringTextToDraw: List<String>? = null
+ val x = mouseX - ((width - xSize) / 2) - padding
+ val isMouseDown = Mouse.isButtonDown(0)
+ val shouldClick = isMouseDown && !wasMouseDown
+ wasMouseDown = isMouseDown
+ val isMouseInScrollArea =
+ x in 0..xSize && mouseY in ((height - ySize) / 2) + barSize..((height + ySize) / 2 - barSize)
+ var y = mouseY - ((height - ySize) / 2 + barSize) + currentScrollOffset
+
+ GlStateManager.pushMatrix()
+ GlStateManager.translate(width / 2F, (height - ySize) / 2F, 0F)
+ GlStateManager.scale(2f, 2f, 1f)
+ TextRenderUtils.drawStringCenteredScaledMaxWidth(
+ title,
+ mc.fontRendererObj,
+ 0F,
+ mc.fontRendererObj.FONT_HEIGHT.toFloat(),
+ false,
+ xSize / 2 - padding,
+ -1
+ )
+ GlStateManager.popMatrix()
+
+ GlStateManager.pushMatrix()
+ GlStateManager.translate(
+ (width - xSize) / 2F + padding,
+ (height + ySize) / 2F - mc.fontRendererObj.FONT_HEIGHT * 2,
+ 0F
+ )
+ var i = 0
+ fun button(title: String, tooltip: List<String>, func: () -> Unit) {
+ val width = mc.fontRendererObj.getStringWidth(title)
+ var overMouse = false
+ if (mouseX - ((this.width - xSize) / 2 + padding) in i..(i + width)
+ && mouseY - (height + ySize) / 2 in -barSize..0
+ ) {
+ overMouse = true
+ hoveringTextToDraw = tooltip
+ if (shouldClick) {
+ func()
+ }
+ }
+ RenderUtils.drawFloatingRectDark(i - 1, -3, width + 4, 14)
+ mc.fontRendererObj.drawString(
+ title,
+ 2 + i.toFloat(),
+ 0F,
+ if (overMouse) 0xFF00FF00.toInt() else -1,
+ overMouse
+ )
+ i += width + 12
+ }
+ button("Apply choices", listOf()) {
+ DefaultConfigFeatures.applyCategorySelections(resetSuggestionState, orderedOptions)
+ mc.displayGuiScreen(null)
+ }
+ button("Turn all on", listOf()) {
+ resetSuggestionState.entries.forEach { entry ->
+ entry.setValue(ResetSuggestionState.TURN_ALL_ON)
+ orderedOptions[entry.key]!!.forEach { it.toggleOverride = null }
+ }
+ }
+ button("Turn all off", listOf()) {
+ resetSuggestionState.entries.forEach { entry ->
+ entry.setValue(ResetSuggestionState.TURN_ALL_OFF)
+ orderedOptions[entry.key]!!.forEach { it.toggleOverride = null }
+ }
+ }
+ button("Leave all untouched", listOf()) {
+ resetSuggestionState.entries.forEach { entry ->
+ entry.setValue(ResetSuggestionState.LEAVE_DEFAULTS)
+ orderedOptions[entry.key]!!.forEach { it.toggleOverride = null }
+ }
+ }
+ button("Cancel", listOf()) {
+ mc.displayGuiScreen(null)
+ }
+ GlStateManager.popMatrix()
+
+ GlStateManager.pushMatrix()
+ GlScissorStack.push(
+ (width - xSize) / 2,
+ (height - ySize) / 2 + barSize,
+ (width + xSize) / 2,
+ (height + ySize) / 2 - barSize,
+ scaledResolution
+ )
+ GlStateManager.translate(
+ (width - xSize) / 2F + padding,
+ (height - ySize) / 2F + barSize - currentScrollOffset,
+ 0F
+ )
+
+ for ((cat) in orderedOptions.entries) {
+ val suggestionState = resetSuggestionState[cat]!!
+
+ drawRect(0, 0, xSize - padding * 2, 1, 0xFF808080.toInt())
+ drawRect(0, 30, xSize - padding * 2, cardHeight + 1, 0xFF808080.toInt())
+ drawRect(0, 0, 1, cardHeight, 0xFF808080.toInt())
+ drawRect(xSize - padding * 2 - 1, 0, xSize - padding * 2, cardHeight, 0xFF808080.toInt())
+
+ mc.fontRendererObj.drawString("§e${cat.name} ${suggestionState.label}", 4, 4, -1)
+ mc.fontRendererObj.drawSplitString("§7${cat.description}", 4, 14, xSize - padding * 2 - 8, -1)
+
+ if (isMouseInScrollArea && y in 0..cardHeight) {
+ hoveringTextToDraw = listOf(
+ "§e${cat.name}",
+ "§7${cat.description}",
+ "§7Current plan: ${suggestionState.label}",
+ "§aClick to toggle!",
+ "§7Hold shift to show all options"
+ )
+
+ if (isShiftKeyDown()) {
+ hoveringTextToDraw = listOf(
+ "§e${cat.name}",
+ "§7${cat.description}"
+ ) + orderedOptions[cat]!!.map { "§7 - §a" + it.name }
+ }
+
+ if (shouldClick) {
+ resetSuggestionState[cat] = suggestionState.next
+ orderedOptions[cat]!!.forEach { it.toggleOverride = null }
+ }
+ }
+
+ y -= cardHeight
+ GlStateManager.translate(0F, cardHeight.toFloat(), 0F)
+ }
+
+ GlStateManager.popMatrix()
+ GlScissorStack.pop(scaledResolution)
+ if (hoveringTextToDraw != null) {
+ Utils.drawHoveringText(hoveringTextToDraw, mouseX, mouseY, width, height, 100, mc.fontRendererObj)
+ }
+
+ }
+
+ private fun scroll(s: Int) {
+ currentScrollOffset =
+ max(0, min(s, (orderedOptions.size + 1) * cardHeight - ySize + barSize + padding * 2))
+ }
+
+ override fun handleMouseInput() {
+ super.handleMouseInput()
+ if (Mouse.getEventDWheel() != 0)
+ scroll(currentScrollOffset - Mouse.getEventDWheel())
+ }
+} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/FeatureToggleProcessor.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/FeatureToggleProcessor.kt
new file mode 100644
index 000000000..fc8c4bd92
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/FeatureToggleProcessor.kt
@@ -0,0 +1,81 @@
+package at.hannibal2.skyhanni.features.misc.massconfiguration
+
+import at.hannibal2.skyhanni.config.FeatureToggle
+import io.github.moulberry.moulconfig.annotations.ConfigEditorBoolean
+import io.github.moulberry.moulconfig.annotations.ConfigOption
+import io.github.moulberry.moulconfig.observer.Property
+import io.github.moulberry.moulconfig.processor.ConfigStructureReader
+import java.lang.reflect.Field
+import java.lang.reflect.ParameterizedType
+import java.util.*
+
+class FeatureToggleProcessor : ConfigStructureReader {
+
+ var latestCategory: Category? = null
+ val pathStack = Stack<String>()
+
+ val allOptions = mutableListOf<FeatureToggleableOption>()
+ val orderedOptions by lazy {
+ allOptions.groupBy { it.category }
+ }
+
+ override fun beginCategory(baseObject: Any?, field: Field?, name: String, description: String) {
+ latestCategory = Category(name, description)
+ }
+
+ override fun endCategory() {
+ }
+
+ override fun beginAccordion(baseObject: Any?, field: Field?, option: ConfigOption?, id: Int) {
+ }
+
+ override fun endAccordion() {
+ }
+
+ override fun pushPath(fieldPath: String) {
+ pathStack.push(fieldPath)
+ }
+
+ override fun popPath() {
+ pathStack.pop()
+ }
+
+ override fun emitOption(baseObject: Any, field: Field, option: ConfigOption) {
+ val featureToggle = field.getAnnotation(FeatureToggle::class.java) ?: return
+ field.getAnnotation(ConfigEditorBoolean::class.java)
+ ?: error("Feature toggle found without ConfigEditorBoolean: $field")
+ val setter: (Boolean) -> Unit
+ val value: Boolean
+ when (field.type) {
+ java.lang.Boolean.TYPE -> {
+ setter = { field.setBoolean(baseObject, it) }
+ value = field.getBoolean(baseObject)
+ }
+
+ Property::class.java -> {
+ val genericType = field.genericType
+ require(genericType is ParameterizedType)
+ require((genericType.actualTypeArguments[0] as Class<*>) == (java.lang.Boolean::class.java))
+ val prop = field.get(baseObject) as Property<Boolean>
+ setter = { prop.set(it) }
+ value = prop.get()
+ }
+
+ else -> error("Invalid FeatureToggle type: $field")
+ }
+ allOptions.add(
+ FeatureToggleableOption(
+ option.name,
+ option.desc,
+ value,
+ featureToggle.trueIsEnabled,
+ latestCategory!!,
+ setter,
+ pathStack.joinToString(".") + "." + field.name
+ )
+ )
+ }
+
+ override fun emitGuiOverlay(baseObject: Any?, field: Field?, option: ConfigOption?) {
+ }
+} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/FeatureToggleableOption.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/FeatureToggleableOption.kt
new file mode 100644
index 000000000..88b9f1a8e
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/FeatureToggleableOption.kt
@@ -0,0 +1,9 @@
+package at.hannibal2.skyhanni.features.misc.massconfiguration
+
+data class FeatureToggleableOption(
+ val name: String, val description: String, val previouslyEnabled: Boolean,
+ val isTrueEnabled: Boolean, val category: Category,
+ val setter: (Boolean) -> Unit,
+ val path: String,
+ var toggleOverride: ResetSuggestionState? = null
+) \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/ResetSuggestionState.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/ResetSuggestionState.kt
new file mode 100644
index 000000000..30a78a7b2
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/ResetSuggestionState.kt
@@ -0,0 +1,10 @@
+package at.hannibal2.skyhanni.features.misc.massconfiguration
+
+enum class ResetSuggestionState(val label: String) {
+ TURN_ALL_OFF("§c§lTurn all off"),
+ TURN_ALL_ON("§a§lTurn all on"),
+ LEAVE_DEFAULTS("§b§lLeave unchanged"),
+ ;
+
+ val next get() = entries[(ordinal + 1) % entries.size]
+} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/trevor/TrevorFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/trevor/TrevorFeatures.kt
index 11c0504d8..c1b4ee3fc 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/misc/trevor/TrevorFeatures.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/trevor/TrevorFeatures.kt
@@ -26,6 +26,7 @@ import net.minecraftforge.fml.common.eventhandler.EventPriority
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import org.lwjgl.input.Keyboard
import kotlin.concurrent.fixedRateTimer
+import kotlin.time.Duration.Companion.seconds
class TrevorFeatures {
@@ -69,7 +70,7 @@ class TrevorFeatures {
if (event.message == "§aReturn to the Trapper soon to get a new animal to hunt!") {
TrevorSolver.resetLocation()
if (config.trapperMobDiedMessage) {
- TitleUtils.sendTitle("§2Mob Died ", 5_000)
+ TitleUtils.sendTitle("§2Mob Died ", 5.seconds)
SoundUtils.playBeepSound()
}
trapperReady = true
@@ -114,7 +115,7 @@ class TrevorFeatures {
if (timeUntilNextReady <= 0 && trapperReady) {
if (timeUntilNextReady == 0) {
- TitleUtils.sendTitle("§2Trapper Ready", 3_000)
+ TitleUtils.sendTitle("§2Trapper Ready", 3.seconds)
SoundUtils.playBeepSound()
}
currentStatus = TrapperStatus.READY
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/trevor/TrevorSolver.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/trevor/TrevorSolver.kt
index 0ef03688e..475a9fda1 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/misc/trevor/TrevorSolver.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/trevor/TrevorSolver.kt
@@ -6,6 +6,7 @@ import at.hannibal2.skyhanni.utils.EntityUtils.hasMaxHealth
import at.hannibal2.skyhanni.utils.LocationUtils
import at.hannibal2.skyhanni.utils.LocationUtils.distanceToPlayer
import at.hannibal2.skyhanni.utils.LorenzUtils.baseMaxHealth
+import at.hannibal2.skyhanni.utils.LorenzUtils.derpy
import at.hannibal2.skyhanni.utils.LorenzVec
import at.hannibal2.skyhanni.utils.toLorenzVec
import net.minecraft.client.Minecraft
@@ -13,6 +14,7 @@ import net.minecraft.client.entity.EntityOtherPlayerMP
import net.minecraft.entity.EntityLivingBase
import net.minecraft.entity.item.EntityArmorStand
import net.minecraft.entity.passive.EntityChicken
+import kotlin.time.Duration.Companion.seconds
object TrevorSolver {
private val animalHealths = intArrayOf(100, 200, 400, 500, 1000, 2000, 5000, 10000, 20000) //future proofing for Derpy :)
@@ -51,7 +53,7 @@ object TrevorSolver {
for (entity in EntityUtils.getAllEntities()) {
if (entity is EntityOtherPlayerMP) continue
val name = entity.name
- val entityHealth = if (entity is EntityLivingBase) entity.baseMaxHealth else 0
+ val entityHealth = if (entity is EntityLivingBase) entity.baseMaxHealth.derpy() else 0
currentMob = TrevorMobs.entries.firstOrNull { it.mobName.contains(name) }
if (currentMob == TrevorMobs.CHICKEN) {
if (entity is EntityChicken) {
@@ -78,7 +80,7 @@ object TrevorSolver {
}
if (canSee) {
if (mobLocation != CurrentMobArea.FOUND) {
- TitleUtils.sendTitle("§2Saw Mob!", 3_000)
+ TitleUtils.sendTitle("§2Saw Mob!", 3.seconds)
}
mobLocation = CurrentMobArea.FOUND
mobCoordinates = entity.position.toLorenzVec()
diff --git a/src/main/java/at/hannibal2/skyhanni/features/mobs/MobHighlight.kt b/src/main/java/at/hannibal2/skyhanni/features/mobs/MobHighlight.kt
index accf478bd..a50479f6b 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/mobs/MobHighlight.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/mobs/MobHighlight.kt
@@ -56,7 +56,9 @@ class MobHighlight {
}
if (config.zealotBruiserHighlighter) {
- if ((maxHealth == 65_000 || maxHealth == 13_000) && entity is EntityEnderman) {
+ val isZealot = maxHealth == 13_000 || maxHealth == 13_000 * 3 // runic
+ val isBruiser = maxHealth == 65_000 || maxHealth == 65_000 * 3 // runic
+ if ((isZealot || isBruiser) && entity is EntityEnderman) {
RenderLivingEntityHelper.setEntityColor(entity, LorenzColor.DARK_AQUA.toColor().withAlpha(127))
{ config.zealotBruiserHighlighter }
RenderLivingEntityHelper.setNoHurtTime(entity) { config.zealotBruiserHighlighter }
@@ -86,7 +88,7 @@ class MobHighlight {
) return
val maxHealth = entity.baseMaxHealth
- if (maxHealth == 12 || maxHealth == 4000 || maxHealth == 20000) {
+ if (maxHealth == 12 || maxHealth == 4000) {
markArachneMinis(entity)
} else {
markArachne(entity)
diff --git a/src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/CrimsonIsleReputationHelper.kt b/src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/CrimsonIsleReputationHelper.kt
index 2efc657bf..cb5006aa7 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/CrimsonIsleReputationHelper.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/CrimsonIsleReputationHelper.kt
@@ -13,12 +13,12 @@ import at.hannibal2.skyhanni.features.nether.reputationhelper.miniboss.DailyMini
import at.hannibal2.skyhanni.utils.LorenzUtils
import at.hannibal2.skyhanni.utils.LorenzUtils.addAsSingletonList
import at.hannibal2.skyhanni.utils.LorenzVec
+import at.hannibal2.skyhanni.utils.OSUtils
import at.hannibal2.skyhanni.utils.RenderUtils.renderStringsAndItems
import at.hannibal2.skyhanni.utils.TabListData
import com.google.gson.JsonObject
import net.minecraftforge.fml.common.eventhandler.EventPriority
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
-import org.lwjgl.input.Keyboard
class CrimsonIsleReputationHelper(skyHanniMod: SkyHanniMod) {
val config get() = SkyHanniMod.feature.misc
@@ -112,7 +112,7 @@ class CrimsonIsleReputationHelper(skyHanniMod: SkyHanniMod) {
if (LorenzUtils.skyBlockIsland != IslandType.CRIMSON_ISLE) return
if (config.reputationHelperUseHotkey) {
- if (!Keyboard.isKeyDown(config.reputationHelperHotkey)) {
+ if (!OSUtils.isKeyHeld(config.reputationHelperHotkey)) {
return
}
}
@@ -151,4 +151,10 @@ class CrimsonIsleReputationHelper(skyHanniMod: SkyHanniMod) {
val z = locationData[2].asDouble - 1
return LorenzVec(x, y, z)
}
+
+ fun showLocations() = when (config.crimsonIsleReputationShowLocation) {
+ 0 -> true
+ 1 -> OSUtils.isKeyHeld(config.reputationHelperHotkey)
+ else -> false
+ }
} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/dailykuudra/DailyKuudraBossHelper.kt b/src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/dailykuudra/DailyKuudraBossHelper.kt
index 597de55e4..bab45b0a9 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/dailykuudra/DailyKuudraBossHelper.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/dailykuudra/DailyKuudraBossHelper.kt
@@ -27,7 +27,7 @@ class DailyKuudraBossHelper(private val reputationHelper: CrimsonIsleReputationH
if (!LorenzUtils.inSkyBlock) return
if (LorenzUtils.skyBlockIsland != IslandType.CRIMSON_ISLE) return
if (!SkyHanniMod.feature.misc.crimsonIsleReputationHelper) return
- if (!SkyHanniMod.feature.misc.crimsonIsleReputationLocation) return
+ if (!reputationHelper.showLocations()) return
if (allKuudraDone) return
kuudraLocation?.let {
diff --git a/src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/dailyquest/DailyQuestHelper.kt b/src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/dailyquest/DailyQuestHelper.kt
index 827ed137a..14e5b131a 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/dailyquest/DailyQuestHelper.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/dailyquest/DailyQuestHelper.kt
@@ -179,7 +179,7 @@ class DailyQuestHelper(val reputationHelper: CrimsonIsleReputationHelper) {
@SubscribeEvent
fun onRenderWorld(event: RenderWorldLastEvent) {
if (!isEnabled()) return
- if (!SkyHanniMod.feature.misc.crimsonIsleReputationLocation) return
+ if (!reputationHelper.showLocations()) return
for (quest in quests) {
if (quest is MiniBossQuest) continue
diff --git a/src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/miniboss/DailyMiniBossHelper.kt b/src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/miniboss/DailyMiniBossHelper.kt
index ad9032d43..982551549 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/miniboss/DailyMiniBossHelper.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/miniboss/DailyMiniBossHelper.kt
@@ -42,7 +42,7 @@ class DailyMiniBossHelper(private val reputationHelper: CrimsonIsleReputationHel
if (!LorenzUtils.inSkyBlock) return
if (LorenzUtils.skyBlockIsland != IslandType.CRIMSON_ISLE) return
if (!SkyHanniMod.feature.misc.crimsonIsleReputationHelper) return
- if (!SkyHanniMod.feature.misc.crimsonIsleReputationLocation) return
+ if (!reputationHelper.showLocations()) return
val playerLocation = LocationUtils.playerLocation()
for (miniBoss in miniBosses) {
diff --git a/src/main/java/at/hannibal2/skyhanni/features/rift/area/dreadfarm/VoltHighlighter.kt b/src/main/java/at/hannibal2/skyhanni/features/rift/area/dreadfarm/VoltHighlighter.kt
index 38c9ceb7c..bef442c31 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/rift/area/dreadfarm/VoltHighlighter.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/rift/area/dreadfarm/VoltHighlighter.kt
@@ -11,7 +11,7 @@ import at.hannibal2.skyhanni.utils.RenderUtils.drawDynamicText
import at.hannibal2.skyhanni.utils.RenderUtils.exactLocation
import at.hannibal2.skyhanni.utils.SimpleTimeMark
import at.hannibal2.skyhanni.utils.SpecialColour
-import at.hannibal2.skyhanni.utils.TimeUtils
+import at.hannibal2.skyhanni.utils.TimeUtils.format
import net.minecraft.client.Minecraft
import net.minecraft.entity.Entity
import net.minecraft.entity.EntityLivingBase
@@ -76,7 +76,7 @@ class VoltHighlighter {
if (dischargeTimeLeft > Duration.ZERO) {
event.drawDynamicText(
event.exactLocation(entity).add(0.0, 2.5, 0.0),
- "§eLightning: ${TimeUtils.formatDuration(dischargeTimeLeft, showMilliSeconds = true)}",
+ "§eLightning: ${dischargeTimeLeft.format(showMilliSeconds = true)}",
2.5
)
}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/rift/area/wyldwoods/ShyCruxWarnings.kt b/src/main/java/at/hannibal2/skyhanni/features/rift/area/wyldwoods/ShyCruxWarnings.kt
index ad38e3cfe..84808625a 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/rift/area/wyldwoods/ShyCruxWarnings.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/rift/area/wyldwoods/ShyCruxWarnings.kt
@@ -6,6 +6,7 @@ import at.hannibal2.skyhanni.features.rift.RiftAPI
import at.hannibal2.skyhanni.utils.EntityUtils
import at.hannibal2.skyhanni.utils.LocationUtils.distanceToPlayer
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import kotlin.time.Duration.Companion.milliseconds
class ShyCruxWarnings {
private val config get() = RiftAPI.config.area.wyldWoodsConfig
@@ -21,7 +22,7 @@ class ShyCruxWarnings {
private fun checkForShy() {
if (EntityUtils.getAllEntities().any { it.name in shyNames && it.distanceToPlayer() < 8 }) {
- TitleUtils.sendTitle("§eLook away!", 150)
+ TitleUtils.sendTitle("§eLook away!", 150.milliseconds)
}
}
} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/features/rift/everywhere/motes/ShowMotesNpcSellPrice.kt b/src/main/java/at/hannibal2/skyhanni/features/rift/everywhere/motes/ShowMotesNpcSellPrice.kt
index 9e06b5015..5ef9abe44 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/rift/everywhere/motes/ShowMotesNpcSellPrice.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/rift/everywhere/motes/ShowMotesNpcSellPrice.kt
@@ -3,14 +3,11 @@ package at.hannibal2.skyhanni.features.rift.everywhere.motes
import at.hannibal2.skyhanni.events.*
import at.hannibal2.skyhanni.features.rift.RiftAPI
import at.hannibal2.skyhanni.features.rift.RiftAPI.motesNpcPrice
-import at.hannibal2.skyhanni.utils.InventoryUtils
+import at.hannibal2.skyhanni.utils.*
import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName_old
-import at.hannibal2.skyhanni.utils.LorenzColor
import at.hannibal2.skyhanni.utils.LorenzUtils.addAsSingletonList
import at.hannibal2.skyhanni.utils.LorenzUtils.addSelector
import at.hannibal2.skyhanni.utils.LorenzUtils.chat
-import at.hannibal2.skyhanni.utils.NEUItems
-import at.hannibal2.skyhanni.utils.NumberUtil
import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators
import at.hannibal2.skyhanni.utils.RenderUtils.highlight
import at.hannibal2.skyhanni.utils.RenderUtils.renderStringsAndItems
@@ -19,6 +16,7 @@ import at.hannibal2.skyhanni.utils.renderables.Renderable
import net.minecraftforge.event.entity.player.ItemTooltipEvent
import net.minecraftforge.fml.common.eventhandler.EventPriority
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import java.awt.Color
class ShowMotesNpcSellPrice {
private val config get() = RiftAPI.config.motes
@@ -52,9 +50,12 @@ class ShowMotesNpcSellPrice {
if (!isInventoryValueEnabled()) return
val name = InventoryUtils.openInventoryName()
if (!name.contains("Rift Storage")) return
- for (slot in InventoryUtils.getItemsInOpenChest()) {
- if (slotList.contains(slot.slotIndex))
- slot highlight LorenzColor.GREEN
+ for ((_, indexes) in Renderable.list) {
+ for (slot in InventoryUtils.getItemsInOpenChest()) {
+ if (indexes.contains(slot.slotIndex)) {
+ slot highlight LorenzColor.GREEN
+ }
+ }
}
}
@@ -90,6 +91,7 @@ class ShowMotesNpcSellPrice {
itemMap.clear()
slotList.clear()
inInventory = false
+ Renderable.list.clear()
}
private fun processItems() {
@@ -132,28 +134,19 @@ class ShowMotesNpcSellPrice {
for ((internalName, pair) in sorted) {
newDisplay.add(buildList {
val (index, value) = pair
- val dashColor = if (slotList.containsAll(index)) "§a" else "§7"
- add(" $dashColor- ")
+ add(" §7- ")
val stack = NEUItems.getItemStack(internalName)
add(stack)
val price = value.formatPrice()
val valuePer = stack.motesNpcPrice() ?: continue
val tips = buildList {
- add("§eClick to highlight in the chest !")
+ add("§6Item: ${stack.displayName}")
add("§6Value per: §d$valuePer Motes")
add("§6Total in chest: §d${(value / valuePer).toInt()}")
+ add("")
+ add("§6Total value: §d$price")
}
- add(Renderable.clickAndHover("§6${stack.displayName}: §b$price", tips) {
- for (slot in InventoryUtils.getItemsInOpenChest()) {
- if (index.contains(slot.slotIndex)) {
- if (slotList.contains(slot.slotIndex)) {
- slotList.remove(slot.slotIndex)
- } else {
- slotList.add(slot.slotIndex)
- }
- }
- }
- })
+ add(Renderable.hoverTips("§6${stack.displayName}: §b$price", tips, indexes = index, stack = stack))
})
}
val total = itemMap.values.fold(0.0) { acc, pair -> acc + pair.second }.formatPrice()
diff --git a/src/main/java/at/hannibal2/skyhanni/features/slayer/HighlightSlayerMiniBoss.kt b/src/main/java/at/hannibal2/skyhanni/features/slayer/HighlightSlayerMiniBoss.kt
deleted file mode 100644
index 8c6399dde..000000000
--- a/src/main/java/at/hannibal2/skyhanni/features/slayer/HighlightSlayerMiniBoss.kt
+++ /dev/null
@@ -1,52 +0,0 @@
-package at.hannibal2.skyhanni.features.slayer
-
-import at.hannibal2.skyhanni.SkyHanniMod
-import at.hannibal2.skyhanni.events.EntityMaxHealthUpdateEvent
-import at.hannibal2.skyhanni.events.withAlpha
-import at.hannibal2.skyhanni.features.damageindicator.DamageIndicatorManager
-import at.hannibal2.skyhanni.mixins.hooks.RenderLivingEntityHelper
-import at.hannibal2.skyhanni.utils.EntityUtils.hasMaxHealth
-import at.hannibal2.skyhanni.utils.LorenzColor
-import at.hannibal2.skyhanni.utils.LorenzUtils
-import net.minecraft.entity.EntityCreature
-import net.minecraft.entity.monster.EntityBlaze
-import net.minecraft.entity.monster.EntityEnderman
-import net.minecraft.entity.monster.EntitySpider
-import net.minecraft.entity.monster.EntityZombie
-import net.minecraft.entity.passive.EntityWolf
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
-
-class HighlightSlayerMiniBoss {
-
- @SubscribeEvent
- fun onEntityHealthUpdate(event: EntityMaxHealthUpdateEvent) {
- if (!isEnabled()) return
-
- val entity = event.entity
- if (DamageIndicatorManager.isBoss(entity)) return
-
- val maxHealth = event.maxHealth
- for (bossType in SlayerMiniBossType.entries) {
- if (!bossType.clazz.isInstance(entity)) continue
-
- if (bossType.health.any { entity.hasMaxHealth(it, false, maxHealth) }) {
- RenderLivingEntityHelper.setEntityColor(entity, LorenzColor.AQUA.toColor().withAlpha(127))
- { SkyHanniMod.feature.slayer.slayerMinibossHighlight }
- RenderLivingEntityHelper.setNoHurtTime(entity) { SkyHanniMod.feature.slayer.slayerMinibossHighlight }
- }
- }
- }
-
- private fun isEnabled() = LorenzUtils.inSkyBlock &&
- SkyHanniMod.feature.slayer.slayerMinibossHighlight &&
- !LorenzUtils.inDungeons && !LorenzUtils.inKuudraFight
-
- enum class SlayerMiniBossType(val clazz: Class<out EntityCreature>, vararg val health: Int) {
- REVENANT(EntityZombie::class.java, 24_000, 90_000, 360_000, 600_000, 2_400_000),
- TARANTULA(EntitySpider::class.java, 54_000, 144_000, 576_000),
- SVEN(EntityWolf::class.java, 45_000, 120_000, 480_000),
- VOIDLING(EntityEnderman::class.java, 8_400_000, 17_500_000, 52_500_000),
- INFERNAL(EntityBlaze::class.java, 12_000_000, 25_000_000),
- ;
- }
-}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerBossSpawnSoon.kt b/src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerBossSpawnSoon.kt
index 0ab6eb997..1d8dd0698 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerBossSpawnSoon.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerBossSpawnSoon.kt
@@ -9,6 +9,7 @@ import at.hannibal2.skyhanni.utils.SoundUtils
import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher
import at.hannibal2.skyhanni.utils.StringUtils.removeColor
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import kotlin.time.Duration.Companion.seconds
class SlayerBossSpawnSoon {
@@ -28,7 +29,7 @@ class SlayerBossSpawnSoon {
if (completion > config.percent / 100.0) {
if (!warned || (config.repeat && completion != lastCompletion)) {
SoundUtils.playBeepSound()
- TitleUtils.sendTitle("§cSlayer boss soon!", 2_000)
+ TitleUtils.sendTitle("§cSlayer boss soon!", 2.seconds)
warned = true
}
} else {
diff --git a/src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerItemProfitTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerItemProfitTracker.kt
index e5f846252..8130526f4 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerItemProfitTracker.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerItemProfitTracker.kt
@@ -15,6 +15,7 @@ import at.hannibal2.skyhanni.utils.ItemUtils.name
import at.hannibal2.skyhanni.utils.LorenzUtils.addAsSingletonList
import at.hannibal2.skyhanni.utils.LorenzUtils.addSelector
import at.hannibal2.skyhanni.utils.LorenzUtils.sortedDesc
+import at.hannibal2.skyhanni.utils.NEUItems.getNpcPrice
import at.hannibal2.skyhanni.utils.NEUItems.getPrice
import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators
import at.hannibal2.skyhanni.utils.RenderUtils.renderStringsAndItems
@@ -28,6 +29,7 @@ import net.minecraft.network.play.server.S0DPacketCollectItem
import net.minecraftforge.fml.common.eventhandler.EventPriority
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import java.util.concurrent.TimeUnit
+import kotlin.time.Duration.Companion.seconds
object SlayerItemProfitTracker {
private val config get() = SkyHanniMod.feature.slayer.itemProfitTracker
@@ -147,7 +149,7 @@ object SlayerItemProfitTracker {
}
if (config.titleWarning) {
if (price > config.minimumPriceWarning) {
- TitleUtils.sendTitle("§a+ $itemName", 5_000)
+ TitleUtils.sendTitle("§a+ $itemName", 5.seconds)
}
}
}
@@ -299,13 +301,13 @@ object SlayerItemProfitTracker {
}
private fun getPrice(internalName: NEUInternalName) =
- internalName.getBazaarData()?.let { getPrice(it) } ?: internalName.getPrice()
+ internalName.getBazaarData()?.let { getPrice(internalName, it) } ?: internalName.getPrice()
- private fun getPrice(bazaarData: BazaarData) = when (config.priceFrom) {
+ private fun getPrice(internalName: NEUInternalName, bazaarData: BazaarData) = when (config.priceFrom) {
0 -> bazaarData.sellPrice
1 -> bazaarData.buyPrice
- else -> bazaarData.npcPrice
+ else -> internalName.getNpcPrice()
}
@SubscribeEvent
diff --git a/src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerMiniBossFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerMiniBossFeatures.kt
new file mode 100644
index 000000000..c03e47146
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerMiniBossFeatures.kt
@@ -0,0 +1,81 @@
+package at.hannibal2.skyhanni.features.slayer
+
+import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.events.EntityMaxHealthUpdateEvent
+import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent
+import at.hannibal2.skyhanni.events.withAlpha
+import at.hannibal2.skyhanni.features.damageindicator.DamageIndicatorManager
+import at.hannibal2.skyhanni.mixins.hooks.RenderLivingEntityHelper
+import at.hannibal2.skyhanni.utils.EntityUtils.hasMaxHealth
+import at.hannibal2.skyhanni.utils.LocationUtils.distanceToPlayer
+import at.hannibal2.skyhanni.utils.LorenzColor
+import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.LorenzUtils.editCopy
+import at.hannibal2.skyhanni.utils.RenderUtils.draw3DLine
+import at.hannibal2.skyhanni.utils.RenderUtils.exactPlayerEyeLocation
+import at.hannibal2.skyhanni.utils.getLorenzVec
+import net.minecraft.entity.EntityCreature
+import net.minecraft.entity.monster.EntityBlaze
+import net.minecraft.entity.monster.EntityEnderman
+import net.minecraft.entity.monster.EntitySpider
+import net.minecraft.entity.monster.EntityZombie
+import net.minecraft.entity.passive.EntityWolf
+import net.minecraftforge.client.event.RenderWorldLastEvent
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+
+class SlayerMiniBossFeatures {
+ private val config get() = SkyHanniMod.feature.slayer
+ private var miniBosses = listOf<EntityCreature>()
+
+ @SubscribeEvent
+ fun onEntityHealthUpdate(event: EntityMaxHealthUpdateEvent) {
+ if (!isEnabled()) return
+ val entity = event.entity as? EntityCreature ?: return
+ if (DamageIndicatorManager.isBoss(entity)) return
+
+ val maxHealth = event.maxHealth
+ for (bossType in SlayerMiniBossType.entries) {
+ if (!bossType.health.any { entity.hasMaxHealth(it, false, maxHealth) }) continue
+ if (!bossType.clazz.isInstance(entity)) continue
+
+ miniBosses = miniBosses.editCopy { add(entity) }
+ RenderLivingEntityHelper.setEntityColor(entity, LorenzColor.AQUA.toColor().withAlpha(127))
+ { config.slayerMinibossHighlight }
+ RenderLivingEntityHelper.setNoHurtTime(entity) { config.slayerMinibossHighlight }
+ }
+ }
+
+ @SubscribeEvent
+ fun onWorldChange(event: LorenzWorldChangeEvent) {
+ miniBosses = emptyList()
+ }
+
+ @SubscribeEvent
+ fun onWorldRender(event: RenderWorldLastEvent) {
+ if (!config.slayerMinibossLine) return
+ for (mob in miniBosses) {
+ if (mob.health <= 0) continue
+ if (mob.isDead) continue
+ if (mob.distanceToPlayer() > 10) continue
+
+ event.draw3DLine(
+ event.exactPlayerEyeLocation(),
+ mob.getLorenzVec().add(0, 1, 0),
+ LorenzColor.AQUA.toColor(),
+ 3,
+ true
+ )
+ }
+ }
+
+ private fun isEnabled() = LorenzUtils.inSkyBlock && !LorenzUtils.inDungeons && !LorenzUtils.inKuudraFight
+
+ enum class SlayerMiniBossType(val clazz: Class<out EntityCreature>, vararg val health: Int) {
+ REVENANT(EntityZombie::class.java, 24_000, 90_000, 360_000, 600_000, 2_400_000),
+ TARANTULA(EntitySpider::class.java, 54_000, 144_000, 576_000),
+ SVEN(EntityWolf::class.java, 45_000, 120_000, 480_000),
+ VOIDLING(EntityEnderman::class.java, 8_400_000, 17_500_000, 52_500_000),
+ INFERNAL(EntityBlaze::class.java, 12_000_000, 25_000_000),
+ ;
+ }
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerQuestWarning.kt b/src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerQuestWarning.kt
index 6f99abe18..6c3648bcc 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerQuestWarning.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerQuestWarning.kt
@@ -15,6 +15,7 @@ import at.hannibal2.skyhanni.utils.StringUtils.removeColor
import at.hannibal2.skyhanni.utils.getLorenzVec
import net.minecraft.entity.EntityLivingBase
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import kotlin.time.Duration.Companion.seconds
class SlayerQuestWarning {
private val config get() = SkyHanniMod.feature.slayer
@@ -36,7 +37,7 @@ class SlayerQuestWarning {
if (message == " §r§c§lSLAYER QUEST FAILED!") {
needNewQuest("The old slayer quest has failed!")
}
- if (message == "§eYour unsuccessful quest has been cleared out!") {
+ if (message == " §r§5§lSLAYER QUEST STARTED!") {
needSlayerQuest = false
}
@@ -134,7 +135,7 @@ class SlayerQuestWarning {
LorenzUtils.chat("§e[SkyHanni] $chatMessage")
if (config.questWarningTitle) {
- TitleUtils.sendTitle("§e$titleMessage", 2_000)
+ TitleUtils.sendTitle("§e$titleMessage", 2.seconds)
}
}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerRngMeterDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerRngMeterDisplay.kt
index 371aa5337..7f785cf10 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerRngMeterDisplay.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerRngMeterDisplay.kt
@@ -19,6 +19,7 @@ import at.hannibal2.skyhanni.utils.StringUtils.removeWordsAtEnd
import io.github.moulberry.notenoughupdates.util.Constants
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import kotlin.math.ceil
+import kotlin.time.Duration.Companion.seconds
class SlayerRngMeterDisplay {
private val config get() = SkyHanniMod.feature.slayer.rngMeterDisplay
@@ -74,7 +75,7 @@ class SlayerRngMeterDisplay {
if (!hasItemSelected) {
if (config.warnEmpty) {
LorenzUtils.warning("§c[Skyhanni] No Slayer RNG Meter Item selected!")
- TitleUtils.sendTitle("§cNo RNG Meter Item!", 3_000)
+ TitleUtils.sendTitle("§cNo RNG Meter Item!", 3.seconds)
}
}
var blockChat = config.hideChat && hasItemSelected
diff --git a/src/main/java/at/hannibal2/skyhanni/features/slayer/VampireSlayerFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/slayer/VampireSlayerFeatures.kt
index 0caa2f3be..6d93816b7 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/slayer/VampireSlayerFeatures.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/slayer/VampireSlayerFeatures.kt
@@ -18,6 +18,7 @@ import at.hannibal2.skyhanni.utils.RenderUtils.draw3DLine
import at.hannibal2.skyhanni.utils.RenderUtils.drawColor
import at.hannibal2.skyhanni.utils.RenderUtils.drawDynamicText
import at.hannibal2.skyhanni.utils.RenderUtils.exactLocation
+import at.hannibal2.skyhanni.utils.RenderUtils.exactPlayerEyeLocation
import at.hannibal2.skyhanni.utils.SoundUtils.playSound
import kotlinx.coroutines.*
import net.minecraft.client.Minecraft
@@ -127,8 +128,12 @@ object VampireSlayerFeatures {
if (shouldSendSound)
playTwinclawsSound()
if (shouldSendTitle)
- TitleUtils.sendTitle("§6§lTWINCLAWS", (1750 - config.twinclawsDelay), 2.6)
- nextClawSend = System.currentTimeMillis() + 5000
+ TitleUtils.sendTitle(
+ "§6§lTWINCLAWS",
+ (1750 - config.twinclawsDelay).milliseconds,
+ 2.6
+ )
+ nextClawSend = System.currentTimeMillis() + 5_000
}
}
}
@@ -178,7 +183,7 @@ object VampireSlayerFeatures {
else canUseSteak && configCoopBoss.steakAlert && containCoop
if (shouldSendSteakTitle)
- TitleUtils.sendTitle("§c§lSTEAK!", 300, 2.6)
+ TitleUtils.sendTitle("§c§lSTEAK!", 300.milliseconds, 2.6)
if (shouldRender) {
RenderLivingEntityHelper.setEntityColor(this, color) { isEnabled() }
@@ -278,9 +283,13 @@ object VampireSlayerFeatures {
val vec = event.exactLocation(it)
val distance = start.distance(vec)
if (distance <= 15) {
- val p = Minecraft.getMinecraft().thePlayer
- val add = if (p.isSneaking) LorenzVec(0.0, 1.54, 0.0) else LorenzVec(0.0, 1.62, 0.0)
- event.draw3DLine(event.exactLocation(p).add(add), vec.add(0.0, 1.54, 0.0), config.lineColor.toChromaColor(), config.lineWidth, true)
+ event.draw3DLine(
+ event.exactPlayerEyeLocation(),
+ vec.add(0.0, 1.54, 0.0),
+ config.lineColor.toChromaColor(),
+ config.lineWidth,
+ true
+ )
}
}
}
@@ -300,10 +309,20 @@ object VampireSlayerFeatures {
color
) { isEnabled() }
- val linesColorStart = (if (isIchor) configBloodIcor.linesColor else configKillerSpring.linesColor).toChromaColor()
+ val linesColorStart =
+ (if (isIchor) configBloodIcor.linesColor else configKillerSpring.linesColor).toChromaColor()
val text = if (isIchor) "§4Ichor" else "§4Spring"
- event.drawColor(stand.position.toLorenzVec().add(0.0, 2.0, 0.0), LorenzColor.DARK_RED, alpha = 1f)
- event.drawDynamicText(stand.position.toLorenzVec().add(0.5, 2.5, 0.5), text, 1.5, ignoreBlocks = false)
+ event.drawColor(
+ stand.position.toLorenzVec().add(0.0, 2.0, 0.0),
+ LorenzColor.DARK_RED,
+ alpha = 1f
+ )
+ event.drawDynamicText(
+ stand.position.toLorenzVec().add(0.5, 2.5, 0.5),
+ text,
+ 1.5,
+ ignoreBlocks = false
+ )
for ((player, stand2) in standList) {
if ((configBloodIcor.showLines && isIchor) || (configKillerSpring.showLines && isSpring))
event.draw3DLine(
@@ -312,7 +331,8 @@ object VampireSlayerFeatures {
// stand2.position.toLorenzVec().add(0.0, 1.5, 0.0),
linesColorStart,
3,
- true)
+ true
+ )
}
}
if (configBloodIcor.renderBeam && isIchor) {
diff --git a/src/main/java/at/hannibal2/skyhanni/features/slayer/blaze/BlazeSlayerFirePitsWarning.kt b/src/main/java/at/hannibal2/skyhanni/features/slayer/blaze/BlazeSlayerFirePitsWarning.kt
index c518d1317..723432b9a 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/slayer/blaze/BlazeSlayerFirePitsWarning.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/slayer/blaze/BlazeSlayerFirePitsWarning.kt
@@ -10,6 +10,7 @@ import at.hannibal2.skyhanni.utils.LorenzUtils
import at.hannibal2.skyhanni.utils.SoundUtils
import at.hannibal2.skyhanni.utils.SoundUtils.playSound
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import kotlin.time.Duration.Companion.seconds
class BlazeSlayerFirePitsWarning {
private val config get() = SkyHanniMod.feature.slayer
@@ -18,7 +19,7 @@ class BlazeSlayerFirePitsWarning {
private var lastFirePitsWarning = 0L
fun fireFirePits() {
- TitleUtils.sendTitle("§cFire Pits!", 2_000)
+ TitleUtils.sendTitle("§cFire Pits!", 2.seconds)
}
}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/slayer/enderman/EndermanSlayerFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/slayer/enderman/EndermanSlayerFeatures.kt
index 609eb6737..dcdadf84a 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/slayer/enderman/EndermanSlayerFeatures.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/slayer/enderman/EndermanSlayerFeatures.kt
@@ -9,24 +9,32 @@ import at.hannibal2.skyhanni.utils.*
import at.hannibal2.skyhanni.utils.EntityUtils.getBlockInHand
import at.hannibal2.skyhanni.utils.ItemUtils.getSkullTexture
import at.hannibal2.skyhanni.utils.ItemUtils.name
+import at.hannibal2.skyhanni.utils.LocationUtils.distanceToPlayer
+import at.hannibal2.skyhanni.utils.LorenzUtils.editCopy
import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland
+import at.hannibal2.skyhanni.utils.LorenzUtils.toChromaColor
+import at.hannibal2.skyhanni.utils.RenderUtils.draw3DLine
import at.hannibal2.skyhanni.utils.RenderUtils.drawColor
-import at.hannibal2.skyhanni.utils.RenderUtils.drawString
+import at.hannibal2.skyhanni.utils.RenderUtils.drawDynamicText
+import at.hannibal2.skyhanni.utils.RenderUtils.exactLocation
+import at.hannibal2.skyhanni.utils.RenderUtils.exactPlayerEyeLocation
+import at.hannibal2.skyhanni.utils.TimeUtils.format
import net.minecraft.entity.item.EntityArmorStand
import net.minecraft.entity.monster.EntityEnderman
import net.minecraft.init.Blocks
import net.minecraftforge.client.event.RenderWorldLastEvent
-import net.minecraftforge.fml.common.eventhandler.EventPriority
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import kotlin.time.Duration.Companion.seconds
class EndermanSlayerFeatures {
private val config get() = SkyHanniMod.feature.slayer
+ private val beaconConfig get() = config.endermanBeaconConfig
private val endermenWithBeacons = mutableListOf<EntityEnderman>()
private val flyingBeacons = mutableListOf<EntityArmorStand>()
- private val nukekebiSkulls = mutableListOf<EntityArmorStand>()
- private val sittingBeacon = mutableListOf<LorenzVec>()
+ private val nukekubiSkulls = mutableListOf<EntityArmorStand>()
+ private var sittingBeacon = mapOf<LorenzVec, SimpleTimeMark>()
private val logger = LorenzLogger("slayer/enderman")
- private val nukekebiSkulTexture =
+ private val nukekubiSkulTexture =
"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZWIwNzU5NGUyZGYyNzM5MjFhNzdjMTAxZDBiZmRmYTExMTVhYmVkNWI5YjIwMjllYjQ5NmNlYmE5YmRiYjRiMyJ9fX0="
@SubscribeEvent
@@ -36,7 +44,7 @@ class EndermanSlayerFeatures {
if (entity in endermenWithBeacons || entity in flyingBeacons) return
if (entity is EntityEnderman) {
- if (config.slayerEndermanBeacon) {
+ if (showBeacon()) {
if (hasBeaconInHand(entity) && canSee(LocationUtils.playerEyeLocation(), entity.getLorenzVec())) {
endermenWithBeacons.add(entity)
logger.log("Added enderman with beacon at ${entity.getLorenzVec()}")
@@ -45,21 +53,22 @@ class EndermanSlayerFeatures {
}
if (entity is EntityArmorStand) {
- if (config.slayerEndermanBeacon) {
+ if (showBeacon()) {
val stack = entity.inventory[4] ?: return
if (stack.name == "Beacon" && canSee(LocationUtils.playerEyeLocation(), entity.getLorenzVec())) {
flyingBeacons.add(entity)
- if (config.slayerEndermanBeaconWaring)
- TitleUtils.sendTitle("§4Beacon", 2_00)
+ if (beaconConfig.showWarning)
+ TitleUtils.sendTitle("§4Beacon", 2.seconds)
logger.log("Added flying beacons at ${entity.getLorenzVec()}")
}
}
if (config.endermanHighlightNukekebi) {
- if (entity.inventory.any { it?.getSkullTexture() == nukekebiSkulTexture }) {
- nukekebiSkulls.add(entity)
- logger.log("Added nukekebi skulls at ${entity.getLorenzVec()}")
- nukekebiSkulls.also { it.removeAll { it.isDead } }
+ if (entity.inventory.any { it?.getSkullTexture() == nukekubiSkulTexture }) {
+ if (entity !in nukekubiSkulls) {
+ nukekubiSkulls.add(entity)
+ logger.log("Added Nukekubi skulls at ${entity.getLorenzVec()}")
+ }
}
}
}
@@ -69,54 +78,120 @@ class EndermanSlayerFeatures {
private fun canSee(a: LorenzVec, b: LorenzVec) = LocationUtils.canSee(a, b) || a.distance(b) < 15
+ private fun showBeacon() = beaconConfig.highlightBeacon || beaconConfig.showWarning || beaconConfig.showLine
+
@SubscribeEvent
fun onRenderMobColored(event: RenderMobColoredEvent) {
if (!IslandType.THE_END.isInIsland()) return
- if (config.slayerEndermanBeacon && event.entity in flyingBeacons) {
- event.color = LorenzColor.DARK_RED.toColor().withAlpha(1)
+ if (beaconConfig.highlightBeacon && event.entity in flyingBeacons) {
+ event.color = beaconConfig.beaconColor.toChromaColor().withAlpha(1)
}
- if (config.endermanHighlightNukekebi && event.entity in nukekebiSkulls) {
+ if (config.endermanHighlightNukekebi && event.entity in nukekubiSkulls) {
event.color = LorenzColor.GOLD.toColor().withAlpha(1)
}
}
- @SubscribeEvent(priority = EventPriority.HIGH)
+ @SubscribeEvent
fun onWorldRender(event: RenderWorldLastEvent) {
if (!IslandType.THE_END.isInIsland()) return
- if (!config.slayerEndermanBeacon) return
- endermenWithBeacons.removeIf { it.isDead || !hasBeaconInHand(it) }
- endermenWithBeacons.map { it.getLorenzVec().add(-0.5, 0.2, -0.5) }
- .forEach { event.drawColor(it, LorenzColor.DARK_RED, alpha = 1f) }
+ if (beaconConfig.highlightBeacon) {
+ endermenWithBeacons.removeIf { it.isDead || !hasBeaconInHand(it) }
+
+ endermenWithBeacons.map { it.getLorenzVec().add(-0.5, 0.2, -0.5) }
+ .forEach { event.drawColor(it, beaconConfig.beaconColor.toChromaColor(), alpha = 0.5f) }
+ }
- for (location in sittingBeacon.toMutableList()) {
- event.drawColor(location, LorenzColor.DARK_RED, alpha = 1f)
- event.drawWaypointFilled(location, LorenzColor.RED.toColor(), true, true)
- event.drawString(location.add(0.5, 0.5, 0.5), "§4Beacon", true)
+ for ((location, time) in sittingBeacon) {
+ if (location.distanceToPlayer() > 20) continue
+ if (beaconConfig.showLine) {
+ event.draw3DLine(
+ event.exactPlayerEyeLocation(),
+ location.add(0.5, 1.0, 0.5),
+ beaconConfig.lneColor.toChromaColor(),
+ beaconConfig.lineWidth,
+ true
+ )
+ }
+ if (beaconConfig.highlightBeacon) {
+ val duration = 5.seconds - time.passedSince()
+ val durationFormat = duration.format(showMilliSeconds = true)
+ event.drawColor(location, beaconConfig.beaconColor.toChromaColor(), alpha = 1f)
+ event.drawWaypointFilled(location, beaconConfig.beaconColor.toChromaColor(), true, true)
+ event.drawDynamicText(location.add(0, 1, 0), "§4Beacon §b$durationFormat", 1.8)
+ }
+ }
+ for (beacon in flyingBeacons) {
+ if (beacon.isDead) continue
+ if (beaconConfig.highlightBeacon) {
+ val beaconLocation = event.exactLocation(beacon)
+ event.drawDynamicText(beaconLocation.add(0, 1, 0), "§4Beacon", 1.8)
+ }
+
+ if (beaconConfig.showLine) {
+ val beaconLocation = event.exactLocation(beacon)
+ event.draw3DLine(
+ event.exactPlayerEyeLocation(),
+ beaconLocation.add(0.5, 1.0, 0.5),
+ beaconConfig.lneColor.toChromaColor(),
+ beaconConfig.lineWidth,
+ true
+ )
+ }
+ }
+
+ config.endermanHighlightNukekebi
+ for (skull in nukekubiSkulls) {
+ if (!skull.isDead) {
+ event.drawDynamicText(
+ skull.getLorenzVec().add(-0.5, 1.5, -0.5),
+ "§6Nukekubi Skull",
+ 1.6,
+ ignoreBlocks = false
+ )
+ }
+ }
+ }
+
+ @SubscribeEvent
+ fun onTick(event: LorenzTickEvent) {
+ if (!IslandType.THE_END.isInIsland()) return
+ if (!event.repeatSeconds(1)) return
+
+ nukekubiSkulls.also { skulls -> skulls.removeAll { it.isDead } }
+ flyingBeacons.also { beacons -> beacons.removeAll { it.isDead } }
+
+ // Removing the beacon if It's still there after 7 sesconds.
+ // This is just a workaround for the cases where the ServerBlockChangeEvent don't detect the beacon despawn info.
+ val toRemove = sittingBeacon.filter { it.value.passedSince() > 7.seconds }
+ if (toRemove.isNotEmpty()) {
+ sittingBeacon = sittingBeacon.editCopy {
+ toRemove.keys.forEach { remove(it) }
+ }
}
}
@SubscribeEvent
fun onBlockChange(event: ServerBlockChangeEvent) {
if (!IslandType.THE_END.isInIsland()) return
- if (!config.slayerEndermanBeacon) return
+ if (!showBeacon()) return
val location = event.location
if (event.new == "beacon") {
val armorStand = flyingBeacons.find { location.distance(it.getLorenzVec()) < 3 }
if (armorStand != null) {
flyingBeacons.remove(armorStand)
- sittingBeacon.add(location)
+ sittingBeacon = sittingBeacon.editCopy { this[location] = SimpleTimeMark.now() }
logger.log("Replaced flying beacon with sitting beacon at $location")
}
} else {
if (location in sittingBeacon) {
logger.log("Removed sitting beacon $location")
- sittingBeacon.remove(location)
+ sittingBeacon = sittingBeacon.editCopy { remove(location) }
}
}
}
@@ -125,8 +200,8 @@ class EndermanSlayerFeatures {
fun onWorldChange(event: LorenzWorldChangeEvent) {
endermenWithBeacons.clear()
flyingBeacons.clear()
- nukekebiSkulls.clear()
- sittingBeacon.clear()
+ nukekubiSkulls.clear()
+ sittingBeacon = emptyMap()
logger.log("Reset everything (world change)")
}
} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/test/SkyHanniTestCommand.kt b/src/main/java/at/hannibal2/skyhanni/test/SkyHanniTestCommand.kt
index 684a1a97d..63bc5f471 100644
--- a/src/main/java/at/hannibal2/skyhanni/test/SkyHanniTestCommand.kt
+++ b/src/main/java/at/hannibal2/skyhanni/test/SkyHanniTestCommand.kt
@@ -10,6 +10,9 @@ import at.hannibal2.skyhanni.features.dungeon.DungeonData
import at.hannibal2.skyhanni.features.garden.visitor.GardenVisitorColorNames
import at.hannibal2.skyhanni.utils.*
import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName
+import at.hannibal2.skyhanni.utils.ItemUtils.getInternalNameOrNull
+import at.hannibal2.skyhanni.utils.NEUItems.getNpcPriceOrNull
+import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators
import at.hannibal2.skyhanni.utils.RenderUtils.renderString
import at.hannibal2.skyhanni.utils.RenderUtils.renderStringsAndItems
import net.minecraft.nbt.NBTTagCompound
@@ -175,6 +178,10 @@ class SkyHanniTestCommand {
OSUtils.copyToClipboard("LorenzVec($x, $y, $z)")
}
+ fun debugVersion() {
+ LorenzUtils.chat("§eYou are using SkyHanni ${SkyHanniMod.version}")
+ }
+
fun debugData(args: Array<String>) {
if (args.size == 2) {
if (args[0] == "profileName") {
@@ -224,14 +231,22 @@ class SkyHanniTestCommand {
}
@SubscribeEvent
- fun onItemTooltipLow(event: ItemTooltipEvent) {
+ fun onShowInternalName(event: ItemTooltipEvent) {
if (!SkyHanniMod.feature.dev.showInternalName) return
- val itemStack = event.itemStack
- if (itemStack != null) {
- val internalName = itemStack.getInternalName()
- if ((internalName == NEUInternalName.NONE) && !SkyHanniMod.feature.dev.showEmptyNames) return
- event.toolTip.add("Internal Name: '${internalName.asString()}'")
- }
+ val itemStack = event.itemStack ?: return
+ val internalName = itemStack.getInternalName()
+ if ((internalName == NEUInternalName.NONE) && !SkyHanniMod.feature.dev.showEmptyNames) return
+ event.toolTip.add("Internal Name: '${internalName.asString()}'")
+ }
+
+ @SubscribeEvent
+ fun onSHowNpcPrice(event: ItemTooltipEvent) {
+ if (!SkyHanniMod.feature.dev.showNpcPrice) return
+ val itemStack = event.itemStack ?: return
+ val internalName = itemStack.getInternalNameOrNull() ?: return
+
+ val npcPrice = internalName.getNpcPriceOrNull() ?: return
+ event.toolTip.add("§7Npc price: §6${npcPrice.addSeparators()}")
}
@SubscribeEvent
diff --git a/src/main/java/at/hannibal2/skyhanni/test/TestExportTools.kt b/src/main/java/at/hannibal2/skyhanni/test/TestExportTools.kt
index e3df5c54c..7ae608d51 100644
--- a/src/main/java/at/hannibal2/skyhanni/test/TestExportTools.kt
+++ b/src/main/java/at/hannibal2/skyhanni/test/TestExportTools.kt
@@ -9,7 +9,6 @@ import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
import net.minecraftforge.client.event.GuiScreenEvent
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
-import org.lwjgl.input.Keyboard
import java.io.InputStreamReader
import java.io.Reader
@@ -41,8 +40,8 @@ object TestExportTools {
}
@SubscribeEvent
- fun onKeybind(event: GuiScreenEvent.KeyboardInputEvent) {
- if (!Keyboard.isKeyDown(SkyHanniMod.feature.dev.copyNBTDataCompressed)) return
+ fun onKeybind(event: GuiScreenEvent.KeyboardInputEvent.Post) {
+ if (!OSUtils.isKeyHeld(SkyHanniMod.feature.dev.copyNBTDataCompressed)) return
val gui = event.gui as? GuiContainer ?: return
val focussedSlot = gui.slotUnderMouse ?: return
val stack = focussedSlot.stack ?: return
diff --git a/src/main/java/at/hannibal2/skyhanni/test/TestShowSlotNumber.kt b/src/main/java/at/hannibal2/skyhanni/test/TestShowSlotNumber.kt
index be202e20d..115cef414 100644
--- a/src/main/java/at/hannibal2/skyhanni/test/TestShowSlotNumber.kt
+++ b/src/main/java/at/hannibal2/skyhanni/test/TestShowSlotNumber.kt
@@ -2,14 +2,14 @@ package at.hannibal2.skyhanni.test
import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.events.RenderInventoryItemTipEvent
+import at.hannibal2.skyhanni.utils.OSUtils
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
-import org.lwjgl.input.Keyboard
class TestShowSlotNumber {
@SubscribeEvent
fun onRenderItemTip(event: RenderInventoryItemTipEvent) {
- if (Keyboard.isKeyDown(SkyHanniMod.feature.dev.showSlotNumberKey)) {
+ if (OSUtils.isKeyHeld(SkyHanniMod.feature.dev.showSlotNumberKey)) {
val slotIndex = event.slot.slotIndex
event.stackTip = "$slotIndex"
}
diff --git a/src/main/java/at/hannibal2/skyhanni/test/command/CopyErrorCommand.kt b/src/main/java/at/hannibal2/skyhanni/test/command/CopyErrorCommand.kt
index 69288a896..946255996 100644
--- a/src/main/java/at/hannibal2/skyhanni/test/command/CopyErrorCommand.kt
+++ b/src/main/java/at/hannibal2/skyhanni/test/command/CopyErrorCommand.kt
@@ -16,10 +16,15 @@ object CopyErrorCommand {
private var cache =
CacheBuilder.newBuilder().expireAfterWrite(10, TimeUnit.MINUTES).build<Pair<String, Int>, Unit>()
+ fun skyHanniError(message: String): Nothing {
+ val exception = IllegalStateException(message)
+ logError(exception, message)
+ throw exception
+ }
+
fun command(array: Array<String>) {
if (array.size != 1) {
LorenzUtils.chat("§cUse /shcopyerror <error id>")
-
return
}
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/APIUtil.kt b/src/main/java/at/hannibal2/skyhanni/utils/APIUtil.kt
index 04bd67c18..917243b47 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/APIUtil.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/APIUtil.kt
@@ -7,6 +7,9 @@ import com.google.gson.JsonParser
import com.google.gson.JsonSyntaxException
import org.apache.http.client.config.RequestConfig
import org.apache.http.client.methods.HttpGet
+import org.apache.http.client.methods.HttpPost
+import org.apache.http.entity.ContentType
+import org.apache.http.entity.StringEntity
import org.apache.http.impl.client.HttpClientBuilder
import org.apache.http.impl.client.HttpClients
import org.apache.http.message.BasicHeader
@@ -83,6 +86,38 @@ object APIUtil {
return JsonObject()
}
+ fun postJSONIsSuccessful(urlString: String, body: String, silentError: Boolean = false): Boolean {
+ val client = builder.build()
+ try {
+ val method = HttpPost(urlString)
+ method.entity = StringEntity(body, ContentType.APPLICATION_JSON)
+
+ client.execute(method).use { response ->
+ val status = response.statusLine
+
+ if (status.statusCode >= 200 || status.statusCode < 300) {
+ return true
+ }
+
+ println("POST request to '$urlString' returned status ${status.statusCode}")
+ LorenzUtils.error("SkyHanni ran into an error whilst sending data. Status: ${status.statusCode}")
+
+ return false
+ }
+ } catch (throwable: Throwable) {
+ if (silentError) {
+ throw throwable
+ } else {
+ throwable.printStackTrace()
+ LorenzUtils.error("SkyHanni ran into an ${throwable::class.simpleName ?: "error"} whilst sending a resource. See logs for more details.")
+ }
+ } finally {
+ client.close()
+ }
+
+ return false
+ }
+
fun readFile(file: File): BufferedReader {
return BufferedReader(InputStreamReader(FileInputStream(file), StandardCharsets.UTF_8))
}
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/ClipboardUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/ClipboardUtils.kt
index a7585702f..09ce8a835 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/ClipboardUtils.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/ClipboardUtils.kt
@@ -11,8 +11,6 @@ import java.awt.datatransfer.Clipboard
import java.awt.datatransfer.DataFlavor
import java.awt.datatransfer.StringSelection
import java.awt.datatransfer.UnsupportedFlavorException
-import java.util.*
-import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds
object ClipboardUtils {
@@ -26,20 +24,12 @@ object ClipboardUtils {
return result
}
- private fun runDelayed(duration: Duration, runnable: () -> Unit) {
- Timer().schedule(object : TimerTask() {
- override fun run() {
- runnable()
- }
- }, duration.inWholeMilliseconds)
- }
-
private suspend fun getClipboard(): Clipboard? {
val deferred = CompletableDeferred<Clipboard?>()
if (canAccessClibpard()) {
deferred.complete(Toolkit.getDefaultToolkit().systemClipboard)
} else {
- runDelayed(5.milliseconds) {
+ LorenzUtils.runDelayed(5.milliseconds) {
SkyHanniMod.coroutineScope.launch {
deferred.complete(getClipboard())
}
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/EntityUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/EntityUtils.kt
index 6763dabeb..12c47355f 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/EntityUtils.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/EntityUtils.kt
@@ -102,8 +102,9 @@ object EntityUtils {
fun EntityLivingBase.hasMaxHealth(health: Int, boss: Boolean = false, maxHealth: Int = baseMaxHealth): Boolean {
if (maxHealth == health) return true
- //Derpy
- if (maxHealth == health * 2) return true
+ if (LorenzUtils.isDerpy) {
+ if (maxHealth == health * 2) return true
+ }
// TODO runic support
@@ -112,7 +113,9 @@ object EntityUtils {
if (maxHealth == health * 3) return true
//Derpy + Corrupted
- if (maxHealth == health * 2 * 3) return true
+ if (LorenzUtils.isDerpy) {
+ if (maxHealth == health * 2 * 3) return true
+ }
}
return false
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/GuiRenderUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/GuiRenderUtils.kt
index 9c9d612f3..a8d493018 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/GuiRenderUtils.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/GuiRenderUtils.kt
@@ -236,7 +236,7 @@ object GuiRenderUtils {
GlStateManager.scale(textScale, textScale, 1f)
drawString(label, xPos * inverseScale, yPos * inverseScale)
drawString(
- "§2$current / ${DecimalFormat("0.#").format(maxValue)}☘",
+ "§2$current / ${DecimalFormat("0.##").format(maxValue)}☘",
xPos * inverseScale,
(yPos + 8) * inverseScale
)
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/ItemUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/ItemUtils.kt
index d90c16ded..bedbebc46 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/ItemUtils.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/ItemUtils.kt
@@ -189,7 +189,7 @@ object ItemUtils {
private val itemAmountCache = mutableMapOf<String, Pair<String, Int>>()
- fun readItemAmount(input: String): Pair<String?, Int> {
+ fun readItemAmount(input: String): Pair<String, Int>? {
if (itemAmountCache.containsKey(input)) {
return itemAmountCache[input]!!
}
@@ -213,7 +213,7 @@ object ItemUtils {
println("")
println("input: '$input'")
println("string: '$string'")
- return Pair(null, 0)
+ return null
}
val itemName = color + matcher.group("name").trim()
@@ -233,4 +233,11 @@ object ItemUtils {
}
return getItemStack().nameWithEnchantment ?: error("Could not find item name for $this")
}
+
+ fun getPetRarityOld(petStack: ItemStack?): Int {
+ val petInternalName = petStack?.getInternalName_old()
+ if (petInternalName == "NONE" || petInternalName == null) return -1
+ val split = petInternalName.split(";")
+ return split.last().toInt()
+ }
} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/LorenzUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/LorenzUtils.kt
index 71dfb1edb..4e01f5da6 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/LorenzUtils.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/LorenzUtils.kt
@@ -3,6 +3,7 @@ package at.hannibal2.skyhanni.utils
import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.data.HypixelData
import at.hannibal2.skyhanni.data.IslandType
+import at.hannibal2.skyhanni.data.MayorElection
import at.hannibal2.skyhanni.features.dungeon.DungeonData
import at.hannibal2.skyhanni.test.TestBingo
import at.hannibal2.skyhanni.utils.NEUItems.getItemStackOrNull
@@ -32,6 +33,8 @@ import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KMutableProperty1
import kotlin.reflect.KProperty
import kotlin.reflect.KProperty0
+import kotlin.time.Duration
+import kotlin.time.Duration.Companion.seconds
object LorenzUtils {
@@ -116,19 +119,25 @@ object LorenzUtils {
fun Double.round(decimals: Int): Double {
var multiplier = 1.0
repeat(decimals) { multiplier *= 10 }
- return kotlin.math.round(this * multiplier) / multiplier
+ val result = kotlin.math.round(this * multiplier) / multiplier
+ val a = result.toString()
+ val b = toString()
+ return if (a.length > b.length) this else result
}
- fun Float.round(decimals: Int): Double {
+ fun Float.round(decimals: Int): Float {
var multiplier = 1.0
repeat(decimals) { multiplier *= 10 }
- return kotlin.math.round(this * multiplier) / multiplier
+ val result = kotlin.math.round(this * multiplier) / multiplier
+ val a = result.toString()
+ val b = toString()
+ return if (a.length > b.length) this else result.toFloat()
}
// TODO replace all calls with regex
fun String.between(start: String, end: String): String = this.split(start, end)[1]
- //TODO change to Int
+ // TODO use derpy() on every use case
val EntityLivingBase.baseMaxHealth: Int
get() = this.getEntityAttribute(SharedMonsterAttributes.maxHealth).baseValue.toInt()
@@ -225,9 +234,10 @@ object LorenzUtils {
fun clickableChat(message: String, command: String) {
val text = ChatComponentText(message)
- text.chatStyle.chatClickEvent = ClickEvent(ClickEvent.Action.RUN_COMMAND, "/${command.removePrefix("/")}")
+ val fullCommand = "/" + command.removePrefix("/")
+ text.chatStyle.chatClickEvent = ClickEvent(ClickEvent.Action.RUN_COMMAND, fullCommand)
text.chatStyle.chatHoverEvent =
- HoverEvent(HoverEvent.Action.SHOW_TEXT, ChatComponentText("§eExecute /${command.removePrefix("/")}"))
+ HoverEvent(HoverEvent.Action.SHOW_TEXT, ChatComponentText("§eExecute $fullCommand"))
Minecraft.getMinecraft().thePlayer.addChatMessage(text)
}
@@ -267,9 +277,9 @@ object LorenzUtils {
}
}
- fun isShiftKeyDown() = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT)
+ fun isShiftKeyDown() = OSUtils.isKeyHeld(Keyboard.KEY_LSHIFT) || OSUtils.isKeyHeld(Keyboard.KEY_RSHIFT)
- fun isControlKeyDown() = Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL)
+ fun isControlKeyDown() = OSUtils.isKeyHeld(Keyboard.KEY_LCONTROL) || OSUtils.isKeyHeld(Keyboard.KEY_RCONTROL)
// MoulConfig is in Java, I don't want to downgrade this logic
fun <T> onChange(vararg properties: Property<out T>, observer: Observer<T>) {
@@ -409,8 +419,8 @@ object LorenzUtils {
val tileSign = (this as AccessorGuiEditSign).tileSign
return (tileSign.signText[1].unformattedText.removeColor() == "^^^^^^"
- && tileSign.signText[2].unformattedText.removeColor() == "Set your"
- && tileSign.signText[3].unformattedText.removeColor() == "speed cap!")
+ && tileSign.signText[2].unformattedText.removeColor() == "Set your"
+ && tileSign.signText[3].unformattedText.removeColor() == "speed cap!")
}
fun inIsland(island: IslandType) = inSkyBlock && skyBlockIsland == island
@@ -474,4 +484,21 @@ object LorenzUtils {
javaClass.getDeclaredField("modifiers").makeAccessible().set(this, modifiers and (Modifier.FINAL.inv()))
return this
}
+
+ fun <T> List<T>.indexOfFirst(vararg args: T) = args.map { indexOf(it) }.firstOrNull { it != -1 }
+
+ private val recalculateDerpy =
+ RecalculatingValue(1.seconds) { MayorElection.isPerkActive("Derpy", "DOUBLE MOBS HP!!!") }
+
+ val isDerpy get() = recalculateDerpy.getValue()
+
+ fun Int.derpy() = if (isDerpy) this / 2 else this
+
+ fun runDelayed(duration: Duration, runnable: () -> Unit) {
+ Timer().schedule(object : TimerTask() {
+ override fun run() {
+ runnable()
+ }
+ }, duration.inWholeMilliseconds)
+ }
} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt b/src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt
index b706bfb68..fac794a53 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt
@@ -1,6 +1,7 @@
package at.hannibal2.skyhanni.utils
import at.hannibal2.skyhanni.config.ConfigManager
+import at.hannibal2.skyhanni.features.bazaar.BazaarDataHolder
import at.hannibal2.skyhanni.test.command.CopyErrorCommand
import at.hannibal2.skyhanni.utils.ItemBlink.checkBlinkItem
import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName_old
@@ -135,32 +136,30 @@ object NEUItems {
fun getInternalNameOrNull(nbt: NBTTagCompound) =
ItemResolutionQuery(manager).withItemNBT(nbt).resolveInternalName()?.asInternalName()
- fun NEUInternalName.getPriceOrNull(useSellingPrice: Boolean = false): Double? {
- val price = getPrice(useSellingPrice)
- if (price == -1.0) {
- return null
- }
- return price
- }
+ fun NEUInternalName.getPrice(useSellingPrice: Boolean = false) = getPriceOrNull(useSellingPrice) ?: -1.0
+
+ fun NEUInternalName.getNpcPrice() = getNpcPriceOrNull() ?: -1.0
+
+ fun NEUInternalName.getNpcPriceOrNull() = BazaarDataHolder.getNpcPrice(this)
fun transHypixelNameToInternalName(hypixelId: String) =
manager.auctionManager.transformHypixelBazaarToNEUItemId(hypixelId).asInternalName()
- fun NEUInternalName.getPrice(useSellingPrice: Boolean = false): Double {
+ fun NEUInternalName.getPriceOrNull(useSellingPrice: Boolean = false): Double? {
if (equals("WISP_POTION")) {
return 20_000.0
}
val result = manager.auctionManager.getBazaarOrBin(asString(), useSellingPrice)
- if (result == -1.0) {
- if (equals("JACK_O_LANTERN")) {
- return getPrice("PUMPKIN", useSellingPrice) + 1
- }
- if (equals("GOLDEN_CARROT")) {
- // 6.8 for some players
- return 7.0 // NPC price
- }
+ if (result != -1.0) return result
+
+ if (equals("JACK_O_LANTERN")) {
+ return getPrice("PUMPKIN", useSellingPrice) + 1
}
- return result
+ if (equals("GOLDEN_CARROT")) {
+ // 6.8 for some players
+ return 7.0 // NPC price
+ }
+ return getNpcPriceOrNull()
}
fun getPrice(internalName: String, useSellingPrice: Boolean = false) =
@@ -178,7 +177,7 @@ object NEUItems {
fun NEUInternalName.getItemStack(definite: Boolean = false): ItemStack =
getItemStackOrNull() ?: run {
- if (getPrice() == -1.0) return@run fallbackItem
+ if (getPriceOrNull() == null) return@run fallbackItem
if (definite) {
Utils.showOutdatedRepoNotification()
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/OSUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/OSUtils.kt
index 254d8ad09..981ea87c3 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/OSUtils.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/OSUtils.kt
@@ -1,7 +1,9 @@
package at.hannibal2.skyhanni.utils
+import io.github.moulberry.moulconfig.internal.KeybindHelper
import net.minecraft.client.settings.KeyBinding
import org.lwjgl.input.Keyboard
+import org.lwjgl.input.Mouse
import java.awt.Desktop
import java.io.IOException
import java.net.URI
@@ -32,7 +34,7 @@ object OSUtils {
fun KeyBinding.isActive(): Boolean {
if (!Keyboard.isCreated()) return false
try {
- if (Keyboard.isKeyDown(this.keyCode)) return true
+ if (isKeyHeld(keyCode)) return true
} catch (e: IndexOutOfBoundsException) {
println("KeyBinding isActive caused an IndexOutOfBoundsException with keyCode: $keyCode")
e.printStackTrace()
@@ -40,4 +42,15 @@ object OSUtils {
}
return this.isKeyDown || this.isPressed
}
+
+ fun isKeyHeld(keyCode: Int): Boolean {
+ if (keyCode == 0) return false
+ return if (keyCode < 0) {
+ Mouse.isButtonDown(keyCode + 100)
+ } else {
+ KeybindHelper.isKeyDown(keyCode)
+ }
+ }
+
+ fun getKeyName(keyCode: Int): String = KeybindHelper.getKeyName(keyCode)
}
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/RenderUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/RenderUtils.kt
index 672b26743..7544e7934 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/RenderUtils.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/RenderUtils.kt
@@ -35,11 +35,10 @@ object RenderUtils {
}
infix fun Slot.highlight(color: Color) {
- val lightingState = GL11.glIsEnabled(GL11.GL_LIGHTING)
-
- GlStateManager.disableLighting()
GlStateManager.color(1f, 1f, 1f, 1f)
-
+ GlStateManager.pushAttrib()
+ GL11.glDisable(GL11.GL_LIGHTING)
+ GL11.glEnable(GL11.GL_DEPTH_TEST)
GlStateManager.pushMatrix()
// TODO don't use z
GlStateManager.translate(0f, 0f, 110 + Minecraft.getMinecraft().renderItem.zLevel)
@@ -51,8 +50,7 @@ object RenderUtils {
color.rgb
)
GlStateManager.popMatrix()
-
- if (lightingState) GlStateManager.enableLighting()
+ GlStateManager.popAttrib()
}
fun RenderWorldLastEvent.drawColor(
@@ -61,6 +59,15 @@ object RenderUtils {
beacon: Boolean = false,
alpha: Float = -1f,
) {
+ drawColor(location, color.toColor(), beacon, alpha)
+ }
+
+ fun RenderWorldLastEvent.drawColor(
+ location: LorenzVec,
+ color: Color,
+ beacon: Boolean = false,
+ alpha: Float = -1f,
+ ) {
val (viewerX, viewerY, viewerZ) = getViewerPos(partialTicks)
val x = location.x - viewerX
val y = location.y - viewerY
@@ -75,11 +82,11 @@ object RenderUtils {
GlStateManager.disableCull()
drawFilledBoundingBox(
AxisAlignedBB(x, y, z, x + 1, y + 1, z + 1).expandBlock(),
- color.toColor(),
+ color,
realAlpha
)
GlStateManager.disableTexture2D()
- if (distSq > 5 * 5 && beacon) renderBeaconBeam(x, y + 1, z, color.toColor().rgb, 1.0f, partialTicks)
+ if (distSq > 5 * 5 && beacon) renderBeaconBeam(x, y + 1, z, color.rgb, 1.0f, partialTicks)
GlStateManager.disableLighting()
GlStateManager.enableTexture2D()
GlStateManager.enableDepth()
@@ -672,7 +679,6 @@ object RenderUtils {
}
fun RenderWorldLastEvent.draw3DLine(p1: LorenzVec, p2: LorenzVec, color: Color, lineWidth: Int, depth: Boolean) {
- GlStateManager.disableDepth()
GlStateManager.disableCull()
val render = Minecraft.getMinecraft().renderViewEntity
@@ -710,8 +716,12 @@ object RenderUtils {
GlStateManager.enableDepth()
}
- fun RenderWorldLastEvent.exactLocation(entity: Entity): LorenzVec {
- return exactLocation(entity, partialTicks)
+ fun RenderWorldLastEvent.exactLocation(entity: Entity) = exactLocation(entity, partialTicks)
+
+ fun RenderWorldLastEvent.exactPlayerEyeLocation(): LorenzVec {
+ val player = Minecraft.getMinecraft().thePlayer
+ val add = if (player.isSneaking) LorenzVec(0.0, 1.54, 0.0) else LorenzVec(0.0, 1.62, 0.0)
+ return exactLocation(player).add(add)
}
fun exactLocation(entity: Entity, partialTicks: Float): LorenzVec {
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/SimpleTimeMark.kt b/src/main/java/at/hannibal2/skyhanni/utils/SimpleTimeMark.kt
index 581585c9a..e79599cae 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/SimpleTimeMark.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/SimpleTimeMark.kt
@@ -1,5 +1,6 @@
package at.hannibal2.skyhanni.utils
+import io.github.moulberry.notenoughupdates.util.SkyBlockTime
import java.time.Instant
import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds
@@ -14,7 +15,9 @@ value class SimpleTimeMark(private val millis: Long) {
fun passedSince() = if (millis == 0L) Duration.INFINITE else now() - this
- fun isInPast() = !passedSince().isNegative()
+ fun timeUntil() = -passedSince()
+
+ fun isInPast() = timeUntil().isNegative()
override fun toString(): String {
if (millis == 0L) return "The Far Past"
@@ -28,5 +31,6 @@ value class SimpleTimeMark(private val millis: Long) {
fun farPast() = SimpleTimeMark(0)
fun Long.asTimeMark() = SimpleTimeMark(this)
+ fun SkyBlockTime.asTimeMark() = SimpleTimeMark(toMillis())
}
} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/SkyBlockItemModifierUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/SkyBlockItemModifierUtils.kt
index 77d291d84..c87941766 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/SkyBlockItemModifierUtils.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/SkyBlockItemModifierUtils.kt
@@ -39,8 +39,13 @@ object SkyBlockItemModifierUtils {
fun ItemStack.getManaDisintegrators() = getAttributeInt("mana_disintegrator_count")
- fun ItemStack.getDungeonStarCount() =
+ fun ItemStack.getDungeonStarCount() = if (isDungeonItem()) {
getAttributeInt("upgrade_level") ?: getAttributeInt("dungeon_item_level")
+ } else null
+
+ private fun ItemStack.isDungeonItem() = getLore().any { it.contains("DUNGEON ") }
+
+ fun ItemStack.getPetExp() = getPetInfo()?.get("exp")?.asDouble
fun ItemStack.getPetCandyUsed(): Int? {
val data = cachedData
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt
index 15cab32f4..d42b597e6 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt
@@ -124,4 +124,32 @@ object StringUtils {
} ?: text
}
}
+
+ fun optionalPlural(number: Int, singular: String, plural: String) =
+ "$number " + if (number == 1) singular else plural
+
+ fun progressBar(percentage: Double, steps: Int = 25): Any {
+ //'§5§o§2§l§m §l§m §l§m §l§m §l§m §l§m §l§m §l§m §l§m §l§m §f§l§m §l§m §l§m §l§m §l§m §l§m §l§m §l§m §l§m §l§m §l§m §l§m §l§m §l§m §l§m §r §e348,144.3§6/§e936k'
+ val prefix = "§5§o§2"
+ val step = "§l§m "
+ val missing = "§f"
+ val end = "§r"
+
+ val builder = StringBuilder()
+ var inMissingArea = false
+ builder.append(prefix)
+ for (i in 0..steps) {
+ val toDouble = i.toDouble()
+ val stepPercentage = toDouble / steps
+ if (stepPercentage >= percentage) {
+ if (!inMissingArea) {
+ builder.append(missing)
+ inMissingArea = true
+ }
+ }
+ builder.append(step)
+ }
+ builder.append(end)
+ return builder.toString()
+ }
} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/TimeUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/TimeUtils.kt
index c088ded64..bcc4bff5f 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/TimeUtils.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/TimeUtils.kt
@@ -8,15 +8,21 @@ object TimeUtils {
private val pattern =
"(?:(?<y>\\d+) ?y(?:\\w* ?)?)?(?:(?<d>\\d+) ?d(?:\\w* ?)?)?(?:(?<h>\\d+) ?h(?:\\w* ?)?)?(?:(?<m>\\d+) ?m(?:\\w* ?)?)?(?:(?<s>\\d+) ?s(?:\\w* ?)?)?".toPattern()
-
fun formatDuration(
duration: Duration,
biggestUnit: TimeUnit = TimeUnit.YEAR,
showMilliSeconds: Boolean = false,
longName: Boolean = false,
maxUnits: Int = -1
+ ): String = duration.format(biggestUnit, showMilliSeconds, longName, maxUnits)
+
+ fun Duration.format(
+ biggestUnit: TimeUnit = TimeUnit.YEAR,
+ showMilliSeconds: Boolean = false,
+ longName: Boolean = false,
+ maxUnits: Int = -1
): String = formatDuration(
- duration.inWholeMilliseconds - 999, biggestUnit, showMilliSeconds, longName, maxUnits
+ inWholeMilliseconds - 999, biggestUnit, showMilliSeconds, longName, maxUnits
)
fun formatDuration(
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/jsonobjects/AnitaUpgradeCostsJson.java b/src/main/java/at/hannibal2/skyhanni/utils/jsonobjects/AnitaUpgradeCostsJson.java
new file mode 100644
index 000000000..c0fbd0ad0
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/utils/jsonobjects/AnitaUpgradeCostsJson.java
@@ -0,0 +1,17 @@
+package at.hannibal2.skyhanni.utils.jsonobjects;
+
+import com.google.gson.annotations.Expose;
+
+import java.util.Map;
+
+public class AnitaUpgradeCostsJson {
+ @Expose
+ public Map<String, Price> level_price;
+
+ public static class Price {
+ @Expose
+ public Integer gold_medals;
+ @Expose
+ public Integer jacob_tickets;
+ }
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/jsonobjects/GardenJson.java b/src/main/java/at/hannibal2/skyhanni/utils/jsonobjects/GardenJson.java
index 0a5a76c43..7f165ec1d 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/jsonobjects/GardenJson.java
+++ b/src/main/java/at/hannibal2/skyhanni/utils/jsonobjects/GardenJson.java
@@ -1,14 +1,21 @@
package at.hannibal2.skyhanni.utils.jsonobjects;
+import at.hannibal2.skyhanni.features.garden.CropType;
import com.google.gson.annotations.Expose;
+import java.util.List;
import java.util.Map;
public class GardenJson {
+ @Expose
+ public List<Integer> garden_exp;
+
+ @Expose
+ public Map<CropType, List<Integer>> crop_milestones;
@Expose
public Map<String, Double> organic_matter;
@Expose
public Map<String, Double> fuel;
-}
+} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt b/src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt
index 7407d5c6b..81ddaabde 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt
@@ -8,6 +8,7 @@ import io.github.moulberry.moulconfig.gui.GuiScreenElementWrapper
import io.github.moulberry.notenoughupdates.util.Utils
import net.minecraft.client.Minecraft
import net.minecraft.client.gui.Gui
+import net.minecraft.client.gui.GuiChat
import net.minecraft.client.gui.inventory.GuiEditSign
import net.minecraft.client.renderer.GlStateManager
import net.minecraft.item.ItemStack
@@ -113,7 +114,10 @@ interface Renderable {
if (isHovered(posX, posY)) {
if (condition() && shouldAllowLink(true, bypassChecks)) {
list[Pair(posX, posY)] = indexes
+ GlStateManager.pushMatrix()
+ GlStateManager.translate(0F, 0F, 400F)
RenderLineTooltips.drawHoveringText(posX, posY, tips, stack)
+ GlStateManager.popMatrix()
}
} else {
if (list.contains(Pair(posX, posY))) {
@@ -190,7 +194,11 @@ interface Renderable {
override val height = 10
override fun render(posX: Int, posY: Int) {
+ GlStateManager.pushMatrix()
+ if (Minecraft.getMinecraft().currentScreen == null || Minecraft.getMinecraft().currentScreen is GuiChat)
+ GlStateManager.translate(0F, 0F, -145F)
any.renderOnScreen(0F, 0F, scaleMultiplier = scale)
+ GlStateManager.popMatrix()
}
}
diff --git a/src/main/resources/assets/skyhanni/folder.png b/src/main/resources/assets/skyhanni/folder.png
new file mode 100644
index 000000000..f4af73530
--- /dev/null
+++ b/src/main/resources/assets/skyhanni/folder.png
Binary files differ
diff --git a/src/main/resources/assets/skyhanni/logo.png b/src/main/resources/assets/skyhanni/logo.png
new file mode 100644
index 000000000..8be408cf1
--- /dev/null
+++ b/src/main/resources/assets/skyhanni/logo.png
Binary files differ
diff --git a/src/test/java/at/hannibal2/skyhanni/test/ItemModifierTest.kt b/src/test/java/at/hannibal2/skyhanni/test/ItemModifierTest.kt
index 0fc172230..00e820566 100644
--- a/src/test/java/at/hannibal2/skyhanni/test/ItemModifierTest.kt
+++ b/src/test/java/at/hannibal2/skyhanni/test/ItemModifierTest.kt
@@ -1,7 +1,6 @@
package at.hannibal2.skyhanni.test
import at.hannibal2.skyhanni.utils.ItemUtils.isEnchanted
-import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getDungeonStarCount
import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getEnchantments
import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getHotPotatoCount
import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getItemUuid
@@ -23,6 +22,6 @@ class ItemModifierTest {
assert(itemStack.getHotPotatoCount() == 15)
assert(itemStack.getEnchantments()?.size == 11)
assert(itemStack.hasArtOfPeace())
- assert(itemStack.getDungeonStarCount() == 10)
+// assert(itemStack.getDungeonStarCount() == 10)
}
} \ No newline at end of file