diff options
164 files changed, 4448 insertions, 1070 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 8cc06f797..d4da09549 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,34 @@ + Added keybind to manually reset the barn/worm fishing timer. - CarsCupcake + Added timer till shared inquisitors will despawn. - hannibal2 + Account upgrade complete reminder. - appable0 ++ Chat message how many places you dropped in the farming weight lb when joining garden. ++ Added command /shfarmingprofile [player name] ++ Opens the elitebot.dev website in your web browser to show your Farming Weight profile. ++ Pet Experience Tooltip + + Show the full pet exp and the progress to level 100 (ignoring rarity) when hovering over a pet while pressing + shift key. ++ Anita Extra Farming Fortune: + + Show current tier and cost to max out in the item tooltip. ++ Sync Jacob Contests - Kaeso + CalMWolfs + + No need to open the calendar every SkyBlock year again. + + Grab Jacob Contest data from the elitebot.dev website. + + Option to send local contest data to elitebot.dev at the start of the new SkyBlock year. ++ Added **SkyHanni Installer** - NetheriteMiner + + Double-clicking the mod jar file will open a window that asks you where to move the mod into. ++ Added Chat Translator - NetheriteMiner + + After enabling, click on any chat message sent by another player to translate it to English. ++ Show the progress bar until maxed crop milestone in the crop milestone inventory. - hannibal2 ++ Show a line to the enderman slayer beacon. - hannibal2 ++ Added **Default Option Settings:** - nea + + Enables or disables all features at once, or per category. + + Sends a chat message on first SkyHanni startup (starting with this feature, so this version everyone will see this + message). + + Shows new features after an update (starting with the next beta, not this one). + + Allows to change those settings anytime again with /shdefaultoptions. ++ While on the Winter Island, show a timer until Jerry's Workshop closes. - hannibal2 ++ Added Reindrake support to the Damage Indicator. - hannibal2 ++ Added visual garden plot borders. - VixidDev + + Press F3 + G to enable/disable the view. ### Changes @@ -45,6 +73,29 @@ + Chest Value now works with Backpack and Ender Chest. - HiZe + Only works if NEU storage is not active. + Removed distance checks when detecting sea creatures for fishing timer. - hannibal2 ++ Added Enchantments Cap to EstimatedItemValue. - hannibal2 + + Only show the top # most expensive enchantments on an item. ++ Count sea emperor and rider of the deep twice against sea creature cap. ++ Clicking on the chat message from farming weight will run the /shfarmingprofile command. ++ Changed Bestiary Display number format - HiZe ++ Changed ff buffs for Elephant and Anita. ++ Changed chicken head timer from 20s to 5s. ++ Added option to show reputation locations only when pressing the hotkey. ++ Delay the custom garden level up message by a few milliseconds to not cut into the garden milestone message. ++ Added runic support for Zealots/Bruiser. ++ Added cultivating and replenish to the visitor rewards. - ReyMaratov ++ Added Bee pet support to /ff - derholzmann12321 ++ Added exportable carrot to /ff. - CalMWolfs + + If SkyHanni doesn't know you have it, run /shcarrot ++ The damage indicator now includes a toggle option for the Ender Slayer Laser Phase timer. - hannibal2 ++ Added ender slayer beacon explode timer. - hannibal2 ++ Show the name over Nukekubi Skulls for in ender slayer (deadly eyes). - hannibal2 ++ Changed the enderman slayer laser timer to be more exact. - hannibal2 ++ Added support for the new fixed inquisitor spawn message from Hypixel for the detection. - hannibal2 ++ Added option to hide the off-screen drop chat message. - hannibal2 ++ Now hides the farming weight display by default when below 200 weight (can be disabled). - hannibal2 ++ Added option to change the Enderman Slayer beacon color. - hannibal2 ++ Added option to show a line to every slayer mini boss around you. - hannibal2 ### Fixes @@ -71,6 +122,36 @@ + Fixed Sea Creature Timer not working on barn. - hannibal2 + Arachne boss highlighter no longer requires damage indicator to be enabled. - hannibal2 + /shtrackcollection Cactus now detects cactus green. hannibal2 ++ Fixed arachne minis falsely show in damage indicator. ++ Fixed rare cases where special laptop keys trigger behavior unintended. - hannibal2 ++ Fixed rendering problems with stack background and custom text lore. - nea ++ Hopefully fixed Derpy problems with Trevor Trapper, Arachne, Arachne Keeper and Zealots. ++ Fixed Anita upgrade detection from the Anita Shop inventory. ++ Fixed error message when clicking a finished upgrade in the community shop. ++ Fixed everything **crop milestone** related. - CalMWolfs ++ Fixed estimated item value detects master stars on non-dungeon items. - hannibal2 ++ Fixed wrong progress bar for pet exp display. - hannibal2 ++ Fixed compatibility problem with NEU for pet exp number format. - hannibal2 ++ Various **/ff fixes** - CalMWolfs ++ Numbers, rounding and pets being reset. ++ Fixed inventory item number offset being wrong. - CalMWolfs ++ Fixed slayer quest detection after death. - hannibal2 ++ Fixed rounding errors with yaw and pitch display. - hannibal2 ++ Fixed ender slayer beacon don't disappear sometimes. - hannibal2 ++ Fixed multiple bugs with garden visitor: - hannibal2 + + Visitors with multiple different crops now calculate the copper price and the visitor drop stats correctly. + + Reward items no longer impact the visitor drop coins spent data negatively. + + Copper per coin price now respects the reward item profit as well. + + Now showing the NPC price for items without ah/bazaar data (looking at pet candy). ++ Now correctly ignoring the minis from tier 2 Arachne in the Damage Indicator. - hannibal2 ++ Fixed highlight in the main bestiary menu. - HiZe ++ Fixed maxed farming fortune possible in /ff - CalMWolfs ++ Fixed negative coins per copper price in visitor inventory. - hannibal2 ++ Fixed rare error message while farming. - hannibal2 ++ Fixed a rare error message while showing the lore of a farming tool. - hannibal2 ++ Fixed estimated item value doesn't detect master stars in Auction House. - hannibal2 ++ Fixed enderman slayer beacon warning only visible for a very short amount of time. - hannibal2 ++ Fixed enderman slayer line to beacon only shows when beacon highlight is enabled. - hannibal2 ### Removed Features @@ -78,6 +159,9 @@ - (Hypixel fixed their bug, finally) - Removed remaining **Hypixel API** support for still existing legacy api keys. - hannibal2 - This should not affect much + - +- Removed wishing compass in item number. + - Every Wishing Compass now only has one use instead of three. ## Version 0.19 @@ -185,7 +269,7 @@ + Show all commands in SkyHanni + Added Attribute price support to Estimated Item Value - nea + Added warning when enderman slayer beacon spawns - dragon99z -+ Added Highlight enderman slayer Nukekebi (Skulls) - dragon99z ++ Added Highlight enderman slayer Nukekubi (Skulls) - dragon99z + Added option to hide the vanilla particles around enderman + Hide particles around enderman slayer bosses and mini bosses + Added support for Shadow Fury abilty cooldown - HiZe diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6de14399a..23433bfc8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,19 +1,161 @@ # How to Contribute -This tutorial explains how to set up a development environment to work on SkyHanni. We use [IntelliJ](https://www.jetbrains.com/idea/) as an example. +This is a technical guide that helps Kotlin and Java developers understand how SkyHanni works, and provides the first +steps for new Forge developers to take. -## Basics -SkyHanni is a 1.8.9 Forge mod, written in [Kotlin](https://kotlinlang.org/) and [Java](https://www.java.com/en/). -We use a [gradle config](https://gradle.org/) to build the mod, -written in [Kotlin DSL](https://docs.gradle.org/current/userguide/kotlin_dsl.html). +# Set up the development environment -This development environment uses [DevAuth](https://github.com/DJtheRedstoner/DevAuth) to allow connecting to Hypixel while debugging in IntelliJ. +When making changes to the code, it is recommended to use an IDE for live debugging and testing. +This tutorial explains how to set up the development environment for SkyHanni. +We use [IntelliJ](https://www.jetbrains.com/idea/) as an example. -## Setup +## Download IntelliJ -### Download IntelliJ -- Download IntelliJ from [JetBrains Website](https://www.jetbrains.com/idea/download/). -- Use Community Edition. -- ![image](https://github.com/hannibal002/SkyHanni/assets/24389977/68b9044c-42d0-44ba-85f7-9848a35a27b2) +- Download IntelliJ from the [JetBrains Website](https://www.jetbrains.com/idea/download/). + - Use the Community Edition. (Scroll down a bit.) -In Progress - more later +## Cloning the project + +- Create an account on GitHub + - Go to https://github.com/hannibal002/SkyHanni + - Click on the fork button to create a fork. + - Leave the settings unchanged + - Click on `create fork` + - Open IntelliJ + - Link the GitHub account with IntelliJ. + - Install Git in IntelliJ. + - In IntelliJ, go to `new` → `project from version control`. + - Select `SkyHanni` from the list. + - Open the project. + +## Setting up IntelliJ + +SkyHanni's Gradle configuration is very similar to the one used in **NotEnoughUpdates**; just follow this guide: +https://github.com/NotEnoughUpdates/NotEnoughUpdates/blob/master/CONTRIBUTING.md + +# Software Used in SkyHanni + +## Core + +SkyHanni is a Forge mod for Minecraft 1.8.9, written in [Kotlin](https://kotlinlang.org/) +and [Java](https://www.java.com/en/). + +We use a [Gradle configuration](https://gradle.org/) to build the mod, +written in [Kotlin DSL](https://docs.gradle.org/current/userguide/kotlin_dsl.html): +[build.gradle.kts](https://github.com/hannibal002/SkyHanni/blob/beta/build.gradle.kts) + +This start script will automatically download all required libraries. + +## NotEnoughUpdates + +SkyHanni requires NEU. +We use NEU to get auction house and bazaar price data for items and to read +the [NEU Item Repo](https://github.com/NotEnoughUpdates/NotEnoughUpdates-REPO) for item internal names, display names +and recipes. + +For more information, see https://github.com/NotEnoughUpdates/NotEnoughUpdates + +## Config + +SkyHanni uses the config system from NEU. + +For more information, see https://github.com/NotEnoughUpdates/MoulConfig + +## Elite Farmers API + +SkyHanni utilizes the [Elite API](https://api.elitebot.dev/) (view the [public site here](https://elitebot.dev)) for some farming features. + +This includes features relating to Farming Weight, as well as syncing jacob contests amongst players for conviencience. All data sent is anonymonized and opt-in. + +## Mixin + +A system to inject code into the original Minecraft code. +This library is not part of SkyHanni itself; it comes preinstalled with Forge. + +For more information, see https://github.com/SpongePowered/Mixin. + +## Repo + +SkyHanni uses a repo system to easily change static variables without the need for a mod update. +The repo is located at https://github.com/hannibal002/SkyHanni-REPO. +A copy of all files in the repo is stored for every SkyHanni user under `.minecraft\config\skyhanni\repo`. +On every game start, the copy gets updated (if outdated and if not manually disabled). +When working with the repo, it is recommended to disable the manual repo update to prevent overriding your local changes +accidentally. + +## DiscordIPC + +DiscordIPC is a service that SkyHanni uses to send information from SkyBlock to Discord in Rich Presence. <br> +Specifically, we use [TirelessTraveler's Fork](https://github.com/ILikePlayingGames/DiscordIPC) of a fork of a fork of +the [original](https://github.com/jagrosh/DiscordIPC). +For info on usage, look +at [DiscordRPCManager.kt](https://github.com/hannibal002/SkyHanni/blob/beta/src/main/java/at/hannibal2/skyhanni/features/misc/discordrpc/DiscordRPCManager.kt) + + +## Auto Updater + +We use the [auto update library](https://repo.nea.moe/#/releases/moe/nea/libautoupdate) from nea. + +# Coding Styles and Conventions + +- Follow the [Hypixel Rules](https://hypixel.net/rules). +- Use the coding conventions for [Kotlin](https://kotlinlang.org/docs/coding-conventions.html) + and [Java](https://www.oracle.com/java/technologies/javase/codeconventions-contents.html). +- Do not copy features from other mods. Exceptions: + - Paid only mods. + - Mods that have reached the end of life. (Rip SBA, Dulkir and Soopy) + - The mod has, according to Hypixel rules, illegal features ("cheat mod"). + - If you can improve the existing feature in a meaningful way. +- All classes should be written in Kotlin, with a few exceptions: + - Config files in `at.hannibal2.skyhanni.config.features` + - Mixin classes in `at.hannibal2.skyhanni.mixins.transformers` + - Java classes that represent JSON data objects in `at.hannibal2.skyhanni.utils.jsonobjects` +- Please use the existing event system, or expand on it. Do not use Forge events. + - (We inject the calls with Mixin) +- Please use existing utils methods. +- We try to avoid calling the NEU code too often. + - (We plan to remove NEU as a dependency in the future.) +- We try not to use Forge-specific methods if possible. + - (We plan to switch to Fabric and Minecraft 1.20 in the future.) +- Please try to avoid using `System.currentTimeMillis()`. Use our own class `SimpleTimeMark` instead. + - See [this commit](https://github.com/hannibal002/SkyHanni/commit/3d748cb79f3a1afa7f1a9b7d0561e5d7bb284a9b) + as an example. + +# Additional Useful Developement Tools + +## DevAuth + +[DevAuth](https://github.com/DJtheRedstoner/DevAuth) is a tool that allows logging in to a Minecraft account while +debugging in IntelliJ. This is very useful for coding live on Hypixel without the need to compile a jar, put it into the +`mods` folder, and start the Minecraft launcher manually. + +- The library is already downloaded by Gradle. +- Create the config folder (Windows only). For other OSes, use the guide from DJtheRedstoner. + - Navigate to `C:\Users\<your username>` + - Create a new folder `.devauth` + - Navigate to `C:\Users\<your username>\.devauth` + - Create a new file `config.toml` + - Paste this text into the file: (Don't change anything.) + +``` +defaultEnabled = true + +defaultAccount = "main" + +[accounts.main] +type = "microsoft" +``` + +- Start Minecraft inside IntelliJ normally. + - Click on the link in the console and verify with a Mojang account. + - The verification process will reappear every few days (after the session token expires). + +## Hot Swap + +Hot Swap allows reloading edited code while debugging, removing the need to restart the whole game every time. + +We use [dcevm](https://dcevm.github.io/) and the IntelliJ +Plugin [HotSwap Agent](https://plugins.jetbrains.com/plugin/9552-hotswapagent) to quickly reload code changes. + +Follow [this](https://forums.Minecraftforge.net/topic/82228-1152-3110-intellij-and-gradlew-forge-hotswap-and-dcevm-tutorial/) +tutorial. diff --git a/FEATURES.md b/FEATURES.md index f367bb5ab..5ca78939b 100644 --- a/FEATURES.md +++ b/FEATURES.md @@ -1,6 +1,6 @@ # SkyHanni - List of all Features -> Use /skyhanni or /sh to open the SkyHanni config in game +Use `/sh` or `/skyhanni` to open the SkyHanni config in game. ## Chat Filter @@ -15,20 +15,22 @@ ## Chat -- Options to change the player chat format (show prefix for channel 'all', hide player rank color, hide colon after ++ Options to change the player chat format (show prefix for channel 'all', hide player rank color, hide colon after player name, hide/change SkyBlock level format, hide/change elite position format, edit channel prefix design) -- Using a clean chat format for player messages (removing the rank prefix, every player writes in the same color) -- Dungeon Filter (Removing annoying chat messages from the dungeon) -- Dungeon Boss Message hider (includes The Watcher as well) -- Option to hide the death messages of other players, except for players who are close to the player, inside the dungeon ++ Using a clean chat format for player messages (removing the rank prefix, every player writes in the same color) ++ Dungeon Filter (Removing annoying chat messages from the dungeon) ++ Dungeon Boss Message hider (includes The Watcher as well) ++ Option to hide the death messages of other players, except for players who are close to the player, inside the dungeon or during a Kuudra fight. -- Scan messages sent by players in all-chat for blacklisted words and greys out the message. -- Chat peeking (holding key to display chat without opening the chat gui) -- Compact Potion Effect Messages -- **Arachne Chat Hider** - - Hide chat messages about the Arachne Fight while outside of Arachne's Sanctuary ++ Scan messages sent by players in all-chat for blacklisted words and greys out the message. ++ Chat peeking (holding key to display chat without opening the chat gui) ++ Compact Potion Effect Messages ++ **Arachne Chat Hider** + + Hide chat messages about the Arachne Fight while outside of Arachne's Sanctuary + Option to shorten the **bestiary level-up** message. ++ Chat **Translator** - NetheriteMiner + + After enabling, click on any chat message sent by another player to translate it to English. ## Dungeon @@ -198,10 +200,16 @@ ## Slayer + Hide poor slayer drop chat messages. -+ Highlight slayer miniboss in blue color. -+ Highlight the enderman slayer Yang Glyph (Beacon) in red color (supports beacon in hand and beacon flying) -+ Warning when enderman slayer beacon spawns - dragon99z -+ Highlight enderman slayer Nukekebi (Skulls) - dragon99z ++ Slayer **Mini Boss:** + + Highlight the mob. + + Show a line from player crosshair to the mob. ++ Enderman Slayer **Yang Glyph**: + + Highlight the beacon in red color. + + Supports beacon in hand and beacon flying. + + Show timer till it explodes. + + Show a line to the beacon. - hannibal2 + + Warning when enderman slayer beacon spawns - dragon99z ++ Highlight enderman slayer Nukekubi (Skulls) - dragon99z + 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. + Cooldown when the Fire Pillar from the Blaze Slayer will kill you. @@ -277,7 +285,7 @@ + Highlight corrupted mobs. + **Arachne Minis Hider** - Hides the nametag above arachne minis. + **Arachne Boss Highlighter** - Highlight the arachne boss in red and mini bosses and orange. -+ Added option to hide the vanilla particles around enderman ++ Option to hide the vanilla particles around enderman ## Garden Features @@ -287,6 +295,7 @@ to checked what items it needs. + **Show Price** - Show the bazaar price of the items required for the visitors. + **Crop Milestone** Number - Show the number of crop milestone in the inventory. ++ Show the progress bar until maxed crop milestone in the crop milestone inventory. - hannibal2 + **Crop Upgrades** Number - Show the number of upgrades in the crop upgrades inventory. + **Visitor Timer** - Timer when the next visitor will appear, and a number how many visitors are already waiting. + **Visitor Notification** - Show as title and in chat when a new visitor is visiting your island. @@ -307,6 +316,7 @@ + provided by the elite skyblock farmers. + next leaderboard position eta. + Instantly showing the next player in the lb when passing someone on the leaderboard. - Kaeso + + Chat message how many places you dropped in the farming weight lb when joining garden. + **Dicer Counter** - Count RNG drops for Melon Dicer and Pumpkin Dicer. + **Warn When Close** - Warn with title and sound when the next crop milestone upgrade happens in 5 seconds. Useful for switching to a different pet for leveling. @@ -325,8 +335,12 @@ require any crop) + **Money per Hour Advanced stats** - Show not only Sell Offer price but also Instant Sell price and NPC Sell price ( Suggestion: Enable Compact Price as well for this) -+ **Anita Medal Profit** - Helps to identify profitable items to buy at the Anita item shop and potential profit from - selling the item at the auction house. ++ **Anita Inventory** + + **Medal Profit** + + Helps to identify profitable items to buy at the Anita item shop and potential profit from + + selling the item at the auction house. + + **Extra Farming Fortune** + + Show current tier and cost to max out in the item tooltip. + **Composter Compact Display** - Displays the compost data from the tab list in a compact form as gui element. + **Composter Upgrade Price** - Show the price for the composter upgrade in the lore + **Highlight Upgrade** - Highlight Upgrades that can be bought right now. @@ -384,6 +398,12 @@ + Override the Overtake ETA to show when you will reach the specified rank + If not there yet + Default: #10k ++ Sync Jacob Contests - Kaeso + CalMWolfs + + No need to open the calendar every SkyBlock year again. + + Grab Jacob Contest data from the elitebot.dev website. + + Option to send local contest data to elitebot.dev at the start of the new SkyBlock year. ++ Added visual garden plot borders. - VixidDev + + Press F3 + G to enable/disable the view. ## The Rift @@ -422,7 +442,7 @@ + Helps to solve the dance room in the mirror verse by showing multiple tasks at once. + Change how many tasks you should see + Hide other players inside the dance room - + Added timer before next instruction + + Timer before next instruction + Option to hide default title (instructions, "Keep it up!" and "It's happening!") + Fully customize the description for now, next and later (with color) + **Upside Down** Parkour & **Lava Maze** - hannibal2 @@ -436,7 +456,7 @@ + Living Metal Suit Progress - HiZe + Display progress Living Metal Suit (Default disabled) + Option to show a compacted version of the overlay when the set is maxed -+ Added Highlight for Blobbercysts in Bacte fight in colloseum in rift - HiZe ++ Highlight for Blobbercysts in Bacte fight in colloseum in rift - HiZe + Show a line between **Defense blocks** and the mob and highlight the blocks - hannibal2 + Hide particles around Defense Blocks + Show a moving animation between **Living Metal** and the next block - hannibal2 @@ -472,6 +492,8 @@ particular item based on the current crop speed. + `/pt <player>` as alias for `/party transfer <player>` + SkyBlock Command `/tp` to check the play time still works ++ **/shfarmingprofile [player name]** + + Opens the elitebot.dev website in your web browser to show your Farming Weight profile. ## Misc @@ -537,11 +559,13 @@ + Show Ice per hour + Customizable GUI + Option to hide the chat messages ++ While on the Winter Island, show a timer until Jerry's Workshop closes. - hannibal2 + **Custom Text Box** - CalMWolfs + Write fancy text into a gui element to show on your screen at all time + Supports color codes + Supports line breaks `\n` - hannibal2 -+ Added /sendcoords sending, detecting and rendering - dragon99z ++ **/sendcoords** - dragon99z + + Sending, detecting and rendering. + Add Dungeon Potion level as item stack size - HiZe + **Ender Node Tracker** - pretz + Tracks items and profit obtained from mining ender nodes and killing normal endermen. @@ -553,4 +577,15 @@ + **Inventory Numbers** + Show the number of the teleport pads inside the 'Change Destination' inventory as stack size. + Only on Private island. -+ Account upgrade complete reminder. - appable0
\ No newline at end of file ++ Account upgrade complete reminder. - appable0 ++ Pet Experience Tooltip + + Show the full pet exp and the progress to level 100 (ignoring rarity) when hovering over an pet while pressing + shift key. ++ **SkyHanni Installer** - NetheriteMiner + + Double-clicking the mod jar file will open a window that asks you where to move the mod into. ++ **Default Option Settings:** - nea + + Enables or disables all features at once, or per category. + + Sends a chat message on first SkyHanni startup (starting with this feature, so this version everyone will see this + message). + + Shows new features after an update (starting with the next beta, not this one). + + Allows to change those settings anytime again with /shdefaultoptions.
\ No newline at end of file diff --git a/INSTALLING.md b/INSTALLING.md new file mode 100644 index 000000000..07bdea45e --- /dev/null +++ b/INSTALLING.md @@ -0,0 +1,133 @@ +# Download and Install SkyHanni + +SkyHanni is a Forge mod for **Minecraft 1.8.9 only**. +Trying to run this on Badlion, Lunar, Feather, or newer versions of Minecraft is **not supported**. + +Follow this guide to install SkyHanni in regular Minecraft Forge. +If you already have Forge mods, you can skip to step 4. Otherwise, start from step 1. +If you already have the latest alpha version from NEU, you can skip to step 5. + +<details> +<summary>1. Run vanilla 1.8.9</summary> + +Run Minecraft 1.8.9, unmodded, for 10 seconds, then close it. + +</details> + + +<details> +<summary>2. Install Java</summary> + +To play with mods, you need Java. +Install [Java 8](https://www.java.com/download/ie_manual.jsp). +Double-click the file to install it. + +</details> + + +<details> +<summary>3. Install Forge</summary> + +Forge is the system that loads your mods into the game. +You need Java to run Forge. +Download [Forge for 1.8.9](https://files.minecraftforge.net/net/minecraftforge/forge/index_1.8.9.html). +Click installer, when you double-click the file, install as client. +If Forge does not open with Java, download [Jarfix](https://johann.loefflmann.net/en/software/jarfix/index.html), +double click it, then try running Forge again. + +</details> + + +<details> +<summary>4. Download NEU</summary> + +Neu is NotEnoughUpdates, another Forge mod that contains files that SkyHanni depends on to function. +You can install it from [Moulberry's Bush Discord Server](https://discord.gg/moulberry) in the +channel [#🧪neu-alphas](https://discord.com/channels/516977525906341928/1028896920346841118) or +from [SkyHanni Discord](https://discord.com/invite/skyhanni-997079228510117908) in the +channel [#neu-updates](https://discord.com/channels/997079228510117908/1123201092193366027) + +</details> + + +<details> +<summary>5. Download SkyHanni</summary> + +SkyHanni has 2 update circles: [Full Release](https://github.com/hannibal002/SkyHanni/releases/latest) +and [Beta](https://github.com/hannibal002/SkyHanni/releases). + +In general, it is recommended to use the **Full Release**. +It updates every 3–4 weeks and should run very stable. +If you find bugs or miss features in the full version, they might be fixed/implemented already in a beta version. + +The **Beta Version**, on the other hand, gets updated multiple times a week, +has new features earlier, but also may contain more bugs. + +</details> + + +<details> +<summary>6. Find .minecraft</summary> + +Once you have downloaded both NEU and SkyHanni, you need to navigate to your `.minecraft` folder. +On Windows, open file explorer, in the file location bar at the top type in `%appdata%` and open `.minecraft`. +On Mac, go to `~/Library/Application Support/minecraft`. + +</details> + + +<details> + +<summary>7. Move mods into mods folder</summary> + +If there is a "mods" folder, great! Open it. +Otherwise, create one and name it exactly "mods". + +Move both your downloaded NEU file and SkyHanni file into the folder. +(If you have already an older version of NEU or SkyHanni in that folder, delete it.) + +*Note: if you have a problem, people may ask to see your mod folder - that is this folder.* + +</details> + + +<details> +<summary>8. Setup RAM</summary> + +If you're running mods, you also need to set up your allocated ram. +If you don't know how much ram your computer has, +follow [this guide](https://www.howtogeek.com/435644/how-to-see-how-much-ram-is-in-your-pc-and-its-speed/). +To allocate ram, go to installation, press the 3 dots next to the installation you are using, +click edit, press more options. +In JVM arguments, look for something that says -Xmx2G or some other number followed by G. +That number is the amount you have allocated for Minecraft to use. +If you have 2G of ram on your computer, you might struggle to play Minecraft. +Try to allocate 1G. If you have 4G, allocate 2G. If you +have 8 or more G, allocate 4G. +You should never need more than 4G, unless you have more mods, than you know what to do. + +</details> + + +<details> +<summary>9. Launch the Forge profile in the launcher</summary> + +Installing Minecraft Forge should have set the profile for you, but if it didn't, go to installations, +select new installation, under version you need to find Forge for 1.8.9 (most likely at the top or bottom) + +</details> + + +<details> +<summary>10. Recommended additional mods (optional)</summary> + +[OptiFine](https://optifine.net/adloadx?f=preview_OptiFine_1.8.9_HD_U_M6_pre2.jar) +and [Patcher](https://sk1er.club/mods/patcher). +Those two mods help you get more FPS in game and let you change many more performance +settings. + +*Ask on discord if you need help with those.* + +</details> + +<h1>And finally, don't forget to <i><b>never run a file that is sent to you in dms</b></i></h1>
\ No newline at end of file diff --git a/OPEN_SOURCE_SOFTWARE.md b/OPEN_SOURCE_SOFTWARE.md index 108d2a707..18e4dfe62 100644 --- a/OPEN_SOURCE_SOFTWARE.md +++ b/OPEN_SOURCE_SOFTWARE.md @@ -12,4 +12,4 @@ SkyHanni would not be possible without the following open source software: | [Skytils](https://github.com/Skytils/SkytilsMod) | [AGPL 3.0](https://github.com/Skytils/SkytilsMod/blob/1.x/LICENSE.md) | | [Forge1.8.9Template](https://github.com/romangraef/Forge1.8.9Template) | [Unlicensed](https://github.com/romangraef/Forge1.8.9Template/blob/master/LICENSE) | | [SoopyV2](https://github.com/Soopyboo32/SoopyV2) | [GPL 3.0](https://github.com/Soopyboo32/SoopyV2/blob/master/LICENSE) | -| [DiscordIPC](https://github.com/jagrosh/DiscordIPC) | [Apache 2.0](https://github.com/jagrosh/DiscordIPC/blob/master/LICENSE) | +| [DiscordIPC](https://github.com/jagrosh/DiscordIPC) | [Apache 2.0](https://github.com/jagrosh/DiscordIPC/blob/master/LICENSE) | @@ -4,11 +4,24 @@ <div align="center"> -[![discord badge](https://img.shields.io/discord/997079228510117908?label=discord&color=9089DA&logo=discord&style=for-the-badge)](https://discord.gg/8DXVN4BJz3) +[![discord badge](https://img.shields.io/discord/997079228510117908?label=discord&color=9089DA&logo=discord&style=for-the-badge)](https://discord.gg/skyhanni-997079228510117908) [![made with kotlin](https://img.shields.io/badge/Made%20With-Kotlin-orange?style=for-the-badge&logo=kotlin&logocolor=white)](https://kotlinlang.org/) [![downloads](https://img.shields.io/github/downloads/hannibal002/SkyHanni/total?label=downloads&color=208a19&logo=github&style=for-the-badge)](https://github.com/hannibal00212/SkyHanni/releases) </div> -SkyHanni is a Minecraft modification that adds new features to Hypixel Skyblock. It is in beta, so expect bugs. +SkyHanni is a Forge mod for Minecraft 1.8.9. It adds many features to Hypixel SkyBlock. +The mod is filled with GUIs, extra chat messages, reminders, message hiders and entity highlighters. +The majority of these features are centered on the Garden, Slayer, Bingo, Diana, and Rift. -Exhaustive List of all features so far: https://github.com/hannibal002/SkyHanni/blob/beta/FEATURES.md +We have a [tutorial](https://github.com/hannibal002/SkyHanni/blob/beta/INSTALLING.md) +for how to download and install the mod. + +Use `/sh` or `/skyhanni` to open the SkyHanni config in game. + +[Here](https://github.com/hannibal002/SkyHanni/blob/beta/FEATURES.md) is a large list of all features. + +For bug reports, feature requests, and other feedback, please visit +our [Discord](https://discord.gg/skyhanni-997079228510117908). + +If you are interested in the technical side of SkyHanni, read +the [Contributing Guide](https://github.com/hannibal002/SkyHanni/blob/beta/CONTRIBUTING.md).
\ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index bf09a1abe..9f23b3a07 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -11,7 +11,7 @@ plugins { } group = "at.hannibal2.skyhanni" -version = "0.20.Beta.8" +version = "0.20.Beta.14" // Toolchains: java { @@ -34,6 +34,7 @@ repositories { } } maven("https://repo.nea.moe/releases") + maven("https://maven.notenoughupdates.org/releases") } val shadowImpl by configurations.creating { @@ -87,10 +88,10 @@ dependencies { isTransitive = false } - shadowModImpl("com.github.NotEnoughUpdates:MoulConfig:1.1.5") - devenvMod("com.github.NotEnoughUpdates:MoulConfig:1.1.5:test") + shadowModImpl(libs.moulconfig) + devenvMod(variantOf(libs.moulconfig) { classifier("test") }) - shadowImpl("moe.nea:libautoupdate:1.0.3") + shadowImpl(libs.libautoupdate) shadowImpl("org.jetbrains.kotlin:kotlin-reflect:1.9.0") // testImplementation(kotlin("test")) @@ -161,6 +162,7 @@ tasks.withType(Jar::class) { manifest.attributes.run { this["FMLCorePluginContainsFMLMod"] = "true" this["ForceLoadAsMod"] = "true" + this["Main-Class"] = "SkyHanniInstallerFrame" // If you don't want mixins, remove these lines this["TweakClass"] = "org.spongepowered.asm.launch.MixinTweaker" diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 000000000..376f286e7 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,7 @@ +[versions] +libautoupdate = "1.0.3" +moulconfig = "1.2.0" + +[libraries] +moulconfig = { module = "org.notenoughupdates.moulconfig:MoulConfig", version.ref = "moulconfig" } +libautoupdate = { module = "moe.nea:libautoupdate", version.ref = "libautoupdate" } 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 Binary files differnew file mode 100644 index 000000000..f4af73530 --- /dev/null +++ b/src/main/resources/assets/skyhanni/folder.png diff --git a/src/main/resources/assets/skyhanni/logo.png b/src/main/resources/assets/skyhanni/logo.png Binary files differnew file mode 100644 index 000000000..8be408cf1 --- /dev/null +++ b/src/main/resources/assets/skyhanni/logo.png 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 |