diff --git a/.github/workflows/assign-relevant-labels.yml b/.github/workflows/assign-relevant-labels.yml new file mode 100644 index 000000000000..4118c7172093 --- /dev/null +++ b/.github/workflows/assign-relevant-labels.yml @@ -0,0 +1,64 @@ +name: "Assign relevant labels" +on: + pull_request_target: + types: [ opened, edited ] +jobs: + assign-label: + if: github.event.pull_request.state == 'open' + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + contents: read + steps: + - name: label + env: + TITLE: ${{ github.event.pull_request.title }} + LABEL_FIX: Bug Fix + LABEL_BACKEND: Backend + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GITHUB_TOKEN}} + script: | + const labelsToAdd = []; + const labelsToRemove = []; + const title = process.env.TITLE.split(":")[0].toUpperCase(); + + if(title.includes("FIX")){ + labelsToAdd.push(process.env.LABEL_FIX); + } else { + labelsToRemove.push(process.env.LABEL_FIX); + } + + if(title.includes("BACKEND")){ + labelsToAdd.push(process.env.LABEL_BACKEND); + } else { + labelsToRemove.push(process.env.LABEL_BACKEND); + } + + for (const label of labelsToAdd) { + github.rest.issues.addLabels({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + labels: [label] + }); + } + + const {data} = await github.rest.issues.listLabelsOnIssue({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + }); + + for (const label of labelsToRemove) { + const filtered = data.filter(l => l.name == label); + if(filtered.length == 1){ + github.rest.issues.removeLabel({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + name: label + }); + } + } diff --git a/.github/workflows/label-bug-fix.yml b/.github/workflows/label-bug-fix.yml deleted file mode 100644 index dae2980de630..000000000000 --- a/.github/workflows/label-bug-fix.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: "Bug Fix label" -on: - pull_request_target: - types: [ opened, edited ] -jobs: - assign-label: - if: github.event.pull_request.state == 'open' # Condition to check if PR is open - runs-on: ubuntu-latest - permissions: - issues: write - pull-requests: write - contents: read - steps: - - name: label - env: - TITLE: ${{ github.event.pull_request.title }} - LABEL: Bug Fix - Sooner than Very Soon - uses: actions/github-script@v7 - with: - github-token: ${{ secrets.GITHUB_TOKEN}} - script: | - if(process.env.TITLE.split(":")[0].toUpperCase().includes("FIX")){ - github.rest.issues.addLabels({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - labels: [process.env.LABEL] - }) - }else{ - const {data} = await github.rest.issues.listLabelsOnIssue({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - }) - const filtered = data.filter(label => label.name == process.env.LABEL) - if(filtered.length == 1){ - github.rest.issues.removeLabel({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - name: process.env.LABEL - }) - } - } diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index ce469091517f..6f2dcbba0155 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,6 +1,56 @@ # SkyHanni - Change Log -## Version 0.27 (in Beta) +## Version 0.28 (in Beta) + +### New Features + +#### Hoppity Features + ++ Added an easier way to check your unique Hoppity Eggs collected on each island. - martimavocado (https://github.com/hannibal002/SkyHanni/pull/2625) + + Shows your progress in the Warp Menu. + + Can be automatically hidden when an island is complete. + +#### Inventory Features + ++ Added Focus Mode. - Thunderblade73 (https://github.com/hannibal002/SkyHanni/pull/2694) + + In Focus Mode, only the name of the item is displayed instead of the full description. + +### Improvements + +#### Inventory Improvements + ++ Added Pocket Sack-in-a-Sack support to Estimated Item Value. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2698) + +#### Chat and Command Improvements + ++ Replaced repeated SkyHanni messages with the previous message. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2700) ++ Added support for Guilds in player-related tab completions. - ThatGravyBoat (https://github.com/hannibal002/SkyHanni/pull/2637) ++ Added support for all Guild and Friend commands in tab completions. - ThatGravyBoat (https://github.com/hannibal002/SkyHanni/pull/2637) + +### Fixes + +#### Fishing Fixes + ++ Fixed fishing displays showing in dungeons. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2697) + +#### Inventory Fixes + ++ Fixed "No Guardian Pet warning" not supporting Pet Rule "On open Experimentation Table". - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2699) ++ Fixed an error with compact experiment rewards chat messages. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2702) + +#### Combat Fixes + ++ Fixed Ghost Counter display appearing while in incorrect areas on the map. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2696) + +### Technical Details + ++ Assigned 'backend' label to PRs with 'backend' in the title. - CalMWolfs (https://github.com/hannibal002/SkyHanni/pull/2690) + + This does not change the functionality of the current bug fix label. ++ Added SuggestionProvider. - ThatGravyBoat (https://github.com/hannibal002/SkyHanni/pull/2637) + + This new class simplifies building suggestion trees. ++ Added Stats API. - Thunderblade73 (https://github.com/hannibal002/SkyHanni/pull/2253) + +## Version 0.27 ### New Features @@ -182,12 +232,14 @@ + Added an option to hide all tooltips inside the Fossil Excavator. - Cuz_Im_Clicks (https://github.com/hannibal002/SkyHanni/pull/2579) + Added support for using the Pickobulus ability for the Mineshaft Pity Display. - Empa (https://github.com/hannibal002/SkyHanni/pull/2540) + Added Area Navigation support to Glacite Tunnels. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2544) -+ Updated wording in mineshaft pity breakdown ("efficient miner" -> "spread"). - luna (https://github.com/hannibal002/SkyHanni/pull/2633) ++ Updated wording in mineshaft pity breakdown ("efficient miner" -> "spread"). - Luna (https://github.com/hannibal002/SkyHanni/pull/2633) ++ Improved the wording of the Mining Event data error chat message. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2671) ++ Added Mining Effects (Powder Pumpkin, Filet O' Fortune, and Chilled Pristine Potato) to the Non-God Effect Display. - jani (https://github.com/hannibal002/SkyHanni/pull/2677) #### Diana Improvements + Added /warp stonks to the Burrow Warp Helper. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2399) -+ Added per-election season Diana Trackers. - !nea (https://github.com/hannibal002/SkyHanni/pull/2487) ++ Added per-election season Diana Trackers. - nea (https://github.com/hannibal002/SkyHanni/pull/2487) + This includes the Diana Profit Tracker and the Mythological Creature Tracker. + The data is stored moving forward, but there is currently no way to view anything other than the current year. + Changed the Diana Profit Tracker and Mythological Creature Tracker to always be visible when holding the Ancestral Spade in hand, even if Diana is not the mayor. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2496) @@ -200,6 +252,7 @@ + Added an opacity slider for the Custom Background Image in the Custom Scoreboard. - Empa (https://github.com/hannibal002/SkyHanni/pull/1837) + Added an Undo message when auto alignment inCustom Scoreboard gets disabled. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2402) + Added an option to show SkyBlock time on the custom scoreboard rounded to 10 minutes, similar to the vanilla scoreboard. - Luna (https://github.com/hannibal002/SkyHanni/pull/2443) ++ Reduced the frequency of scoreboard errors being displayed. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2672) #### Inventory Improvements @@ -234,6 +287,7 @@ + Added the required chocolate amount to the tooltip of milestone rabbits in Hoppity's Collection. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2523) + Improved the responsiveness of Hoppity Chat Compacting. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2488) + Added the ability to see how many duplicates you have previously found in Hoppity messages. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2556) ++ Improved the formatting of the Hoppity Event Stats card. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2638) #### Combat Improvements @@ -256,12 +310,14 @@ + Made the waypoint to the middle of the plot for Pest Waypoint optional (off by default). - Luna (https://github.com/hannibal002/SkyHanni/pull/2469) + Reduced one click for supercrafting visitor materials by using `/viewrecipe` instead of `/recipe` when using the Shopping List button. - Miestiek (https://github.com/hannibal002/SkyHanni/pull/2505) + Added ignored crops for the Farming Lane feature. - martimavocado (https://github.com/hannibal002/SkyHanni/pull/2622) ++ Made the Visitor Timer GUI clickable to teleport to the Barn. - martimavocado (https://github.com/hannibal002/SkyHanni/pull/2658) #### Rift Improvements + Updated the description of the config for Enigma Soul Waypoints to help find the Rift Guide in the game. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2433) + Added Path Finder to Enigma Soul waypoints in the Rift. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2515) + Added the option to choose the color of the Living Metal Helper highlight. - MTOnline (https://github.com/hannibal002/SkyHanni/pull/2616) ++ Added an option to hide players while in Gunther's Rift Race. - MTOnline (https://github.com/hannibal002/SkyHanni/pull/2655) #### Dungeon Improvements @@ -287,6 +343,10 @@ + Added a warning in chat when the computer's time is inaccurate, along with a tutorial on how to fix it. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2623) + Improved the way pathfinding lines are rendered. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2634) + Automatically starts pathfinding after clicking on SkyHanni reminder chat messages about Carnival Reminder, Hoppity NPC, City Project, and account/profile upgrades. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2635) ++ Greatly improved performance by optimizing SkyHanni Chroma support for Patcher Font Renderer. - nopo (https://github.com/hannibal002/SkyHanni/pull/2666) ++ "Could not find server id" errors are now less common. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2680) ++ Clarified the wording of Bazaar Data Loading error messages. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2681) ++ Indicate in the CF menu when the chocolate amount has reached the cap and is therefore halted. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2688) ### Fixes @@ -329,6 +389,8 @@ + Fixed pair detection. + Fixed enchanting XP detection. + Fixed Minister in Calendar Perk description sometimes not using the gray color. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2632) ++ Fixed highlighting items in one's own inventory for some Bazaar features, e.g., in the "click to re-order" feature. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2640) ++ Automatically remove incorrect Account/Profile Upgrade warnings by talking to Elizabeth. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2674) #### Mining Fixes @@ -355,6 +417,9 @@ + Fixed the Mineshaft Pity Counter not working in the Great Glacite Lake. - martimavocado (https://github.com/hannibal002/SkyHanni/pull/2565) + Fixed Powder Tracker inaccuracies. - Empa (https://github.com/hannibal002/SkyHanni/pull/2591) + Fixed Jasper gemstones not being addressed in the Powder Mining filter. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2618) ++ Fixed the King Talisman Tracker sometimes not displaying the correct data. - martimavocado (https://github.com/hannibal002/SkyHanni/pull/2663) ++ Fixed the Powder Tracker not tracking items correctly. - HiZe (https://github.com/hannibal002/SkyHanni/pull/2645) ++ Fixed an error in Powder Tracker. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2678) #### Scoreboard Fixes @@ -378,6 +443,9 @@ + Fixed a Custom Scoreboard error during M7 Dragons. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2510) + Fixed Custom Scoreboard error during the Raffle Event. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2545) + Fixed both the Custom Scoreboard Active and Starting Soon Tab List events being active simultaneously in the Garden. - Empa, j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2592) ++ Fixed Custom Scoreboard not showing the Perkpocalypse Mayor. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2683) ++ Fixed some scoreboard error messages appearing in chat. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2672) ++ Fixed the custom scoreboard not updating when the Hypixel scoreboard is not updating. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2685) #### Hoppity Fixes @@ -389,15 +457,19 @@ + Fixed an issue where Fish the Rabbit and El Dorado did not have compacted chat messages. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2488) + Fixed inconsistencies in Hoppity Duplicate Number counts. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2595) + Fixed Fish the Rabbit and El Dorado incorrectly counting as unique rabbits during Hoppity's Hunt. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2627) ++ Fixed Hoppity Collection Display not updating the rabbit count in some cases, e.g., when collecting rabbits on alpha or manually changing the config values. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2686) ++ Fixed the chocolate count increasing in other menus even when production is halted. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2688) #### Chat Fixes + Fixed an error with Patcher Coordinate Detection from chat. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2410) + Fixed ultimate enchants not showing in `/show`. - Vixid (https://github.com/hannibal002/SkyHanni/pull/2465) ++ Fixed being unable to shift-click on chat messages. - nopo (https://github.com/hannibal002/SkyHanni/pull/2650) #### Commands Fixes + Fixed the command `/shtps` printing nothing if the TPS display was currently showing nothing. - CalMWolfs (https://github.com/hannibal002/SkyHanni/pull/2446) ++ Fixed "/viewrecipe command replace" breaking pages. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2679) #### Dungeon Fixes @@ -409,10 +481,11 @@ + Fixed the reputation helper not updating after a sack update. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2439) + Fixed Heavy Pearls sometimes not being highlighted. - Luna (https://github.com/hannibal002/SkyHanni/pull/2479) ++ Added a delay to the Pablo helper message so it appears after he finishes his dialogue. - Luna (https://github.com/hannibal002/SkyHanni/pull/2662) #### Garden Fixes -+ Fixed outdated Dicer gemstone fortune in FF guide. - Not_a_cow (https://github.com/hannibal002/SkyHanni/pull/2499) ++ Fixed outdated Dicer gemstone fortune in FF guide. - not_a_cow (https://github.com/hannibal002/SkyHanni/pull/2499) + Fixed some garden messages not being blocked. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2532) + Fixed active sprays not being removed from the GUI when using a washer. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2532) @@ -422,6 +495,9 @@ + Fixed a case where the Broodmother countdown could be wildly inaccurate. - MTOnline (https://github.com/hannibal002/SkyHanni/pull/2513) + Fixed Flare Display spamming chat with negative values when the server is lagging. - Stella (https://github.com/hannibal002/SkyHanni/pull/2567) + Fixed a case where the Imminent stage did not update the Broodmother countdown. - MTOnline (https://github.com/hannibal002/SkyHanni/pull/2602)v ++ Fixed some Islands Dummy mob types not being detected by the Damage Indicator. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2646) ++ Fixed the Ender Node Tracker not detecting some items. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2644) ++ Fixed Flare Expiration warnings not appearing in chat or as a title. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2643) #### The Carnival Fixes @@ -430,7 +506,8 @@ #### Fishing Fixes -+ Fixed error messages while using the Chum Bucket Hider feature. - nea89 (https://github.com/hannibal002/SkyHanni/pull/2587) ++ Fixed error messages while using the Chum Bucket Hider feature. - nea (https://github.com/hannibal002/SkyHanni/pull/2587) ++ Fixed the Trophy Fish Title displaying an undefined character in the format. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2670) #### Rift Fixes @@ -459,6 +536,9 @@ + Fixed Area Navigation distances to player being incorrect. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2634) + Fixed item trackers displaying removed item names incorrectly. - CalMWolfs (https://github.com/hannibal002/SkyHanni/pull/2620) + Fixed some messages from Pablo NPC not being detected. - Luna (https://github.com/hannibal002/SkyHanni/pull/2636) ++ Fixed SkyHanni re-downloading the repository on every launch. - nopo (https://github.com/hannibal002/SkyHanni/pull/2669) ++ Fixed unknown Perkpocalypse Mayor chat spam. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2683) ++ Fixed the wiki keybind searching for "null" on items with no internal name. - MTOnline (https://github.com/hannibal002/SkyHanni/pull/2682) ### Technical Details @@ -490,7 +570,7 @@ + Changed RenderableTooltips to be more consistent with the vanilla ones. - Empa (https://github.com/hannibal002/SkyHanni/pull/1869) + Improved error logging for enchant parser. - Vixid (https://github.com/hannibal002/SkyHanni/pull/2454) + Added renderable search box. - Thunderblade73 (https://github.com/hannibal002/SkyHanni/pull/2475) -+ Added the ability to add more optional display modes to trackers. - !nea (https://github.com/hannibal002/SkyHanni/pull/2487) ++ Added the ability to add more optional display modes to trackers. - nea (https://github.com/hannibal002/SkyHanni/pull/2487) + These extra trackers still need to provide their own storage. + Added perk descriptions to mayor perks. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2342) + These are loaded when checking the active mayor/minister from the API, so most of the perks will initially have no description. @@ -530,6 +610,13 @@ + Added `detekt` runner to the build process. - Daveed & nea (https://github.com/hannibal002/SkyHanni/pull/2547) + Added Clock Offset Millis using an NTP server. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2623) + Added `EntityMovementData.onNextTeleport()` logic, which triggers a runnable after the world has changed or the player has teleported. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2635) ++ Added Bazaar Fetch information to `/shdebug`. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2675) ++ Removed the password from the download source check. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2649) ++ Added a missing SkyBlock check for debug commands `/shtrackparticles` and `/shtracksounds`. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2641) ++ Prepared for later migration of correct config name of Plhlegblast. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2684) ++ Added the ability to disable SkyHanni errors via repo configuration. - nopo (https://github.com/hannibal002/SkyHanni/pull/2668) ++ Added current server ID and fetch data to the `/shdebug` command. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2680) ++ Added more `/shdebug` checks for aspects like OS, Java version, and launcher. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2691) ### Removed Features @@ -539,6 +626,7 @@ + Replaced then with a draggable list of different Hoppity collection highlight options. + Removed "Forge GfS". - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2564) + Hypixel now pulls directly from sacks when using the forge. ++ Removed Mithril Powder from the Powder Tracker. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2656) ## Version 0.26 diff --git a/docs/FEATURES.md b/docs/FEATURES.md index a57725958d57..ed5c74ad3e0b 100644 --- a/docs/FEATURES.md +++ b/docs/FEATURES.md @@ -226,6 +226,8 @@ Use `/sh` or `/skyhanni` to open the SkyHanni config in game. + Display the price per Stonk when taking the minimum bid in the Stonks Auction (Richard Menu). - Thunderblade73 (https://github.com/hannibal002/SkyHanni/pull/2195) + Added Ultimate Enchant Star. - Empa (https://github.com/hannibal002/SkyHanni/pull/2612) + Shows a star on Enchanted Books with an Ultimate Enchant. ++ Added Focus Mode. - Thunderblade73 (https://github.com/hannibal002/SkyHanni/pull/2694) + + In Focus Mode, only the name of the item is displayed instead of the full description.
@@ -1005,6 +1007,9 @@ Use `/sh` or `/skyhanni` to open the SkyHanni config in game. + Abi = Dark Green. + Added a toggle to highlight found rabbits in Hoppity's Collection menu. - the1divider (https://github.com/hannibal002/SkyHanni/pull/2438) + Added the ability to change the color of missing rabbit dyes in Hoppity's Collection to reflect rabbit rarity. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2522) ++ Added an easier way to check your unique Hoppity Eggs collected on each island. - martimavocado (https://github.com/hannibal002/SkyHanni/pull/2625) + + Shows your progress in the Warp Menu. + + Can be automatically hidden when an island is complete. ### The Carnival diff --git a/pull_request_template.md b/pull_request_template.md index b004c1c13866..02769a0f8470 100644 --- a/pull_request_template.md +++ b/pull_request_template.md @@ -1,4 +1,6 @@ - + + ## Dependencies - pr_number_or_link_here diff --git a/root.gradle.kts b/root.gradle.kts index 9346a78f9f92..e3af39d26071 100644 --- a/root.gradle.kts +++ b/root.gradle.kts @@ -14,7 +14,7 @@ plugins { allprojects { group = "at.hannibal2.skyhanni" - version = "0.27.Beta.14" + version = "0.28.Beta.1" repositories { mavenCentral() mavenLocal() diff --git a/src/main/java/at/hannibal2/skyhanni/api/SkillAPI.kt b/src/main/java/at/hannibal2/skyhanni/api/SkillAPI.kt index b40255449226..0e35e602fc61 100644 --- a/src/main/java/at/hannibal2/skyhanni/api/SkillAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/api/SkillAPI.kt @@ -392,7 +392,7 @@ object SkillAPI { ChatUtils.chat("§bSkill Custom Goal Level") val map = storage?.filter { it.value.customGoalLevel != 0 } ?: return if (map.isEmpty()) { - ChatUtils.chat("§cYou haven't set any custom goals yet!") + ChatUtils.userError("You haven't set any custom goals yet!") } map.forEach { (skill, data) -> ChatUtils.chat("§e${skill.displayName}: §b${data.customGoalLevel}") diff --git a/src/main/java/at/hannibal2/skyhanni/api/event/EventHandler.kt b/src/main/java/at/hannibal2/skyhanni/api/event/EventHandler.kt index 4b4c008523e2..d164e0e774d7 100644 --- a/src/main/java/at/hannibal2/skyhanni/api/event/EventHandler.kt +++ b/src/main/java/at/hannibal2/skyhanni/api/event/EventHandler.kt @@ -6,6 +6,7 @@ import at.hannibal2.skyhanni.test.command.ErrorManager import at.hannibal2.skyhanni.utils.ChatUtils import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.LorenzUtils.inAnyIsland +import at.hannibal2.skyhanni.utils.StringUtils import at.hannibal2.skyhanni.utils.chat.Text import java.lang.invoke.LambdaMetafactory import java.lang.invoke.MethodHandles @@ -91,7 +92,8 @@ class EventHandler private constructor(val name: String, priv errors++ if (errors <= 3) { val errorName = throwable::class.simpleName ?: "error" - val message = "Caught an $errorName in ${listener.name} at $name: ${throwable.message}" + val aOrAn = StringUtils.optionalAn(errorName) + val message = "Caught $aOrAn $errorName in ${listener.name} at $name: ${throwable.message}" ErrorManager.logErrorWithData(throwable, message, ignoreErrorCache = onError != null) } onError?.invoke(throwable) diff --git a/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt b/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt index aa15461f5af2..7c41245fc7f8 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt +++ b/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt @@ -12,7 +12,7 @@ import com.google.gson.JsonPrimitive object ConfigUpdaterMigrator { val logger = LorenzLogger("ConfigMigration") - const val CONFIG_VERSION = 60 + const val CONFIG_VERSION = 61 fun JsonElement.at(chain: List, init: Boolean): JsonElement? { if (chain.isEmpty()) return this if (this !is JsonObject) return null diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/chroma/ChromaConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/chroma/ChromaConfig.java index 6a02e2ed3061..b3f8577f0c0f 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/chroma/ChromaConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/chroma/ChromaConfig.java @@ -20,7 +20,7 @@ public class ChromaConfig { public boolean chromaPreview = false; @Expose - @ConfigOption(name = "Enabled", desc = "Toggle SkyHanni's chroma. §e(Disables Patcher's Optimized Font Renderer while enabled)") + @ConfigOption(name = "Enabled", desc = "Toggle SkyHanni's chroma.") @ConfigEditorBoolean @FeatureToggle public Property enabled = Property.of(false); @@ -80,7 +80,7 @@ public String toString() { public Runnable resetSettings = ChromaManager::resetChromaSettings; @Expose - @ConfigOption(name = "Everything Chroma", desc = "Render §4§l§oALL §r§7text in chroma. §e(Some enchants may appear white with SBA enchant parsing)") + @ConfigOption(name = "Everything Chroma", desc = "Render §4§l§oALL §r§7text in chroma. §e(Disables Patcher's Optimized Font Renderer while enabled)") @ConfigEditorBoolean public boolean allChroma = false; diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/combat/FerocityDisplayConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/combat/FerocityDisplayConfig.java index d212a4a0797b..605a31a2b4da 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/combat/FerocityDisplayConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/combat/FerocityDisplayConfig.java @@ -13,7 +13,7 @@ public class FerocityDisplayConfig { @ConfigOption( name = "Enabled", desc = "Show ferocity stat as single GUI element.\n" + - "§eRequires tab list widget enabled and ferocity selected to work." + "§eRequires tab list widget enabled and ferocity selected to update live." ) @ConfigEditorBoolean @FeatureToggle diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/commands/BetterWikiCommandConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/commands/BetterWikiCommandConfig.java index fc6d0be06fc2..df0468226e77 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/commands/BetterWikiCommandConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/commands/BetterWikiCommandConfig.java @@ -53,7 +53,7 @@ public class BetterWikiCommandConfig { public boolean menuOpenWiki = false; @Expose - @ConfigOption(name = "Fandom Wiki Key", desc = "Search for an item on Wiki with this keybind.\n" + + @ConfigOption(name = "Wiki Key", desc = "Search for an item's wiki page with this keybind.\n" + "§cFor an optimal experience, do §lNOT §cbind this to a mouse button.") @ConfigEditorKeybind(defaultKey = Keyboard.KEY_NONE) public int wikiKeybind = Keyboard.KEY_NONE; diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/commands/TabCompleteConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/commands/TabCompleteConfig.java index 790224761e1e..388cec87da93 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/commands/TabCompleteConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/commands/TabCompleteConfig.java @@ -36,22 +36,22 @@ public class TabCompleteConfig { public boolean party = true; @Expose - @ConfigOption(name = "VIP Visits", desc = "Tab-complete the visit to special users with cake souls on it.") + @ConfigOption(name = "Guild", desc = "Tab-complete Guild Members.") @ConfigEditorBoolean @FeatureToggle - public boolean vipVisits = true; + public boolean guild = false; @Expose - @ConfigOption(name = "/gfs Sack", desc = "Tab-complete §e/gfs §7sack items.") + @ConfigOption(name = "VIP Visits", desc = "Tab-complete the visit to special users with cake souls on it.") @ConfigEditorBoolean @FeatureToggle - public boolean gfsSack = true; + public boolean vipVisits = true; @Expose - @ConfigOption(name = "Party Commands", desc = "Tab-complete commonly used party commands.") + @ConfigOption(name = "/gfs Sack", desc = "Tab-complete §e/gfs §7sack items.") @ConfigEditorBoolean @FeatureToggle - public boolean partyCommands = true; + public boolean gfsSack = true; @Expose @ConfigOption(name = "View Recipe", desc = "Tab-complete item IDs in the the Hypixel command §e/viewrecipe§7. Only items with recipes are tab completed.") diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/event/hoppity/HoppityEggsConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/event/hoppity/HoppityEggsConfig.java index 8bbaa962ca26..3fd83db69655 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/event/hoppity/HoppityEggsConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/event/hoppity/HoppityEggsConfig.java @@ -211,4 +211,15 @@ public String toString() { @ConfigEditorBoolean @FeatureToggle public boolean petWarning = false; + + @Expose + @ConfigOption(name = "Show uniques in Warp Menu", desc = "Shows your unique eggs in the Warp Menu during the hoppity event.") + @ConfigEditorBoolean + @FeatureToggle + public boolean uniquesWarpMenu = true; + + @Expose + @ConfigOption(name = "Hide when maxed", desc = "Stops the above feature from working when the island is complete.") + @ConfigEditorBoolean + public boolean uniquesWarpMenuHideMax = true; } diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/garden/visitor/TimerConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/garden/visitor/TimerConfig.java index 32bff02debbe..a6b7e509e610 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/garden/visitor/TimerConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/garden/visitor/TimerConfig.java @@ -34,5 +34,6 @@ public class TimerConfig { @Expose @ConfigLink(owner = TimerConfig.class, field = "enabled") + // TODO rename to position public Position pos = new Position(-200, 40, false, true); } diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/FocusModeConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/FocusModeConfig.java new file mode 100644 index 000000000000..3211354fec3d --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/FocusModeConfig.java @@ -0,0 +1,22 @@ +package at.hannibal2.skyhanni.config.features.inventory; + +import at.hannibal2.skyhanni.config.FeatureToggle; +import com.google.gson.annotations.Expose; +import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean; +import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorKeybind; +import io.github.notenoughupdates.moulconfig.annotations.ConfigOption; +import org.lwjgl.input.Keyboard; + +public class FocusModeConfig { + + @Expose + @ConfigOption(name = "Enabled", desc = "In focus mode you only see the name of the item instead of the whole description.") + @ConfigEditorBoolean + @FeatureToggle + public boolean enabled = false; + + @Expose + @ConfigOption(name = "Toggle Key", desc = "Key to toggle the focus mode on and off.") + @ConfigEditorKeybind(defaultKey = Keyboard.KEY_NONE) + public int toggleKey = Keyboard.KEY_NONE; +} diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/InventoryConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/InventoryConfig.java index 6e064ced6420..71ab7c792147 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/InventoryConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/InventoryConfig.java @@ -84,6 +84,11 @@ public class InventoryConfig { @Accordion public PersonalCompactorConfig personalCompactor = new PersonalCompactorConfig(); + @Expose + @ConfigOption(name = "Focus Mode", desc="") + @Accordion + public FocusModeConfig focusMode = new FocusModeConfig(); + @Expose @ConfigOption(name = "RNG Meter", desc = "") @Accordion diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/mining/PowderTrackerConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/mining/PowderTrackerConfig.java index 1c32cabc2e95..247da9b546d3 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/mining/PowderTrackerConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/mining/PowderTrackerConfig.java @@ -24,7 +24,6 @@ import static at.hannibal2.skyhanni.config.features.mining.PowderTrackerConfig.PowderDisplayEntry.GOLD_ESSENCE; import static at.hannibal2.skyhanni.config.features.mining.PowderTrackerConfig.PowderDisplayEntry.HARD_STONE; import static at.hannibal2.skyhanni.config.features.mining.PowderTrackerConfig.PowderDisplayEntry.JADE; -import static at.hannibal2.skyhanni.config.features.mining.PowderTrackerConfig.PowderDisplayEntry.MITHRIL_POWDER; import static at.hannibal2.skyhanni.config.features.mining.PowderTrackerConfig.PowderDisplayEntry.ROBOTRON; import static at.hannibal2.skyhanni.config.features.mining.PowderTrackerConfig.PowderDisplayEntry.RUBY; import static at.hannibal2.skyhanni.config.features.mining.PowderTrackerConfig.PowderDisplayEntry.SAPPHIRE; @@ -56,7 +55,6 @@ public class PowderTrackerConfig { public Property> textFormat = Property.of(new ArrayList<>(Arrays.asList( TOTAL_CHESTS, DOUBLE_POWDER, - MITHRIL_POWDER, GEMSTONE_POWDER, SPACER_1, DIAMOND_ESSENCE, @@ -78,7 +76,6 @@ public class PowderTrackerConfig { public enum PowderDisplayEntry implements HasLegacyId { TOTAL_CHESTS("§d852 Total chests Picked §7(950/h)", 2), DOUBLE_POWDER("§bx2 Powder: §aActive!", 3), - MITHRIL_POWDER("§b250,420 §aMithril Powder §7(350,000/h)", 4), GEMSTONE_POWDER("§b250,420 §dGemstone Powder §7(350,000/h)", 5), SPACER_1("", 6), DIAMOND_ESSENCE("§b129 §bDiamond Essence §7(600/h)", 7), diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/misc/MiscConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/misc/MiscConfig.java index df1ae1da5c04..0869262959c0 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/misc/MiscConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/misc/MiscConfig.java @@ -15,6 +15,7 @@ import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorDraggableList; import io.github.notenoughupdates.moulconfig.annotations.ConfigLink; import io.github.notenoughupdates.moulconfig.annotations.ConfigOption; +import io.github.notenoughupdates.moulconfig.annotations.SearchTag; import io.github.notenoughupdates.moulconfig.observer.Property; import java.util.ArrayList; @@ -226,6 +227,7 @@ public class MiscConfig { @Expose @ConfigOption(name = "Account Upgrade Reminder", desc = "Remind you to claim community shop account and profile upgrades when complete.") @ConfigEditorBoolean + @SearchTag("Elizabeth Community Center") @FeatureToggle public boolean accountUpgradeReminder = true; diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/rift/area/westvillage/GunthersRaceConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/rift/area/westvillage/GunthersRaceConfig.java index beb4acc9e3a0..10d18fa85c05 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/rift/area/westvillage/GunthersRaceConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/rift/area/westvillage/GunthersRaceConfig.java @@ -30,4 +30,10 @@ public class GunthersRaceConfig { @ConfigOption(name = "Monochrome Color", desc = "Set a boring monochrome color for the guide waypoints.") @ConfigEditorColour public Property monochromeColor = Property.of("0:60:0:0:255"); + + @Expose + @ConfigOption(name = "Hide Other Players", desc = "Hide other players while in the race.") + @ConfigEditorBoolean + @FeatureToggle + public boolean hidePlayers = false; } diff --git a/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java b/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java index 754eea3bba59..4ad2c8eb300a 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java +++ b/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java @@ -6,6 +6,7 @@ import at.hannibal2.skyhanni.data.MaxwellAPI; import at.hannibal2.skyhanni.data.jsonobjects.local.HotmTree; import at.hannibal2.skyhanni.data.model.ComposterUpgrade; +import at.hannibal2.skyhanni.data.model.SkyblockStat; import at.hannibal2.skyhanni.features.combat.endernodetracker.EnderNodeTracker; import at.hannibal2.skyhanni.features.combat.ghostcounter.GhostData; import at.hannibal2.skyhanni.features.dungeon.CroesusChestTracker; @@ -102,6 +103,9 @@ public static class ChocolateFactoryStorage { @Expose public long currentChocolate = 0; + @Expose + public long maxChocolate = 0; + @Expose public long chocolateThisPrestige = 0; @@ -200,6 +204,9 @@ public static class CarnivalStorage { public Map goals = new HashMap<>(); } + @Expose + public Map stats = new HashMap<>(SkyblockStat.getEntries().size()); + @Expose public MaxwellPowerStorage maxwell = new MaxwellPowerStorage(); diff --git a/src/main/java/at/hannibal2/skyhanni/data/GuildAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/GuildAPI.kt index 541eb323cf8f..1e98b61e424a 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/GuildAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/GuildAPI.kt @@ -38,7 +38,7 @@ object GuildAPI { } } - fun isInGuild(name: String) = ProfileStorageData.playerSpecific?.guildMembers?.let { - name in it - } ?: false + fun isInGuild(name: String) = name in getAllMembers() + + fun getAllMembers() = ProfileStorageData.playerSpecific?.guildMembers ?: emptyList() } diff --git a/src/main/java/at/hannibal2/skyhanni/data/HypixelData.kt b/src/main/java/at/hannibal2/skyhanni/data/HypixelData.kt index 039bd7d28afd..3707d10af0a7 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/HypixelData.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/HypixelData.kt @@ -4,6 +4,7 @@ import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.api.event.HandleEvent import at.hannibal2.skyhanni.config.ConfigManager.Companion.gson import at.hannibal2.skyhanni.data.model.TabWidget +import at.hannibal2.skyhanni.events.DebugDataCollectEvent import at.hannibal2.skyhanni.events.HypixelJoinEvent import at.hannibal2.skyhanni.events.IslandChangeEvent import at.hannibal2.skyhanni.events.LorenzChatEvent @@ -119,6 +120,9 @@ object HypixelData { var skyBlock = false var skyBlockIsland = IslandType.UNKNOWN var serverId: String? = null + private var lastSuccessfulServerIdFetchTime = SimpleTimeMark.farPast() + private var lastSuccessfulServerIdFetchType: String? = null + private var failedServerIdFetchCounter = 0 // Ironman, Stranded and Bingo var noTrade = false @@ -159,24 +163,61 @@ object HypixelData { TabWidget.SERVER.matchMatcherFirstLine { serverId = group("serverid") + lastSuccessfulServerIdFetchTime = SimpleTimeMark.now() + lastSuccessfulServerIdFetchType = "tab list" + failedServerIdFetchCounter = 0 return } ScoreboardData.sidebarLinesFormatted.matchFirst(serverIdScoreboardPattern) { val serverType = if (group("servertype") == "M") "mega" else "mini" serverId = "$serverType${group("serverid")}" + lastSuccessfulServerIdFetchTime = SimpleTimeMark.now() + lastSuccessfulServerIdFetchType = "scoreboard" + failedServerIdFetchCounter = 0 return } + failedServerIdFetchCounter++ + if (failedServerIdFetchCounter < 3) return ErrorManager.logErrorWithData( Exception("NoServerId"), "Could not find server id", + "failedServerIdFetchCounter" to failedServerIdFetchCounter, + "lastSuccessfulServerIdFetchTime" to lastSuccessfulServerIdFetchTime, + "lastSuccessfulServerIdFetchType" to lastSuccessfulServerIdFetchType, "islandType" to LorenzUtils.skyBlockIsland, "tablist" to TabListData.getTabList(), "scoreboard" to ScoreboardData.sidebarLinesFormatted, ) } + @SubscribeEvent + fun onDebugDataCollect(event: DebugDataCollectEvent) { + event.title("Server ID") + if (!LorenzUtils.inSkyBlock) { + event.addIrrelevant("not in sb") + return + } + + val id = serverId + if (id == null) { + event.addData { + add("server id is null!") + add("failedServerIdFetchCounter: $failedServerIdFetchCounter") + add("") + add("last successful fetch time: $lastSuccessfulServerIdFetchTime") + add("last successful fetch type: $lastSuccessfulServerIdFetchType") + } + } else { + event.addIrrelevant { + add("Server id: '$id'") + add("fetch time: $lastSuccessfulServerIdFetchTime") + add("fetch type: $lastSuccessfulServerIdFetchType") + } + } + } + fun getPlayersOnCurrentServer(): Int { var amount = 0 val playerPatternList = mutableListOf( diff --git a/src/main/java/at/hannibal2/skyhanni/data/MayorAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/MayorAPI.kt index 469c48489245..949e33146ce6 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/MayorAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/MayorAPI.kt @@ -143,6 +143,7 @@ object MayorAPI { ChatUtils.clickableChat( "The Perkpocalypse Mayor is not known! Click here to update the temporary Mayor.", onClick = { HypixelCommands.calendar() }, + replaceSameMessage = true, ) } } @@ -170,7 +171,7 @@ object MayorAPI { } ?: false } ?: return - val perk = stack.getLore().nextAfter({ perkpocalypsePerksPattern.matches(it) }) ?: return + val perk = stack.getLore().nextAfter({ perkpocalypsePerksPattern.matches(it) }, 2) ?: return // This is the first Perk of the Perkpocalypse Mayor val jerryMayor = getMayorFromPerk(getPerkFromName(perk.removeColor()) ?: return)?.addAllPerks() ?: return diff --git a/src/main/java/at/hannibal2/skyhanni/data/MiningAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/MiningAPI.kt index 45aec43d3c72..47133f199a49 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/MiningAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/MiningAPI.kt @@ -74,7 +74,7 @@ object MiningAPI { */ private val pickobulusFailPattern by pickbobulusGroup.pattern( "fail", - "§7Your §r§aPickobulus §r§7didn't destroy any blocks!" + "§7Your §r§aPickobulus §r§7didn't destroy any blocks!", ) private data class MinedBlock(val ore: OreBlock, var confirmed: Boolean) { @@ -127,6 +127,8 @@ object MiningAPI { var lastColdReset = SimpleTimeMark.farPast() private set + private var lastOreMinedTime = SimpleTimeMark.farPast() + fun inGlaciteArea() = inGlacialTunnels() || IslandType.MINESHAFT.isInIsland() fun inDwarvenBaseCamp() = IslandType.DWARVEN_MINES.isInIsland() && dwarvenBaseCampPattern.matches(LorenzUtils.skyBlockArea) @@ -341,6 +343,7 @@ object MiningAPI { currentAreaOreBlocks = setOf() resetOreEvent() resetPickobulusEvent() + lastOreMinedTime = SimpleTimeMark.farPast() } private fun resetOreEvent() { @@ -359,6 +362,11 @@ object MiningAPI { pickobulusWaitingForBlock = false } + @HandleEvent(onlyOnSkyblock = true) + fun onOreMined(event: OreMinedEvent) { + lastOreMinedTime = SimpleTimeMark.now() + } + @SubscribeEvent fun onDebugDataCollect(event: DebugDataCollectEvent) { event.title("Mining API") @@ -366,6 +374,10 @@ object MiningAPI { event.addIrrelevant("not in a mining island") return } + if (lastOreMinedTime.passedSince() > 30.seconds) { + event.addIrrelevant("not mined recently") + return + } event.addData { if (lastInitSound.isFarPast()) { diff --git a/src/main/java/at/hannibal2/skyhanni/data/bazaar/HypixelBazaarFetcher.kt b/src/main/java/at/hannibal2/skyhanni/data/bazaar/HypixelBazaarFetcher.kt index 13044b7c3151..7a97fca1d19d 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/bazaar/HypixelBazaarFetcher.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/bazaar/HypixelBazaarFetcher.kt @@ -2,6 +2,7 @@ package at.hannibal2.skyhanni.data.bazaar import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.config.ConfigManager +import at.hannibal2.skyhanni.events.DebugDataCollectEvent import at.hannibal2.skyhanni.events.LorenzTickEvent import at.hannibal2.skyhanni.features.inventory.bazaar.BazaarData import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule @@ -29,10 +30,29 @@ object HypixelBazaarFetcher { private const val HIDDEN_FAILED_ATTEMPTS = 3 var latestProductInformation = mapOf() + private var lastSuccessfulFetch = SimpleTimeMark.farPast() private var nextFetchTime = SimpleTimeMark.farPast() private var failedAttempts = 0 private var nextFetchIsManual = false + @SubscribeEvent + fun onDebugDataCollect(event: DebugDataCollectEvent) { + event.title("Bazaar Data Fetcher from API") + + val data = listOf( + "failedAttempts: $failedAttempts", + "nextFetchIsManual: $nextFetchIsManual", + "nextFetchTime: ${nextFetchTime.timeUntil()}", + "lastSuccessfulFetch: ${lastSuccessfulFetch.passedSince()}", + ) + + if (failedAttempts == 0) { + event.addIrrelevant(data) + } else { + event.addData(data) + } + } + @SubscribeEvent fun onTick(event: LorenzTickEvent) { if (!canFetch()) return @@ -51,6 +71,7 @@ object HypixelBazaarFetcher { if (response.success) { latestProductInformation = process(response.products) failedAttempts = 0 + lastSuccessfulFetch = SimpleTimeMark.now() } else { val rawResponse = jsonResponse.toString() onError(fetchType, Exception("success=false, cause=${response.cause}"), rawResponse) @@ -98,13 +119,20 @@ object HypixelBazaarFetcher { e.printStackTrace() } else { nextFetchTime = SimpleTimeMark.now() + 15.minutes - ErrorManager.logErrorWithData( - e, - userMessage, - "fetchType" to fetchType, - "failedAttempts" to failedAttempts, - "rawResponse" to rawResponse, - ) + if (rawResponse == null || rawResponse.toString() == "{}") { + ChatUtils.chat( + "§cFailed loading Bazaar Price data!\n" + + "Please wait until the Hypixel API is sending correct data again! There is nothing else to do at the moment.", + ) + } else { + ErrorManager.logErrorWithData( + e, + userMessage, + "fetchType" to fetchType, + "failedAttempts" to failedAttempts, + "rawResponse" to rawResponse, + ) + } } } diff --git a/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/RepoErrorData.kt b/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/RepoErrorData.kt new file mode 100644 index 000000000000..41d0f701cb15 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/RepoErrorData.kt @@ -0,0 +1,19 @@ +package at.hannibal2.skyhanni.data.jsonobjects.repo + +import com.google.gson.annotations.Expose +import com.google.gson.annotations.SerializedName + +data class RepoErrorJson( + @Expose @SerializedName("changed_error_messages") val changedErrorMessages: List, +) + +data class RepoErrorData( + @Expose @SerializedName("message_exact") private var rawMessageExact: List?, + @Expose @SerializedName("message_starts_with") private var rawMessageStartsWith: List?, + @Expose @SerializedName("replace_message") var replaceMessage: String?, + @Expose @SerializedName("custom_message") var customMessage: String?, + @Expose @SerializedName("affected_versions") var affectedVersions: List = listOf(), +) { + val messageExact get() = rawMessageExact ?: emptyList() + val messageStartsWith get() = rawMessageStartsWith ?: emptyList() +} diff --git a/src/main/java/at/hannibal2/skyhanni/data/model/SkyblockStat.kt b/src/main/java/at/hannibal2/skyhanni/data/model/SkyblockStat.kt index f31c95958659..d1c6dede0327 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/model/SkyblockStat.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/model/SkyblockStat.kt @@ -1,69 +1,115 @@ package at.hannibal2.skyhanni.data.model +import at.hannibal2.skyhanni.data.ProfileStorageData +import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent +import at.hannibal2.skyhanni.events.WidgetUpdateEvent +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.utils.DelayedRun +import at.hannibal2.skyhanni.utils.ItemUtils.getLore +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.RegexUtils.groupOrNull +import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher import at.hannibal2.skyhanni.utils.StringUtils.allLettersFirstUppercase +import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern import net.minecraft.client.Minecraft +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import org.intellij.lang.annotations.Language import java.util.EnumMap +import java.util.regex.Pattern +import kotlin.math.roundToInt -enum class SkyblockStat(val icon: String) { - DAMAGE("§c❁"), - HEALTH("§c❤"), - DEFENSE("§a❈"), - STRENGTH("§c❁"), - INTELLIGENCE("§b✎"), - - CRIT_DAMAGE("§9☠"), - CRIT_CHANCE("§9☣"), - FEROCITY("§c⫽"), - BONUS_ATTACK_SPEED("§e⚔"), - ABILITY_DAMAGE("§c๑"), - HEALTH_REGEN("§c❣"), - VITALITY("§4♨"), - MENDING("§a☄"), - TRUE_DEFENCE("§7❂"), - SWING_RANGE("§eⓈ"), - SPEED("§f✦"), - SEA_CREATURE_CHANCE("§3α"), - MAGIC_FIND("§b✯"), - PET_LUCK("§d♣"), - FISHING_SPEED("§b☂"), - BONUS_PEST_CHANCE("§2ൠ"), - COMBAT_WISDOM("§3☯"), - MINING_WISDOM("§3☯"), - FARMING_WISDOM("§3☯"), - FORAGING_WISDOM("§3☯"), - FISHING_WISDOM("§3☯"), - ENCHANTING_WISDOM("§3☯"), - ALCHEMY_WISDOM("§3☯"), - CARPENTRY_WISDOM("§3☯"), - RUNECRAFTING_WISDOM("§3☯"), - SOCIAL_WISDOM("§3☯"), - TAMING_WISDOM("§3☯"), - MINING_SPEED("§6⸕"), - BREAKING_POWER("§2Ⓟ"), - PRISTINE("§5✧"), - FORAGING_FORTUNE("§☘"), - FARMING_FORTUNE("§6☘"), - - MINING_SPREAD("§e▚"), - MINING_FORTUNE("§6☘"), - ORE_FORTUNE("§6☘"), - DWARVEN_METAL_FORTUNE("§6☘"), - BLOCK_FORTUNE("§6☘"), - GEMSTONE_FORTUNE("§6☘"), - - FEAR("§a☠"), - HEAT_RESISTANCE("§c♨"), - - UNKNOWN("§c?") +enum class SkyblockStat( + val icon: String, + @Language("RegExp") tabListPatternS: String, + @Language("RegExp") menuPatternS: String, +) { + DAMAGE("§c❁", "", ""), // Weapon only + HEALTH("§c❤", " Health: §r§c❤(?.*)", " §c❤ Health §f(?.*)"), // TODO get from action bar + DEFENSE("§a❈", " Defense: §r§a❈(?.*)", " §a❈ Defense §f(?.*)"), // TODO get from action bar + STRENGTH("§c❁", " Strength: §r§c❁(?.*)", " §c❁ Strength §f(?.*)"), + INTELLIGENCE("§b✎", " Intelligence: §r§b✎(?.*)", " §b✎ Intelligence §f(?.*)"), // TODO get from action bar + CRIT_DAMAGE("§9☠", " Crit Damage: §r§9☠(?.*)", " §9☠ Crit Damage §f(?.*)"), + CRIT_CHANCE("§9☣", " Crit Chance: §r§9☣(?.*)", " §9☣ Crit Chance §f(?.*)"), + FEROCITY("§c⫽", " Ferocity: §r§c⫽(?.*)", " §c⫽ Ferocity §f(?.*)"), + BONUS_ATTACK_SPEED("§e⚔", " Attack Speed: §r§e⚔(?.*)", " §e⚔ Bonus Attack Speed §f(?.*)"), + ABILITY_DAMAGE("§c๑", " Ability Damage: §r§c๑(?.*)", " §c๑ Ability Damage §f(?.*)"), + HEALTH_REGEN("§c❣", " Health Regen: §r§c❣(?.*)", " §c❣ Health Regen §f(?.*)"), + VITALITY("§4♨", " Vitality: §r§4♨(?.*)", " §4♨ Vitality §f(?.*)"), + MENDING("§a☄", " Mending: §r§a☄(?.*)", " §a☄ Mending §f(?.*)"), + TRUE_DEFENCE("§7❂", " True Defense: §r§f❂(?.*)", " §f❂ True Defense §f(?.*)"), + SWING_RANGE("§eⓈ", " Swing Range: §r§eⓈ(?.*)", " §eⓈ Swing Range §f(?.*)"), + SPEED("§f✦", " Speed: §r§f✦(?.*)", " §f✦ Speed §f(?.*)"), // TODO add the way sba did get it (be careful with 500+ Speed) + SEA_CREATURE_CHANCE("§3α", " Sea Creature Chance: §r§3α(?.*)", " §3α Sea Creature Chance §f(?.*)"), + MAGIC_FIND("§b✯", " Magic Find: §r§b✯(?.*)", " §b✯ Magic Find §f(?.*)"), + PET_LUCK("§d♣", " Pet Luck: §r§d♣(?.*)", " §d♣ Pet Luck §f(?.*)"), + FISHING_SPEED("§b☂", " Fishing Speed: §r§b☂(?.*)", " §b☂ Fishing Speed §f(?.*)"), + DOUBLE_HOOK_CHANCE("§9⚓", " Double Hook Chance: §r§9⚓(?.*)", ""), + BONUS_PEST_CHANCE("§2ൠ", " (?:§r§7§m)?Bonus Pest Chance: (?:§r§2)?ൠ(?.*)", " (?:§7§m|§2)ൠ Bonus Pest Chance (?:§f)?(?.*)"), + COMBAT_WISDOM("§3☯", " Combat Wisdom: §r§3☯(?.*)", " §3☯ Combat Wisdom §f(?.*)"), + MINING_WISDOM("§3☯", " Mining Wisdom: §r§3☯(?.*)", " §3☯ Mining Wisdom §f(?.*)"), + FARMING_WISDOM("§3☯", " Farming Wisdom: §r§3☯(?.*)", " §3☯ Farming Wisdom §f(?.*)"), + FORAGING_WISDOM("§3☯", " Foraging Wisdom: §r§3☯(?.*)", " §3☯ Foraging Wisdom §f(?.*)"), + FISHING_WISDOM("§3☯", " Fishing Wisdom: §r§3☯(?.*)", " §3☯ Fishing Wisdom §f(?.*)"), + ENCHANTING_WISDOM("§3☯", " Enchanting Wisdom: §r§3☯(?.*)", " §3☯ Enchanting Wisdom §f(?.*)"), + ALCHEMY_WISDOM("§3☯", " Alchemy Wisdom: §r§3☯(?.*)", " §3☯ Alchemy Wisdom §f(?.*)"), + CARPENTRY_WISDOM("§3☯", " Carpentry Wisdom: §r§3☯(?.*)", " §3☯ Carpentry Wisdom §f(?.*)"), + RUNECRAFTING_WISDOM("§3☯", " Runecrafting Wisdom: §r§3☯(?.*)", " §3☯ Runecrafting Wisdom §f(?.*)"), + SOCIAL_WISDOM("§3☯", " Social Wisdom: §r§3☯(?.*)", " §3☯ Social Wisdom §f(?.*)"), + TAMING_WISDOM("§3☯", " Taming Wisdom: §r§3☯(?.*)", " §3☯ Taming Wisdom §f(?.*)"), + MINING_SPEED("§6⸕", " Mining Speed: §r§6⸕(?.*)", " §6⸕ Mining Speed §f(?.*)"), + BREAKING_POWER("§2Ⓟ", "", " §2Ⓟ Breaking Power §f(?.*)"), + PRISTINE("§5✧", " Pristine: §r§5✧(?.*)", " §5✧ Pristine §f(?.*)"), + FORAGING_FORTUNE("§☘", " Foraging Fortune: §r§6☘(?.*)", " §6☘ Foraging Fortune §f(?.*)"), + FARMING_FORTUNE("§6☘", " (?:§r§7§m)?Farming Fortune: (?:§r§6)?☘(?.*)", " (?:§7§m|§6)☘ Farming Fortune (?:§f)?(?.*)"), + MINING_FORTUNE("§6☘", " Mining Fortune: §r§6☘(?.*)", " §6☘ Mining Fortune §f(?.*)"), + FEAR("§a☠", "", ""), // Skyblock does not like fear. It only shows during Great Spook, therefore no Data. + COLD_RESISTANCE("§b❄", " Cold Resistance: §r§b❄(?.*)", ""), + WHEAT_FORTUNE("§7☘", "", " §7(?:§m)☘ Wheat Fortune (?.*)"), + CARROT_FORTUNE("§7☘", "", " §7(?:§m)☘ Carrot Fortune (?.*)"), + POTATO_FORTUNE("§7☘", "", " §7(?:§m)☘ Potato Fortune (?.*)"), + PUMPKIN_FORTUNE("§7☘", "", " §7(?:§m)☘ Pumpkin Fortune (?.*)"), + MELON_FORTUNE("§7☘", "", " §7(?:§m)☘ Melon Fortune (?.*)"), + MUSHROOM_FORTUNE("§7☘", "", " §7(?:§m)☘ Mushroom Fortune (?.*)"), + CACTUS_FORTUNE("§7☘", "", " §7(?:§m)☘ Cactus Fortune (?.*)"), + NETHER_WART_FORTUNE("§7☘", "", " §7(?:§m)☘ Nether Wart Fortune (?.*)"), + COCOA_BEANS_FORTUNE("§7☘", "", " §7(?:§m)☘ Cocoa Beans Fortune (?.*)"), + SUGAR_CANE_FORTUNE("§7☘", "", " §7(?:§m)☘ Sugar Cane Fortune (?.*)"), + + MINING_SPREAD("§e▚", " (§r§7§m)?Mining Spread: (§r§e)?▚(?.*)", " (§7§m|§e)▚ Mining Spread (§f)?(?.*)"), + GEMSTONE_SPREAD("§e▚", " (§r§7§m)?Mining Spread: (§r§e)?▚(?.*)", " (§7§m|§e)▚ Gemstone Spread (§f)?(?.*)"), + ORE_FORTUNE("§6☘", " Ore Fortune: §r§6☘(?.*)", " §6☘ Ore Fortune §f103"), + DWARVEN_METAL_FORTUNE("§6☘", " Dwarven Metal Fortune: §r§6☘(?.*)", " §6☘ Dwarven Metal Fortune §f(?.*)"), + BLOCK_FORTUNE("§6☘", " Block Fortune: §r§6☘(?.*)", " §6☘ Block Fortune §f(?.*)"), + GEMSTONE_FORTUNE("§6☘", " Gemstone Fortune: §r§6☘(?.*)", " §6☘ Gemstone Fortune §f(?.*)"), + HEAT_RESISTANCE("§c♨", " Heat Resistance: §r§c♨(?.*)", " §c♨ Heat Resistance §f(?.*)"), + + UNKNOWN("§c?", "", "") ; + var lastKnownValue: Double + get() = ProfileStorageData.profileSpecific?.stats?.get(this) ?: 0.0 + set(value) { + ProfileStorageData.profileSpecific?.stats?.set(this, value) + } + + var lastSource: StatSourceType = StatSourceType.UNKNOWN + val capitalizedName = name.lowercase().allLettersFirstUppercase() val iconWithName = "$icon $capitalizedName" + val keyName = name.lowercase().replace('_', '.') + + val displayValue get() = icon + lastKnownValue.roundToInt() + + val tablistPattern by RepoPattern.pattern("stats.tablist.$keyName", tabListPatternS) + val menuPattern by RepoPattern.pattern("stats.menu.$keyName", menuPatternS) + fun asString(value: Int) = (if (value > 0) "+" else "") + value.toString() + " " + this.icon + @SkyHanniModule companion object { + val fontSizeOfLargestIcon by lazy { entries.maxOf { Minecraft.getMinecraft().fontRendererObj.getStringWidth(it.icon) } + 1 } @@ -71,6 +117,59 @@ enum class SkyblockStat(val icon: String) { fun getValueOrNull(string: String): SkyblockStat? = entries.firstOrNull { it.name == string } fun getValue(string: String): SkyblockStat = getValueOrNull(string) ?: UNKNOWN + + init { + entries.forEach { + it.tablistPattern + it.menuPattern + } + } + + @SubscribeEvent + fun onInventory(event: InventoryFullyOpenedEvent) { + if (!LorenzUtils.inSkyBlock) return + onSkyblockMenu(event) + onStatsMenu(event) + } + + private const val PLAYER_STATS_SLOT_INDEX = 13 + + private fun onSkyblockMenu(event: InventoryFullyOpenedEvent) { + if (event.inventoryName != "SkyBlock Menu") return + val list = event.inventoryItems[PLAYER_STATS_SLOT_INDEX]?.getLore() ?: return + DelayedRun.runNextTick { // Delayed to not impact opening time + assignEntry(list, StatSourceType.SKYBLOCK_MENU) { it.menuPattern } + } + } + + private val statsMenuRelevantSlotIndexes = listOf(15, 16, 24, 25) + + private fun onStatsMenu(event: InventoryFullyOpenedEvent) { + if (event.inventoryName != "Your Equipment and Stats") return + val list = statsMenuRelevantSlotIndexes.mapNotNull { event.inventoryItems[it]?.getLore() }.flatten() + if (list.isEmpty()) return + DelayedRun.runNextTick { // Delayed to not impact opening time + assignEntry(list, StatSourceType.STATS_MENU) { it.menuPattern } + } + } + + @SubscribeEvent + fun onTabList(event: WidgetUpdateEvent) { + if (!event.isWidget(TabWidget.STATS, TabWidget.DUNGEON_SKILLS_AND_STATS)) return + val type = if (event.isWidget(TabWidget.DUNGEON_SKILLS_AND_STATS)) StatSourceType.TABLIST_DUNGEON else StatSourceType.TABLIST + assignEntry(event.lines, type) { it.tablistPattern } + } + + private fun assignEntry(lines: List, type: StatSourceType, pattern: (SkyblockStat) -> Pattern) { + for (line in lines) for (entry in entries) { + val matchResult = pattern(entry).matchMatcher(line) { + groupOrNull("value")?.replace("[,%]".toRegex(), "")?.toDouble() + } ?: continue + entry.lastKnownValue = matchResult + entry.lastSource = type + break // Exit the inner loop once a match is found + } + } } } @@ -93,3 +192,10 @@ class SkyblockStatList : EnumMap(SkyblockStat::class.java) } } +enum class StatSourceType { + UNKNOWN, + SKYBLOCK_MENU, + STATS_MENU, + TABLIST, + TABLIST_DUNGEON, +} diff --git a/src/main/java/at/hannibal2/skyhanni/data/repo/RepoManager.kt b/src/main/java/at/hannibal2/skyhanni/data/repo/RepoManager.kt index ec6f0cbd9ebe..b3109c9ee4d6 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/repo/RepoManager.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/repo/RepoManager.kt @@ -36,7 +36,7 @@ class RepoManager(private val configLocation: File) { private var latestRepoCommit: String? = null val repoLocation: File = File(configLocation, "repo") private var error = false - private var lastRepoUpdate = SimpleTimeMark.farPast() + private var lastRepoUpdate = SimpleTimeMark.now() companion object { diff --git a/src/main/java/at/hannibal2/skyhanni/events/LorenzEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/LorenzEvent.kt index 4a294a6779ca..b567d9ae6d06 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/LorenzEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/LorenzEvent.kt @@ -7,6 +7,7 @@ import at.hannibal2.skyhanni.mixins.hooks.setValue import at.hannibal2.skyhanni.mixins.transformers.AccessorEventBus import at.hannibal2.skyhanni.test.command.ErrorManager import at.hannibal2.skyhanni.utils.ChatUtils +import at.hannibal2.skyhanni.utils.StringUtils import at.hannibal2.skyhanni.utils.chat.Text import at.hannibal2.skyhanni.utils.system.PlatformUtils import net.minecraftforge.common.MinecraftForge @@ -57,7 +58,8 @@ abstract class LorenzEvent : Event() { if (printError && errors <= visibleErrors) { val callerName = listener.toString().split(" ")[1].split("@")[0].split(".").last() val errorName = throwable::class.simpleName ?: "error" - val message = "Caught an $errorName in $callerName at $eventName: ${throwable.message}" + val aOrAn = StringUtils.optionalAn(errorName) + val message = "Caught $aOrAn $errorName in $callerName at $eventName: ${throwable.message}" ErrorManager.logErrorWithData(throwable, message, ignoreErrorCache = ignoreErrorCache) } onError(throwable) 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 4d9af4c9d042..28a2b4b4f081 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/chat/ChatFilter.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/chat/ChatFilter.kt @@ -281,6 +281,7 @@ object ChatFilter { "§6§lGOOD CATCH! §r§bYou found a §r§fSpooky Bait§r§b.", "§e[NPC] Jacob§f: §rMy contest has started!", "§eObtain a §r§6Booster Cookie §r§efrom the community shop in the hub!", + "Unknown command. Type \"/help\" for help. ('uhfdsolguhkjdjfhgkjhdfdlgkjhldkjhlkjhsldkjfhldshkjf')", ) private val skymallMessages = listOf( diff --git a/src/main/java/at/hannibal2/skyhanni/features/chat/CompactExperimentRewards.kt b/src/main/java/at/hannibal2/skyhanni/features/chat/CompactExperimentRewards.kt index 286166ee7c0b..8ad277b4a419 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/chat/CompactExperimentRewards.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/chat/CompactExperimentRewards.kt @@ -21,7 +21,7 @@ object CompactExperimentRewards { private val config get() = SkyHanniMod.feature.chat - private var gainedRewards = mutableListOf() + private val gainedRewards = mutableListOf() private var lastTimeTableOpened = SimpleTimeMark.farPast() private var currentMessage = "" @@ -89,7 +89,7 @@ object CompactExperimentRewards { } private fun sendMessage(reward: String?) { - if (gainedRewards.last() != reward || currentMessage == "") return + if (gainedRewards.lastOrNull() != reward || currentMessage == "") return val expList = mutableListOf().apply { gainedRewards.forEach { add("§8+$it") } diff --git a/src/main/java/at/hannibal2/skyhanni/features/combat/FerocityDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/combat/FerocityDisplay.kt index c30299e4f167..8ea8449f467a 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/combat/FerocityDisplay.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/combat/FerocityDisplay.kt @@ -1,14 +1,11 @@ package at.hannibal2.skyhanni.features.combat import at.hannibal2.skyhanni.SkyHanniMod -import at.hannibal2.skyhanni.data.model.TabWidget +import at.hannibal2.skyhanni.data.model.SkyblockStat import at.hannibal2.skyhanni.events.GuiRenderEvent -import at.hannibal2.skyhanni.events.WidgetUpdateEvent import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.LorenzUtils -import at.hannibal2.skyhanni.utils.RegexUtils.matchFirst import at.hannibal2.skyhanni.utils.RenderUtils.renderString -import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern import net.minecraftforge.fml.common.eventhandler.SubscribeEvent @SkyHanniModule @@ -16,35 +13,11 @@ object FerocityDisplay { private val config get() = SkyHanniMod.feature.combat.ferocityDisplay - /** - * REGEX-TEST: Ferocity: §r§c⫽14 - */ - private val ferocityPattern by RepoPattern.pattern( - "combat.ferocity.tab", - " Ferocity: §r§c⫽(?.*)", - ) - - private var display = "" - - @SubscribeEvent - fun onTabListUpdate(event: WidgetUpdateEvent) { - if (!isEnabled()) return - if (!event.isWidget(TabWidget.STATS, TabWidget.DUNGEON_SKILLS_AND_STATS)) return - display = "" - if (event.isClear()) return - val stat = event.lines.matchFirst(ferocityPattern) { - group("stat") - } ?: return - - display = "§c⫽$stat" - - } - @SubscribeEvent fun onRenderOverlay(event: GuiRenderEvent) { if (!isEnabled()) return - - config.position.renderString(display, posLabel = "Ferocity Display") + if (SkyblockStat.FEROCITY.lastKnownValue == 0.0) return + config.position.renderString(SkyblockStat.FEROCITY.displayValue, posLabel = "Ferocity Display") } fun isEnabled() = LorenzUtils.inSkyBlock && config.enabled diff --git a/src/main/java/at/hannibal2/skyhanni/features/combat/SpidersDenAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/combat/SpidersDenAPI.kt index 7986c55e9d3a..af1dd8430186 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/combat/SpidersDenAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/combat/SpidersDenAPI.kt @@ -1,12 +1,11 @@ package at.hannibal2.skyhanni.features.combat -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboard +import at.hannibal2.skyhanni.data.ScoreboardData import at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardPattern import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.RegexUtils.matches @SkyHanniModule object SpidersDenAPI { - private fun getSbLines(): List = CustomScoreboard.activeLines - fun isAtTopOfNest(): Boolean = getSbLines().any { ScoreboardPattern.broodmotherPattern.matches(it) } + fun isAtTopOfNest(): Boolean = ScoreboardData.sidebarLinesFormatted.any { ScoreboardPattern.broodmotherPattern.matches(it) } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/combat/ghostcounter/GhostCounter.kt b/src/main/java/at/hannibal2/skyhanni/features/combat/ghostcounter/GhostCounter.kt index 40e329f20cdf..14abcfad6f3c 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/combat/ghostcounter/GhostCounter.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/combat/ghostcounter/GhostCounter.kt @@ -11,6 +11,7 @@ import at.hannibal2.skyhanni.events.ConfigLoadEvent import at.hannibal2.skyhanni.events.GuiRenderEvent import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent import at.hannibal2.skyhanni.events.LorenzChatEvent +import at.hannibal2.skyhanni.events.LorenzTickEvent import at.hannibal2.skyhanni.events.PurseChangeCause import at.hannibal2.skyhanni.events.PurseChangeEvent import at.hannibal2.skyhanni.events.SecondPassedEvent @@ -24,6 +25,7 @@ import at.hannibal2.skyhanni.features.combat.ghostcounter.GhostUtil.isUsingCTGho import at.hannibal2.skyhanni.features.combat.ghostcounter.GhostUtil.preFormat import at.hannibal2.skyhanni.features.combat.ghostcounter.GhostUtil.prettyTime import at.hannibal2.skyhanni.features.inventory.bazaar.BazaarApi.getBazaarData +import at.hannibal2.skyhanni.features.misc.IslandAreas import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.ChatUtils import at.hannibal2.skyhanni.utils.ChatUtils.chat @@ -332,7 +334,6 @@ object GhostCounter { } } - inMist = LorenzUtils.skyBlockArea == "The Mist" update() if (event.repeatSeconds(2)) { @@ -341,6 +342,11 @@ object GhostCounter { } } + @SubscribeEvent + fun onTick(event: LorenzTickEvent) { + inMist = IslandAreas.currentAreaName == "The Mist" + } + @SubscribeEvent fun onActionBarUpdate(event: ActionBarUpdateEvent) { if (!isEnabled()) return diff --git a/src/main/java/at/hannibal2/skyhanni/features/commands/PartyCommands.kt b/src/main/java/at/hannibal2/skyhanni/features/commands/PartyCommands.kt index e7b3333dd7eb..3cbd43a785a2 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/commands/PartyCommands.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/commands/PartyCommands.kt @@ -2,7 +2,6 @@ package at.hannibal2.skyhanni.features.commands import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator -import at.hannibal2.skyhanni.data.FriendAPI import at.hannibal2.skyhanni.data.PartyAPI import at.hannibal2.skyhanni.data.PartyAPI.partyLeader import at.hannibal2.skyhanni.data.PartyAPI.transferVoluntaryPattern @@ -11,7 +10,6 @@ import at.hannibal2.skyhanni.events.MessageSendToServerEvent import at.hannibal2.skyhanni.features.misc.limbo.LimboTimeTracker import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.ChatUtils -import at.hannibal2.skyhanni.utils.EntityUtils import at.hannibal2.skyhanni.utils.HypixelCommands import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.RegexUtils.matches @@ -115,25 +113,9 @@ object PartyCommands { if (command == "pk" || command == "pt" || command == "pp" && config.shortCommands) { return PartyAPI.partyMembers } - - if (command == "p" || command == "party") { - val friends = if (config.tabComplete.friends) { - FriendAPI.getAllFriends().filter { it.bestFriend || !config.tabComplete.onlyBestFriends }.map { it.name } - } else { - emptyList() - } - val allOnLobby = EntityUtils.getPlayerEntities().map { it.name } - return friends + getPartyCommands() + allOnLobby - } return null } - private fun getPartyCommands(): List { - return if (config.tabComplete.partyCommands && PartyAPI.partyMembers.isNotEmpty()) { - otherPartyCommands - } else emptyList() - } - @SubscribeEvent fun onConfigFix(event: ConfigUpdaterMigrator.ConfigFixEvent) { event.move(5, "commands.usePartyTransferAlias", "commands.shortCommands") @@ -157,14 +139,3 @@ object PartyCommands { ) } } - -private val otherPartyCommands = listOf( - "Disband", - "KickOffline", - "Leave", - "List", - "Mute", - "Private", - "Warp", - "Settings", -) diff --git a/src/main/java/at/hannibal2/skyhanni/features/commands/ViewRecipeCommand.kt b/src/main/java/at/hannibal2/skyhanni/features/commands/ViewRecipeCommand.kt index e3d6a5713297..dbaf037ca363 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/commands/ViewRecipeCommand.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/commands/ViewRecipeCommand.kt @@ -6,6 +6,7 @@ import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.ChatUtils.senderIsSkyhanni import at.hannibal2.skyhanni.utils.HypixelCommands import at.hannibal2.skyhanni.utils.NEUItems +import at.hannibal2.skyhanni.utils.NumberUtil.isInt import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern import net.minecraftforge.fml.common.eventhandler.SubscribeEvent @@ -30,12 +31,20 @@ object ViewRecipeCommand { if (!config.viewRecipeLowerCase) return if (event.senderIsSkyhanni()) return - val item = pattern.matchMatcher(event.message.lowercase()) { - group("item").uppercase().replace(" ", "_") + val input = pattern.matchMatcher(event.message.lowercase()) { + group("item").uppercase() } ?: return + val args = input.split(" ") + val endsWithPageNumber = args.last().isInt() + val finalCommand = if (endsWithPageNumber) { + "${args.dropLast(1).joinToString("_")} ${args.last()}" + } else { + input.replace(" ", "_") + } + event.cancel() - HypixelCommands.viewRecipe(item) + HypixelCommands.viewRecipe(finalCommand) } val list by lazy { diff --git a/src/main/java/at/hannibal2/skyhanni/features/commands/WikiManager.kt b/src/main/java/at/hannibal2/skyhanni/features/commands/WikiManager.kt index af56be8e7ba4..e6a1ef4e955e 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/commands/WikiManager.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/commands/WikiManager.kt @@ -8,7 +8,6 @@ import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.ChatUtils import at.hannibal2.skyhanni.utils.InventoryUtils import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName -import at.hannibal2.skyhanni.utils.ItemUtils.itemName import at.hannibal2.skyhanni.utils.KeyboardManager.isKeyHeld import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.NEUItems @@ -50,7 +49,7 @@ object WikiManager { } if (message == ("/wikithis")) { val itemInHand = InventoryUtils.getItemInHand() ?: run { - ChatUtils.chat("§cYou must be holding an item to use this command!") + ChatUtils.userError("You must be holding an item to use this command!") return } wikiTheItem(itemInHand, config.autoOpenWiki) @@ -70,7 +69,7 @@ object WikiManager { private fun wikiTheItem(item: ItemStack, autoOpen: Boolean, useFandom: Boolean = config.useFandom) { val itemDisplayName = - item.itemName.replace("§a✔ ", "").replace("§c✖ ", "") + item.displayName.replace("§a✔ ", "").replace("§c✖ ", "") val internalName = item.getInternalName().asString() val wikiUrlSearch = if (internalName != "NONE") internalName else itemDisplayName.removeColor() @@ -79,7 +78,7 @@ object WikiManager { fun otherWikiCommands(args: Array, useFandom: Boolean, wikithis: Boolean = false) { if (wikithis && !LorenzUtils.inSkyBlock) { - ChatUtils.chat("§cYou must be in SkyBlock to do this!") + ChatUtils.userError("You must be in SkyBlock to do this!") return } @@ -88,7 +87,7 @@ object WikiManager { if (wikithis) { val itemInHand = InventoryUtils.getItemInHand() ?: run { - ChatUtils.chat("§cYou must be holding an item to use this command!") + ChatUtils.userError("You must be holding an item to use this command!") return } wikiTheItem(itemInHand, false, useFandom = useFandom) @@ -102,8 +101,10 @@ object WikiManager { } fun sendWikiMessage( - search: String = "", displaySearch: String = search, - autoOpen: Boolean = config.autoOpenWiki, useFandom: Boolean = config.useFandom + search: String = "", + displaySearch: String = search, + autoOpen: Boolean = config.autoOpenWiki, + useFandom: Boolean = config.useFandom, ) { val wiki = if (useFandom) "SkyBlock Fandom Wiki" else "Official SkyBlock Wiki" val urlPrefix = if (useFandom) FANDOM_URL_PREFIX else OFFICIAL_URL_PREFIX diff --git a/src/main/java/at/hannibal2/skyhanni/features/commands/suggestions/SuggestionEntry.kt b/src/main/java/at/hannibal2/skyhanni/features/commands/suggestions/SuggestionEntry.kt new file mode 100644 index 000000000000..74fcb0ef0e01 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/commands/suggestions/SuggestionEntry.kt @@ -0,0 +1,31 @@ +package at.hannibal2.skyhanni.features.commands.suggestions + +interface SuggestionEntry { + + val suggestions: List + + fun isEntryFor(argument: String): Boolean { + return this.suggestions.any { it.equals(argument, ignoreCase = true) } + } +} + +data class LiteralSuggestionEntry(override val suggestions: List) : SuggestionEntry + +data class CompositeSuggestionEntry(val entries: List) : SuggestionEntry { + override val suggestions: List get() = entries.flatMap { it.suggestions } + override fun isEntryFor(argument: String): Boolean = entries.any { it.isEntryFor(argument) } +} + +data class ParentSuggestionEntry(val parent: SuggestionEntry, val children: List) : SuggestionEntry { + override val suggestions: List get() = parent.suggestions + override fun isEntryFor(argument: String): Boolean = parent.isEntryFor(argument) +} + +data class LazySuggestionEntry(val supplier: MutableList.() -> Unit) : SuggestionEntry { + override val suggestions: List get() = mutableListOf().apply { supplier() } +} + +data class ConditionalSuggestionEntry(val condition: () -> Boolean, val entry: SuggestionEntry) : SuggestionEntry { + override val suggestions: List get() = if (condition()) entry.suggestions else emptyList() + override fun isEntryFor(argument: String): Boolean = entry.isEntryFor(argument) +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/commands/suggestions/SuggestionProvider.kt b/src/main/java/at/hannibal2/skyhanni/features/commands/suggestions/SuggestionProvider.kt new file mode 100644 index 000000000000..eda4c704cbcf --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/commands/suggestions/SuggestionProvider.kt @@ -0,0 +1,83 @@ +package at.hannibal2.skyhanni.features.commands.suggestions + +class SuggestionProvider { + + private val entry = mutableListOf() + + fun add(entry: SuggestionEntry) { + this.entry.add(entry) + } + + private fun List.getEntryForPath(path: List): SuggestionEntry? { + val entry = this.firstOrNull { it.isEntryFor(path.first()) } + val remainingPath = path.drop(1) + if (remainingPath.isNotEmpty()) { + if (entry is ParentSuggestionEntry) { + return entry.children.getEntryForPath(remainingPath) + } + return null + } else if (entry is ParentSuggestionEntry) { + return CompositeSuggestionEntry(entry.children) + } + return null + } + + fun getSuggestions(command: String): List { + val arguments = command.lowercase().split(" ") + val last = arguments.lastOrNull() ?: "" + val suggestions = mutableListOf() + if (arguments.size != 1) { + entry.getEntryForPath(arguments.dropLast(1))?.suggestions?.let { suggestions.addAll(it) } + } else { + entry.forEach { suggestions.addAll(it.suggestions) } + } + return suggestions.filter { it.startsWith(last, ignoreCase = true) } + } + + companion object { + + fun build(builder: Builder.() -> Unit): SuggestionProvider { + val b = Builder() + b.builder() + return b.build() + } + } +} + +class Builder { + private val entries = mutableListOf() + + fun add(entry: SuggestionEntry) { + entries.add(entry) + } + + fun conditional(condition: () -> Boolean, builder: Builder.() -> Unit) { + val childBuilder = Builder() + childBuilder.builder() + add(ConditionalSuggestionEntry(condition, CompositeSuggestionEntry(childBuilder.entries))) + } + + fun literal(vararg literals: String) { + add(LiteralSuggestionEntry(literals.toList())) + } + + fun lazy(supplier: () -> List) { + add(LazySuggestionEntry { addAll(supplier()) }) + } + + fun group(vararg children: SuggestionEntry) { + add(CompositeSuggestionEntry(children.toList())) + } + + fun parent(vararg literals: String, children: Builder.() -> Unit) { + val childBuilder = Builder() + childBuilder.children() + add(ParentSuggestionEntry(LiteralSuggestionEntry(literals.toList()), childBuilder.entries)) + } + + fun build(): SuggestionProvider { + val provider = SuggestionProvider() + entries.forEach { provider.add(it) } + return provider + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/commands/tabcomplete/PlayerTabComplete.kt b/src/main/java/at/hannibal2/skyhanni/features/commands/tabcomplete/PlayerTabComplete.kt index 070ab478e083..95acec9a6931 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/commands/tabcomplete/PlayerTabComplete.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/commands/tabcomplete/PlayerTabComplete.kt @@ -3,9 +3,12 @@ package at.hannibal2.skyhanni.features.commands.tabcomplete import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator import at.hannibal2.skyhanni.data.FriendAPI +import at.hannibal2.skyhanni.data.GuildAPI import at.hannibal2.skyhanni.data.PartyAPI import at.hannibal2.skyhanni.data.jsonobjects.repo.VipVisitsJson import at.hannibal2.skyhanni.events.RepositoryReloadEvent +import at.hannibal2.skyhanni.features.commands.suggestions.LazySuggestionEntry +import at.hannibal2.skyhanni.features.commands.suggestions.SuggestionProvider import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.EntityUtils import net.minecraftforge.fml.common.eventhandler.SubscribeEvent @@ -15,68 +18,97 @@ object PlayerTabComplete { private val config get() = SkyHanniMod.feature.misc.commands.tabComplete private var vipVisits = listOf() - private val ignoredCommandCategories = mapOf( - "f" to listOf(PlayerCategory.FRIENDS), - "friend" to listOf(PlayerCategory.FRIENDS), - "msg" to listOf(), - "w" to listOf(), - "tell" to listOf(), - "boop" to listOf(), + private val friendsEntry = lazyEntry { FriendAPI.getAllFriends().map { it.name } } + private val partyMembersEntry = lazyEntry { PartyAPI.partyMembers } + private val guildMembersEntry = lazyEntry { GuildAPI.getAllMembers() } + private val vipVisitsEntry = lazyEntry { vipVisits } + private val islandPlayersEntry = lazyEntry { EntityUtils.getPlayerEntities().map { it.name } } + + private val suggestions = SuggestionProvider.build { + parent("f", "friend") { + parent("accept", "add", "deny") { add(getExcluding(PlayerCategory.FRIENDS)) } + parent("best") { add(friendsEntry) } + parent("remove", "nickname") { add(friendsEntry) } + parent("list") { literal("best") } + literal("help", "notifications", "removeall", "requests") + } - "visit" to listOf(), - "invite" to listOf(), - "ah" to listOf(), + parent("g", "guild") { + parent("invite") { add(getExcluding(PlayerCategory.GUILD)) } + parent("kick", "transfer", "setrank", "promote", "demote") { add(guildMembersEntry) } + parent("mute", "unmute") { + add(guildMembersEntry) + literal("everyone") + } + parent("member") { add(guildMembersEntry) } + literal( + "top", "toggle", "tagcolor", "tag", "slow", "settings", "rename", "quest", "permissions", "party", "onlinemode", + "online", "officerchat", "notifications", "mypermissions", "motd", "menu", "members", "log", "leave", "info", "history", + "help", "discord", "disband", "create", "chat", "accept", + ) + } - "pv" to listOf(), // NEU's Profile Viewer - "shmarkplayer" to listOf(), // SkyHanni's Mark Player + parent("p", "party") { + parent("accept", "invite") { add(getExcluding(PlayerCategory.PARTY)) } + conditional({ PartyAPI.partyMembers.isNotEmpty() }) { + parent("kick", "demote", "promote", "transfer") { add(partyMembersEntry) } + literal("chat", "disband", "kickoffline", "leave", "list", "mute", "poll", "private", "settings", "warp") + } + } - "trade" to listOf(PlayerCategory.FRIENDS, PlayerCategory.PARTY), - ) + parent("w", "msg", "tell", "boop") { add(getExcluding()) } - @SubscribeEvent - fun onRepoReload(event: RepositoryReloadEvent) { - val data = event.getConstant("VipVisits") - vipVisits = data.vipVisits - } + parent("visit") { + add(getExcluding()) + conditional({ config.vipVisits }) { + add(vipVisitsEntry) + } + } - @SubscribeEvent - fun onConfigFix(event: ConfigUpdaterMigrator.ConfigFixEvent) { - event.move(2, "misc.tabCompleteCommands", "commands.tabComplete") + parent("invite") { add(getExcluding()) } + parent("ah") { add(getExcluding()) } + + parent("pv") { add(getExcluding()) } + parent("shmarkplayer") { add(getExcluding()) } + + parent("trade") { add(islandPlayersEntry) } } enum class PlayerCategory { FRIENDS, ISLAND_PLAYERS, PARTY, + GUILD, } - fun handleTabComplete(command: String): List? { - val ignoredCategories = ignoredCommandCategories[command] ?: return null - - return buildList { + private fun getExcluding(vararg categories: PlayerCategory) = LazySuggestionEntry { + if (config.friends && PlayerCategory.FRIENDS !in categories) { + addAll(FriendAPI.getAllFriends().filter { it.bestFriend || !config.onlyBestFriends }.map { it.name }) + } + if (config.islandPlayers && PlayerCategory.ISLAND_PLAYERS !in categories) { + addAll(EntityUtils.getPlayerEntities().map { it.name }) + } + if (config.party && PlayerCategory.PARTY !in categories) { + addAll(PartyAPI.partyMembers) + } + if (config.guild && PlayerCategory.GUILD !in categories) { + addAll(GuildAPI.getAllMembers()) + } + } - if (config.friends && PlayerCategory.FRIENDS !in ignoredCategories) { - FriendAPI.getAllFriends().filter { it.bestFriend || !config.onlyBestFriends }.forEach { add(it.name) } - } + private fun lazyEntry(getter: () -> List) = LazySuggestionEntry { addAll(getter()) } - if (config.islandPlayers && PlayerCategory.ISLAND_PLAYERS !in ignoredCategories) { - for (entity in EntityUtils.getPlayerEntities()) { - add(entity.name) - } - } + fun handleTabComplete(command: String): List? = suggestions.getSuggestions(command).takeIf { it.isNotEmpty() }?.distinct() - if (config.party && PlayerCategory.PARTY !in ignoredCategories) { - for (member in PartyAPI.partyMembers) { - add(member) - } - } + @SubscribeEvent + fun onRepoReload(event: RepositoryReloadEvent) { + val data = event.getConstant("VipVisits") + vipVisits = data.vipVisits + } - if (config.vipVisits && command == "visit") { - for (visit in vipVisits) { - add(visit) - } - } - } + @SubscribeEvent + fun onConfigFix(event: ConfigUpdaterMigrator.ConfigFixEvent) { + event.move(2, "misc.tabCompleteCommands", "commands.tabComplete") } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/commands/tabcomplete/TabComplete.kt b/src/main/java/at/hannibal2/skyhanni/features/commands/tabcomplete/TabComplete.kt index 602c4a3b9e10..aa66b69377dd 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/commands/tabcomplete/TabComplete.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/commands/tabcomplete/TabComplete.kt @@ -14,20 +14,18 @@ object TabComplete { @SubscribeEvent fun handleTabComplete(event: TabCompletionEvent) { val splits = event.leftOfCursor.split(" ") - if (splits.size > 1) { - var command = splits.first().lowercase() - if (command.startsWith("/")) { - command = command.substring(1) - customTabComplete(command)?.let { - event.addSuggestions(it) - } - } + if (splits.size <= 1) return + var command = splits.first().lowercase() + if (!command.startsWith("/")) return + command = command.substring(1) + customTabComplete(event.leftOfCursor.substring(1), command)?.let { + event.addSuggestions(it) } } - private fun customTabComplete(command: String): List? { + private fun customTabComplete(fullCommand: String, command: String): List? { GetFromSacksTabComplete.handleTabComplete(command)?.let { return it } - PlayerTabComplete.handleTabComplete(command)?.let { return it } + PlayerTabComplete.handleTabComplete(fullCommand)?.let { return it } CollectionTracker.handleTabComplete(command)?.let { return it } PartyCommands.customTabComplete(command)?.let { return it } ViewRecipeCommand.customTabComplete(command)?.let { return it } diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCollectionStats.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCollectionStats.kt index 7d2a6a457c28..6d201e57edcd 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCollectionStats.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCollectionStats.kt @@ -505,7 +505,11 @@ object HoppityCollectionStats { val found = !rabbitNotFoundPattern.anyMatches(itemLore) - if (!found) continue + if (!found) { + // if the config has wrong data, remove it + loggedRabbits.remove(itemName) + continue + } val duplicates = duplicatesFoundPattern.firstMatcher(itemLore) { group("duplicates").formatInt() diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/WarpMenuUniques.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/WarpMenuUniques.kt new file mode 100644 index 000000000000..939dea1b702f --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/WarpMenuUniques.kt @@ -0,0 +1,58 @@ +package at.hannibal2.skyhanni.features.event.hoppity + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.data.IslandType +import at.hannibal2.skyhanni.events.LorenzToolTipEvent +import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactoryAPI +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.LorenzVec +import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher +import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +@SkyHanniModule +object WarpMenuUniques { + + /** + * REGEX-TEST: §bSkyBlock Hub + * REGEX-TEST: §aThe Barn§7 - §bSpawn + * REGEX-TEST: §aCrystal Hollows§7 - §bEntrance + */ + private val islandNamePattern by RepoPattern.pattern( + "inventory.warpmenu.island.name", + "§[ab](?[\\w ']+)(?:§7 - §b.*)?", + ) + + private val collectedEggStorage: MutableMap>? + get() = ChocolateFactoryAPI.profileStorage?.collectedEggLocations + + private val config get() = SkyHanniMod.feature.event.hoppityEggs + + @SubscribeEvent + fun onTooltip(event: LorenzToolTipEvent) { + if (!LorenzUtils.inSkyBlock) return + if (!config.uniquesWarpMenu) return + if (!HoppityAPI.isHoppityEvent()) return + if (event.slot.inventory.name != "Fast Travel") return + + val name = islandNamePattern.matchMatcher(event.slot.stack.displayName) { + group("name") + } ?: return + + val island = when (name) { + "SkyBlock Hub" -> IslandType.HUB + "The Barn" -> IslandType.THE_FARMING_ISLANDS + else -> IslandType.getByNameOrNull(name) ?: return + } + if (island == IslandType.DUNGEON_HUB) return + + if (HoppityEggLocations.apiEggLocations[island]?.size == null) return + val maxEggs = 15 + val collectedEggs = collectedEggStorage?.get(island)?.size ?: 0 + + if (collectedEggs >= maxEggs && config.uniquesWarpMenuHideMax) return + + event.toolTip.add(2, "§7Collected Hoppity Eggs: ${if (collectedEggs == maxEggs) "§a" else ""}$collectedEggs/$maxEggs") + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/fame/UpgradeReminder.kt b/src/main/java/at/hannibal2/skyhanni/features/fame/UpgradeReminder.kt index d22151c1b014..b55aa8f11e7f 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/fame/UpgradeReminder.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/fame/UpgradeReminder.kt @@ -96,6 +96,36 @@ object UpgradeReminder { fun onInventoryOpen(event: InventoryFullyOpenedEvent) { if (!LorenzUtils.inSkyBlock) return inInventory = event.inventoryName == "Community Shop" + if (!inInventory) return + + if (currentProfileUpgrade == null && currentAccountUpgrade == null) return + detectWrongAccountUpgradeData(event.inventoryItems) + } + + private fun detectWrongAccountUpgradeData(items: Map) { + val hasProfileUpgrade = foundActiveUpgrade(items, 27..35) + if (!hasProfileUpgrade && currentProfileUpgrade != null) { + ChatUtils.chat("§eRemoved invalid Profile Upgrade information.") + currentProfileUpgrade = null + } + + val hasAccountUpgrade = foundActiveUpgrade(items, 36..44) + if (!hasAccountUpgrade && currentAccountUpgrade != null) { + ChatUtils.chat("§eRemoved invalid Account Upgrade information.") + currentAccountUpgrade = null + } + } + + private fun foundActiveUpgrade(items: Map, slots: IntRange): Boolean { + for (slot in slots) { + val item = items[slot] ?: continue + val isUpgrading = item.getLore().any { it == "§aCurrently upgrading!" } + val isDone = item.getLore().any { it == "§cClick to claim!" } + val isReadyForUpgrade = item.getLore().any { it == "§eClick to start upgrade!" } + if (isUpgrading || isDone) return true + if (isReadyForUpgrade) return false + } + return false } @SubscribeEvent diff --git a/src/main/java/at/hannibal2/skyhanni/features/fishing/FishingAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/fishing/FishingAPI.kt index 596d6f49cfd2..89ae7dc18317 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/fishing/FishingAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/fishing/FishingAPI.kt @@ -9,6 +9,7 @@ import at.hannibal2.skyhanni.events.LorenzTickEvent import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent import at.hannibal2.skyhanni.events.RepositoryReloadEvent import at.hannibal2.skyhanni.events.entity.EntityEnterWorldEvent +import at.hannibal2.skyhanni.features.dungeon.DungeonAPI import at.hannibal2.skyhanni.features.fishing.trophy.TrophyFishManager import at.hannibal2.skyhanni.features.fishing.trophy.TrophyFishManager.getFilletValue import at.hannibal2.skyhanni.features.fishing.trophy.TrophyRarity @@ -137,7 +138,8 @@ object FishingAPI { return info?.getFilletValue(rarity) ?: 0 } - fun isFishing(checkRodInHand: Boolean = true) = IsFishingDetection.isFishing || (checkRodInHand && holdingRod) + fun isFishing(checkRodInHand: Boolean = true) = + (IsFishingDetection.isFishing || (checkRodInHand && holdingRod)) && !DungeonAPI.inDungeon() fun seaCreatureCount(entity: EntityArmorStand): Int { val name = entity.name diff --git a/src/main/java/at/hannibal2/skyhanni/features/fishing/tracker/SeaCreatureTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/fishing/tracker/SeaCreatureTracker.kt index ca8a73ce9d5f..e106858012de 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/fishing/tracker/SeaCreatureTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/fishing/tracker/SeaCreatureTracker.kt @@ -4,11 +4,13 @@ import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.events.ConfigLoadEvent import at.hannibal2.skyhanni.events.FishingBobberCastEvent import at.hannibal2.skyhanni.events.GuiRenderEvent +import at.hannibal2.skyhanni.events.ProfileJoinEvent import at.hannibal2.skyhanni.events.SeaCreatureFishEvent import at.hannibal2.skyhanni.features.fishing.FishingAPI import at.hannibal2.skyhanni.features.fishing.SeaCreatureManager import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.test.command.ErrorManager +import at.hannibal2.skyhanni.utils.ChatUtils import at.hannibal2.skyhanni.utils.CollectionUtils.addOrPut import at.hannibal2.skyhanni.utils.CollectionUtils.addSearchString import at.hannibal2.skyhanni.utils.CollectionUtils.sumAllValues @@ -25,6 +27,7 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent @SkyHanniModule object SeaCreatureTracker { + private var needMigration = true private val config get() = SkyHanniMod.feature.fishing.seaCreatureTracker @@ -72,7 +75,15 @@ object SeaCreatureTracker { return map } + @SubscribeEvent + fun onProfileJoin(event: ProfileJoinEvent) { + needMigration = true + } + private fun drawDisplay(data: Data): List = buildList { + // manually migrating from "Phlhlegblast" to "Plhlegblast" when the new name is in the repo + tryToMigrate(data.amount) + addSearchString("§7Sea Creature Tracker:") val filter: (String) -> Boolean = addCategories(data) @@ -85,7 +96,7 @@ object SeaCreatureTracker { "Sea Creature Tracker can not display a name correctly", "Could not find sea creature by name", "SeaCreatureManager.allFishingMobs.keys" to SeaCreatureManager.allFishingMobs.keys, - "name" to name + "name" to name, ) name } @@ -100,6 +111,25 @@ object SeaCreatureTracker { addSearchString(" §7- §e${total.addSeparators()} §7Total Sea Creatures") } + private fun tryToMigrate( + data: MutableMap, + ) { + if (!needMigration) return + needMigration = false + + val oldName = "Phlhlegblast" + val newName = "Plhlegblast" + + // only migrate once the repo contains the new name + if (SeaCreatureManager.allFishingMobs.containsKey(newName)) { + data[oldName]?.let { + ChatUtils.debug("Sea Creature Tracker migrated $it $oldName to $newName") + data[newName] = it + data.remove(oldName) + } + } + } + private fun MutableList.addCategories(data: Data): (String) -> Boolean { val amounts = getCurrentCategories(data) val list = amounts.keys.toList() @@ -115,7 +145,7 @@ object SeaCreatureTracker { val id = list.indexOf(currentCategory) currentCategory = list[(id + 1) % list.size] tracker.update() - } + }, ) } @@ -161,6 +191,5 @@ object SeaCreatureTracker { tracker.resetCommand() } - private fun isEnabled() = - LorenzUtils.inSkyBlock && config.enabled && !FishingAPI.wearingTrophyArmor && !LorenzUtils.inKuudraFight + private fun isEnabled() = LorenzUtils.inSkyBlock && config.enabled && !FishingAPI.wearingTrophyArmor && !LorenzUtils.inKuudraFight } diff --git a/src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/TrophyFishMessages.kt b/src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/TrophyFishMessages.kt index 66ddde50b939..4a23e84e5d52 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/TrophyFishMessages.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/TrophyFishMessages.kt @@ -96,7 +96,7 @@ object TrophyFishMessages { } private fun sendTitle(displayName: String, displayRarity: String?, amount: Int) { - val text = "$displayName\n$displayRarity $amount!" + val text = "$displayName $displayRarity §8$amount§c!" LorenzUtils.sendTitle(text, 3.seconds, 2.8, 7f) } diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/SensitivityReducer.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/SensitivityReducer.kt index ceec04aa0f20..d8593047ec26 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/SensitivityReducer.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/SensitivityReducer.kt @@ -126,7 +126,7 @@ object SensitivityReducer { fun manualToggle() { if (isToggled) { - ChatUtils.chat("This command is disabled while the Sensitivity is lowered.") + ChatUtils.userError("This command is disabled while the Sensitivity is lowered!") return } isManualToggle = !isManualToggle 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 3a69f2ece3b8..af31448d66e4 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 @@ -11,15 +11,17 @@ import at.hannibal2.skyhanni.features.garden.GardenAPI import at.hannibal2.skyhanni.features.garden.farming.GardenCropSpeed import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.test.command.ErrorManager +import at.hannibal2.skyhanni.utils.HypixelCommands import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.RegexUtils.matchFirst -import at.hannibal2.skyhanni.utils.RenderUtils.renderString +import at.hannibal2.skyhanni.utils.RenderUtils.renderRenderable import at.hannibal2.skyhanni.utils.SimpleTimeMark import at.hannibal2.skyhanni.utils.SoundUtils import at.hannibal2.skyhanni.utils.StringUtils.removeColor import at.hannibal2.skyhanni.utils.TabListData import at.hannibal2.skyhanni.utils.TimeUtils import at.hannibal2.skyhanni.utils.TimeUtils.format +import at.hannibal2.skyhanni.utils.renderables.Renderable import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import kotlin.time.Duration @@ -36,10 +38,10 @@ object GardenVisitorTimer { private val timePattern by RepoPattern.pattern( "garden.visitor.timer.time.new", - " Next Visitor: §r(?.*)" + " Next Visitor: §r(?.*)", ) - private var display = "" + private var display: Renderable? = null private var lastMillis = 0.seconds private var sixthVisitorArrivalTime = SimpleTimeMark.farPast() private var visitorJustArrived = false @@ -65,7 +67,7 @@ object GardenVisitorTimer { @SubscribeEvent fun onProfileJoin(event: ProfileJoinEvent) { - display = "" + display = null lastMillis = 0.seconds sixthVisitorArrivalTime = SimpleTimeMark.farPast() visitorJustArrived = false @@ -84,7 +86,7 @@ object GardenVisitorTimer { TabListData.getTabList().matchFirst(timePattern) { val timeInfo = group("info").removeColor() if (timeInfo == "Not Unlocked!") { - display = "§cVisitors not unlocked!" + display = Renderable.string("§cVisitors not unlocked!") return } if (timeInfo == "Queue Full!") { @@ -97,7 +99,7 @@ object GardenVisitorTimer { millis = TimeUtils.getDuration(timeInfo) } } ?: run { - display = "§cVisitor time info not in tab list" + display = createDisplayText("§cVisitor time info not in tab list") return } @@ -140,7 +142,7 @@ object GardenVisitorTimer { if (lastMillis == Duration.INFINITE) { ErrorManager.logErrorStateWithData( "Found Visitor Timer bug, reset value", "lastMillis was infinite", - "lastMillis" to lastMillis + "lastMillis" to lastMillis, ) lastMillis = 0.seconds } @@ -168,14 +170,20 @@ object GardenVisitorTimer { "Next in §$formatColor$formatDuration$extraSpeed" } val visitorLabel = if (visitorsAmount == 1) "visitor" else "visitors" - display = "§b$visitorsAmount $visitorLabel §7($next§7)" + display = createDisplayText("§b$visitorsAmount $visitorLabel §7($next§7)") } + private fun createDisplayText(text: String) = Renderable.clickAndHover( + text, + listOf("§eClick to teleport to the barn!"), + onClick = { HypixelCommands.teleportToPlot("barn") }, + ) + @SubscribeEvent fun onRenderOverlay(event: GuiRenderEvent.GuiOverlayRenderEvent) { if (!isEnabled()) return - config.pos.renderString(display, posLabel = "Garden Visitor Timer") + config.pos.renderRenderable(display, posLabel = "Garden Visitor Timer") } @SubscribeEvent diff --git a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/CustomScoreboard.kt b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/CustomScoreboard.kt index c9fb4b15f821..4a86519c374e 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/CustomScoreboard.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/CustomScoreboard.kt @@ -30,6 +30,7 @@ import at.hannibal2.skyhanni.utils.RenderUtils.HorizontalAlignment import at.hannibal2.skyhanni.utils.RenderUtils.VerticalAlignment import at.hannibal2.skyhanni.utils.RenderUtils.renderRenderable import at.hannibal2.skyhanni.utils.SimpleTimeMark +import at.hannibal2.skyhanni.utils.SimpleTimeMark.Companion.fromNow import at.hannibal2.skyhanni.utils.StringUtils.firstLetterUppercase import at.hannibal2.skyhanni.utils.TabListData import at.hannibal2.skyhanni.utils.renderables.Renderable @@ -50,12 +51,7 @@ object CustomScoreboard { private var cache = emptyList() private const val GUI_NAME = "Custom Scoreboard" - // Cached scoreboard data, only update after no change for 300ms - var activeLines = emptyList() - - // Most recent scoreboard state, not in use until cached - private var mostRecentLines = emptyList() - private var lastScoreboardUpdate = SimpleTimeMark.farFuture() + private var nextScoreboardUpdate = SimpleTimeMark.farFuture() @SubscribeEvent fun onRenderOverlay(event: GuiRenderEvent.GuiOverlayRenderEvent) { @@ -87,9 +83,7 @@ object CustomScoreboard { fun onGuiPositionMoved(event: GuiPositionMovedEvent) { if (event.guiName == GUI_NAME) { with(alignmentConfig) { - if (horizontalAlignment != HorizontalAlignment.DONT_ALIGN || - verticalAlignment != VerticalAlignment.DONT_ALIGN - ) { + if (horizontalAlignment != HorizontalAlignment.DONT_ALIGN || verticalAlignment != VerticalAlignment.DONT_ALIGN) { val tempHori = horizontalAlignment val tempVert = verticalAlignment @@ -113,16 +107,9 @@ object CustomScoreboard { fun onTick(event: LorenzTickEvent) { if (!isEnabled()) return - // We want to update the scoreboard as soon as we have new data, not 5 ticks delayed - var dirty = false - if (lastScoreboardUpdate.passedSince() > 300.milliseconds) { - activeLines = mostRecentLines - lastScoreboardUpdate = SimpleTimeMark.farFuture() - dirty = true - } - - // Creating the lines - if (event.isMod(5) || dirty) { + if (dirty || nextScoreboardUpdate.isInPast()) { + nextScoreboardUpdate = 250.milliseconds.fromNow() + dirty = false display = createLines().removeEmptyLinesFromEdges() if (TabListData.fullyLoaded) { cache = display.toList() @@ -135,11 +122,9 @@ object CustomScoreboard { @SubscribeEvent fun onScoreboardChange(event: ScoreboardUpdateEvent) { - mostRecentLines = event.scoreboard - lastScoreboardUpdate = SimpleTimeMark.now() + dirty = true } - internal val config get() = SkyHanniMod.feature.gui.customScoreboard internal val displayConfig get() = config.display internal val alignmentConfig get() = displayConfig.alignment @@ -160,12 +145,12 @@ object CustomScoreboard { private fun addAllNonSkyBlockLines() = buildList { addAll(ScoreboardElement.TITLE.getVisiblePair()) - addAll(activeLines.map { it to HorizontalAlignment.LEFT }) + addAll(ScoreboardData.sidebarLinesFormatted.map { it to HorizontalAlignment.LEFT }) } private fun addDefaultSkyBlockLines() = buildList { add(ScoreboardData.objectiveTitle to displayConfig.titleAndFooter.alignTitleAndFooter) - addAll(activeLines.map { it to HorizontalAlignment.LEFT }) + addAll(ScoreboardData.sidebarLinesFormatted.map { it to HorizontalAlignment.LEFT }) } private fun addCustomSkyBlockLines() = buildList { @@ -175,7 +160,8 @@ object CustomScoreboard { if ( informationFilteringConfig.hideConsecutiveEmptyLines && - lines.first().first == "" && lastOrNull()?.first?.isEmpty() == true + lines.first().first == "" && + lastOrNull()?.first?.isEmpty() == true ) { continue } diff --git a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/CustomScoreboardUtils.kt b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/CustomScoreboardUtils.kt index 4cfc403c421f..99fdc4f3fcf6 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/CustomScoreboardUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/CustomScoreboardUtils.kt @@ -3,6 +3,7 @@ package at.hannibal2.skyhanni.features.gui.customscoreboard import at.hannibal2.skyhanni.config.features.gui.customscoreboard.DisplayConfig import at.hannibal2.skyhanni.data.BitsAPI import at.hannibal2.skyhanni.data.HypixelData +import at.hannibal2.skyhanni.data.ScoreboardData import at.hannibal2.skyhanni.features.bingo.BingoAPI import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboard.displayConfig import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators @@ -27,7 +28,7 @@ object CustomScoreboardUtils { fun getProfileTypeSymbol() = when { HypixelData.ironman -> "§7♲ " HypixelData.stranded -> "§a☀ " - HypixelData.bingo -> CustomScoreboard.activeLines.firstNotNullOfOrNull { + HypixelData.bingo -> ScoreboardData.sidebarLinesFormatted.firstNotNullOfOrNull { BingoAPI.getIconFromScoreboard(it)?.plus(" ") } ?: "§e❤ " @@ -43,7 +44,7 @@ object CustomScoreboardUtils { internal fun String.formatNum() = this.formatDouble().formatNum() - internal fun getMotes() = getGroupFromPattern(CustomScoreboard.activeLines, ScoreboardPattern.motesPattern, "motes") + internal fun getMotes() = getGroupFromPattern(ScoreboardData.sidebarLinesFormatted, ScoreboardPattern.motesPattern, "motes") internal fun getBank() = getGroupFromPattern(TabListData.getTabList(), ScoreboardPattern.bankPattern, "bank") internal fun getBits() = BitsAPI.bits.coerceAtLeast(0).formatNum() @@ -57,15 +58,15 @@ object CustomScoreboardUtils { } internal fun getCopper() = - getGroupFromPattern(CustomScoreboard.activeLines, ScoreboardPattern.copperPattern, "copper") + getGroupFromPattern(ScoreboardData.sidebarLinesFormatted, ScoreboardPattern.copperPattern, "copper") internal fun getGems() = getGroupFromPattern(TabListData.getTabList(), ScoreboardPattern.gemsPattern, "gems") internal fun getHeat() = - getGroupFromPattern(CustomScoreboard.activeLines, ScoreboardPattern.heatPattern, "heat") + getGroupFromPattern(ScoreboardData.sidebarLinesFormatted, ScoreboardPattern.heatPattern, "heat") internal fun getNorthStars() = - getGroupFromPattern(CustomScoreboard.activeLines, ScoreboardPattern.northstarsPattern, "northstars") + getGroupFromPattern(ScoreboardData.sidebarLinesFormatted, ScoreboardPattern.northstarsPattern, "northstars") class UndetectedScoreboardLines(message: String) : Exception(message) diff --git a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardElements.kt b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardElements.kt index 0289a3c81862..e1c5d3f845d1 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardElements.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardElements.kt @@ -39,8 +39,6 @@ import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.getHeat import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.getMotes import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.getNorthStars -import at.hannibal2.skyhanni.test.command.ErrorManager -import at.hannibal2.skyhanni.utils.CollectionUtils.editCopy import at.hannibal2.skyhanni.utils.CollectionUtils.nextAfter import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.LorenzUtils.inAdvancedMiningIsland @@ -50,41 +48,25 @@ import at.hannibal2.skyhanni.utils.NumberUtil.percentageColor import at.hannibal2.skyhanni.utils.RegexUtils.anyMatches import at.hannibal2.skyhanni.utils.RegexUtils.matches import at.hannibal2.skyhanni.utils.RenderUtils.HorizontalAlignment +import at.hannibal2.skyhanni.utils.SimpleTimeMark import at.hannibal2.skyhanni.utils.SkyBlockTime import at.hannibal2.skyhanni.utils.StringUtils.firstLetterUppercase import at.hannibal2.skyhanni.utils.StringUtils.pluralize import at.hannibal2.skyhanni.utils.TabListData -import at.hannibal2.skyhanni.utils.TimeLimitedSet import at.hannibal2.skyhanni.utils.TimeUtils.format import at.hannibal2.skyhanni.utils.TimeUtils.formatted import kotlin.time.Duration.Companion.seconds -internal var confirmedUnknownLines = listOf() -internal var unconfirmedUnknownLines = listOf() -internal var unknownLinesSet = TimeLimitedSet(1.seconds) { onRemoval(it) } - -private fun onRemoval(line: String) { - if (!LorenzUtils.inSkyBlock) return - if (!unconfirmedUnknownLines.contains(line)) return - if (line !in unconfirmedUnknownLines) return - unconfirmedUnknownLines = unconfirmedUnknownLines.filterNot { it == line } - confirmedUnknownLines = confirmedUnknownLines.editCopy { add(line) } - if (!config.unknownLinesWarning) return - val pluralize = pluralize(confirmedUnknownLines.size, "unknown line", withNumber = true) - val message = "CustomScoreboard detected $pluralize" - ErrorManager.logErrorWithData( - CustomScoreboardUtils.UndetectedScoreboardLines(message), - message, - "Unknown Lines" to confirmedUnknownLines, - "Island" to LorenzUtils.skyBlockIsland, - "Area" to HypixelData.skyBlockArea, - "Full Scoreboard" to CustomScoreboard.activeLines, - noStackTrace = true, - betaOnly = true, - ) -} +internal var allUnknownLines = listOf() +internal var lastRecentAlarmWarning = SimpleTimeMark.farPast() -internal var amountOfUnknownLines = 0 +internal fun recentUnknownLines() = allUnknownLines.filter { it.lastFound.passedSince() < 3.seconds } + +internal class UnknownLine(val line: String) { + val firstFound = SimpleTimeMark.now() + var lastFound = SimpleTimeMark.now() + var lastWarned = SimpleTimeMark.farPast() +} enum class ScoreboardElement( private val displayPair: () -> List, @@ -389,7 +371,7 @@ private fun getPurseDisplayPair(): List { var purse = PurseAPI.currentPurse.formatNum() if (!displayConfig.hideCoinsDifference) { - val earned = getGroupFromPattern(CustomScoreboard.activeLines, PurseAPI.coinsPattern, "earned") + val earned = getGroupFromPattern(ScoreboardData.sidebarLinesFormatted, PurseAPI.coinsPattern, "earned") if (earned != null) purse += " §7(§e+$earned§7)§6" } @@ -492,7 +474,7 @@ private fun getHeatDisplayPair(): List { } private fun getHeatShowWhen() = inAnyIsland(IslandType.CRYSTAL_HOLLOWS) && - CustomScoreboard.activeLines.any { ScoreboardPattern.heatPattern.matches(it) } + ScoreboardData.sidebarLinesFormatted.any { ScoreboardPattern.heatPattern.matches(it) } private fun getColdDisplayPair(): List { val cold = -MiningAPI.cold @@ -507,7 +489,7 @@ private fun getColdDisplayPair(): List { } private fun getColdShowWhen() = inAnyIsland(IslandType.DWARVEN_MINES, IslandType.MINESHAFT) && - CustomScoreboard.activeLines.any { ScoreboardPattern.coldPattern.matches(it) } + ScoreboardData.sidebarLinesFormatted.any { ScoreboardPattern.coldPattern.matches(it) } private fun getNorthStarsDisplayPair(): List { val northStars = getNorthStars()?.formatNum() ?: "0" @@ -550,7 +532,7 @@ private fun getIslandDisplayPair() = private fun getLocationDisplayPair() = buildList { HypixelData.skyBlockAreaWithSymbol?.let { add(it to HorizontalAlignment.LEFT) } - CustomScoreboard.activeLines.firstOrNull { ScoreboardPattern.plotPattern.matches(it) } + ScoreboardData.sidebarLinesFormatted.firstOrNull { ScoreboardPattern.plotPattern.matches(it) } ?.let { add(it to HorizontalAlignment.LEFT) } } @@ -568,12 +550,12 @@ fun getPlayerAmountDisplayPair() = buildList { private fun getVisitDisplayPair() = listOf( - CustomScoreboard.activeLines.first { ScoreboardPattern.visitingPattern.matches(it) } to + ScoreboardData.sidebarLinesFormatted.first { ScoreboardPattern.visitingPattern.matches(it) } to HorizontalAlignment.LEFT, ) private fun getVisitShowWhen() = - CustomScoreboard.activeLines.any { ScoreboardPattern.visitingPattern.matches(it) } + ScoreboardData.sidebarLinesFormatted.any { ScoreboardPattern.visitingPattern.matches(it) } private fun getDateDisplayPair() = listOf( @@ -582,7 +564,7 @@ private fun getDateDisplayPair() = private fun getTimeDisplayPair(): List { val symbol = - getGroupFromPattern(CustomScoreboard.activeLines, ScoreboardPattern.timePattern, "symbol") ?: "" + getGroupFromPattern(ScoreboardData.sidebarLinesFormatted, ScoreboardPattern.timePattern, "symbol") ?: "" return listOf( "§7" + SkyBlockTime.now() .formatted( @@ -671,7 +653,7 @@ private fun getCookieShowWhen(): Boolean { } private fun getObjectiveDisplayPair() = buildList { - val formattedLines = CustomScoreboard.activeLines + val formattedLines = ScoreboardData.sidebarLinesFormatted val objective = formattedLines.firstOrNull { ScoreboardPattern.objectivePattern.matches(it) } if (objective != null) { add(objective to HorizontalAlignment.LEFT) @@ -690,7 +672,7 @@ private fun getObjectiveDisplayPair() = buildList { } private fun getObjectiveShowWhen(): Boolean = - ScoreboardPattern.objectivePattern.anyMatches(CustomScoreboard.activeLines) + ScoreboardPattern.objectivePattern.anyMatches(ScoreboardData.sidebarLinesFormatted) private fun getSlayerDisplayPair(): List = buildList { add((if (SlayerAPI.hasActiveSlayerQuest()) "Slayer Quest" else "") to HorizontalAlignment.LEFT) @@ -802,6 +784,11 @@ private fun getMayorDisplayPair() = buildList { } if (!mayorConfig.showExtraMayor) return@buildList + addAll(addMinister()) + addAll(addPerkpocalypseMayor()) +} + +private fun addMinister() = buildList { val ministerName = MayorAPI.currentMinister?.mayorName?.let { MayorAPI.mayorNameWithColorCode(it) } ?: return@buildList add(ministerName to HorizontalAlignment.LEFT) @@ -810,7 +797,9 @@ private fun getMayorDisplayPair() = buildList { add(" §7- §e${perk.perkName}" to HorizontalAlignment.LEFT) } } +} +private fun addPerkpocalypseMayor() = buildList { val jerryExtraMayor = MayorAPI.jerryExtraMayor val extraMayor = jerryExtraMayor.first ?: return@buildList @@ -860,15 +849,10 @@ private fun getFooterDisplayPair(): List = listOf( ).flatten() private fun getExtraDisplayPair(): List { - if (unconfirmedUnknownLines.isEmpty()) return listOf("" to HorizontalAlignment.LEFT) - amountOfUnknownLines = unconfirmedUnknownLines.size + val lines = recentUnknownLines() + if (lines.isEmpty()) return listOf("" to HorizontalAlignment.LEFT) - return listOf("§cUndetected Lines:" to HorizontalAlignment.LEFT) + unconfirmedUnknownLines.map { it to HorizontalAlignment.LEFT } + return listOf("§cUndetected Lines:" to HorizontalAlignment.LEFT) + lines.map { it.line to HorizontalAlignment.LEFT } } -private fun getExtraShowWhen(): Boolean { - if (unconfirmedUnknownLines.isEmpty()) { - amountOfUnknownLines = 0 - } - return unconfirmedUnknownLines.isNotEmpty() -} +private fun getExtraShowWhen(): Boolean = recentUnknownLines().isNotEmpty() diff --git a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardEvent.kt b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardEvent.kt index 6531d5158d75..3d8251dfbb63 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardEvent.kt @@ -2,6 +2,7 @@ package at.hannibal2.skyhanni.features.gui.customscoreboard import at.hannibal2.skyhanni.data.HypixelData import at.hannibal2.skyhanni.data.IslandType +import at.hannibal2.skyhanni.data.ScoreboardData import at.hannibal2.skyhanni.data.model.TabWidget import at.hannibal2.skyhanni.features.combat.SpidersDenAPI.isAtTopOfNest import at.hannibal2.skyhanni.features.dungeon.DungeonAPI @@ -29,7 +30,7 @@ import at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardPattern as * because they are visible for a maximum of like 1 minute every 5 days and ~12 hours. */ -private fun getSbLines(): List = CustomScoreboard.activeLines +private fun getSbLines(): List = ScoreboardData.sidebarLinesFormatted enum class ScoreboardEvent( private val displayLine: () -> List, diff --git a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/UnknownLinesHandler.kt b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/UnknownLinesHandler.kt index 38612f29703b..0dff1f4933dd 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/UnknownLinesHandler.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/UnknownLinesHandler.kt @@ -1,15 +1,22 @@ package at.hannibal2.skyhanni.features.gui.customscoreboard import at.hannibal2.skyhanni.data.BitsAPI +import at.hannibal2.skyhanni.data.HypixelData import at.hannibal2.skyhanni.data.PurseAPI +import at.hannibal2.skyhanni.data.ScoreboardData import at.hannibal2.skyhanni.features.misc.ServerRestartTitle import at.hannibal2.skyhanni.features.rift.area.stillgorechateau.RiftBloodEffigies +import at.hannibal2.skyhanni.test.command.ErrorManager import at.hannibal2.skyhanni.utils.ChatUtils +import at.hannibal2.skyhanni.utils.CollectionUtils.editCopy import at.hannibal2.skyhanni.utils.CollectionUtils.nextAfter import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.RegexUtils.matches +import at.hannibal2.skyhanni.utils.SimpleTimeMark import at.hannibal2.skyhanni.utils.StringUtils.removeResets import java.util.regex.Pattern +import kotlin.time.Duration.Companion.minutes +import kotlin.time.Duration.Companion.seconds import at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardPattern as SbPattern object UnknownLinesHandler { @@ -133,7 +140,7 @@ object UnknownLinesHandler { private var remoteOnlyPatternsAdded = false fun handleUnknownLines() { - val sidebarLines = CustomScoreboard.activeLines + val sidebarLines = ScoreboardData.sidebarLinesFormatted var unknownLines = sidebarLines.map { it.removeResets() }.filter { it.isNotBlank() }.filter { it.trim().length > 3 } @@ -205,19 +212,50 @@ object UnknownLinesHandler { /* * Handle broken scoreboard lines */ - confirmedUnknownLines = confirmedUnknownLines.filter { it in unknownLines } + if (unknownLines.isEmpty()) return - unknownLines = unknownLines.filter { it !in confirmedUnknownLines } - - unconfirmedUnknownLines = unknownLines - - unknownLines = unknownLines.filter { it !in unknownLinesSet } + for (line in unknownLines) { + val unknownLine = allUnknownLines.firstOrNull { it.line == line } + if (unknownLine == null) { + if (LorenzUtils.inSkyBlock) { + ChatUtils.debug("Unknown Scoreboard line: '$line'") + } + allUnknownLines = allUnknownLines.editCopy { + add(UnknownLine(line)) + } + } else { + unknownLine.lastFound = SimpleTimeMark.now() + val firstFoundSince = unknownLine.firstFound.passedSince() + val lastWarnedSince = unknownLine.lastWarned.passedSince() + if (firstFoundSince > 3.seconds && lastWarnedSince > 30.minutes) { + unknownLine.lastWarned = SimpleTimeMark.now() + warn(line, "same line active for 3 seconds") + continue + } + } + } - unknownLines.forEach { - if (LorenzUtils.inSkyBlock) { - ChatUtils.debug("Unknown Scoreboard line: '$it'") + if (lastRecentAlarmWarning.passedSince() > 30.minutes) { + val recentAlarms = allUnknownLines.filter { it.firstFound.passedSince() < 6.seconds } + if (recentAlarms.size >= 5) { + warn(recentAlarms.first().line, "5 different lines in 5 seconds") } - unknownLinesSet.add(it) } } + + private fun warn(line: String, reason: String) { + ErrorManager.logErrorWithData( + // line inclucded in chat message to not cache a previous message + CustomScoreboardUtils.UndetectedScoreboardLines(line), + "CustomScoreboard detected a unknown line: '$line'", + "Unknown Line" to line, + "reason" to reason, + "Island" to LorenzUtils.skyBlockIsland, + "Area" to HypixelData.skyBlockArea, + "Full Scoreboard" to ScoreboardData.sidebarLinesFormatted, + noStackTrace = true, + betaOnly = true, + ) + + } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/FocusMode.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/FocusMode.kt new file mode 100644 index 000000000000..c02f2993399a --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/FocusMode.kt @@ -0,0 +1,35 @@ +package at.hannibal2.skyhanni.features.inventory + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.events.LorenzTickEvent +import at.hannibal2.skyhanni.events.LorenzToolTipEvent +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.utils.InventoryUtils +import at.hannibal2.skyhanni.utils.KeyboardManager.isKeyClicked +import at.hannibal2.skyhanni.utils.LorenzUtils +import net.minecraftforge.fml.common.eventhandler.EventPriority +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +@SkyHanniModule +object FocusMode { + + private val config get() = SkyHanniMod.feature.inventory.focusMode + + private var toggle = true + + @SubscribeEvent(priority = EventPriority.LOWEST) + fun onLorenzToolTip(event: LorenzToolTipEvent) { + if (!isEnabled() || !toggle) return + if(event.toolTip.isEmpty()) return + event.toolTip = mutableListOf(event.toolTip.first()) + } + + @SubscribeEvent + fun onLorenzTick(event: LorenzTickEvent) { + if (!isEnabled()) return + if (!config.toggleKey.isKeyClicked()) return + toggle = !toggle + } + + fun isEnabled() = LorenzUtils.inSkyBlock && InventoryUtils.inContainer() && config.enabled +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateAmount.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateAmount.kt index 7f0694e2a779..1f1f6d0c0969 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateAmount.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateAmount.kt @@ -31,6 +31,7 @@ enum class ChocolateAmount(val chocolate: () -> Long) { companion object { fun chocolateSinceUpdate(): Long { + if (ChocolateFactoryAPI.isMax()) return 0L val lastUpdate = profileStorage?.lastDataSave ?: return 0 val currentTime = SimpleTimeMark.now() val secondsSinceUpdate = (currentTime - lastUpdate).inWholeSeconds diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryAPI.kt index 112e8a7a7383..195ea51d32f9 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryAPI.kt @@ -239,4 +239,8 @@ object ChocolateFactoryAPI { it.rabbit.removeColor() == rabbitName.removeColor() } } + + fun isMax(): Boolean = profileStorage?.let { + it.maxChocolate == it.currentChocolate + } ?: false } diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryDataLoader.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryDataLoader.kt index eebbb19e93a7..64a99a8c911f 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryDataLoader.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryDataLoader.kt @@ -51,6 +51,14 @@ object ChocolateFactoryDataLoader { "chocolate.thisprestige", "§7Chocolate this Prestige: §6(?[\\d,]+)", ) + + /** + * REGEX-TEST: §7Max Chocolate: §660B + */ + private val maxChocolatePattern by ChocolateFactoryAPI.patternGroup.pattern( + "chocolate.max", + "§7Max Chocolate: §6(?.*)", + ) private val chocolateForPrestigePattern by ChocolateFactoryAPI.patternGroup.pattern( "chocolate.forprestige", "§7§cRequires (?\\w+) Chocolate this.*", @@ -230,6 +238,9 @@ object ChocolateFactoryDataLoader { chocolateThisPrestigePattern.matchMatcher(line) { profileStorage.chocolateThisPrestige = group("amount").formatLong() } + maxChocolatePattern.matchMatcher(line) { + profileStorage.maxChocolate = group("max").formatLong() + } chocolateForPrestigePattern.matchMatcher(line) { ChocolateFactoryAPI.chocolateForPrestige = group("amount").formatLong() prestigeCost = ChocolateFactoryAPI.chocolateForPrestige diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryStats.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryStats.kt index 8d08e485e16f..36c79728cd39 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryStats.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryStats.kt @@ -76,7 +76,10 @@ object ChocolateFactoryStats { val map = buildMap { put(ChocolateFactoryStat.HEADER, "§6§lChocolate Factory ${ChocolateFactoryAPI.currentPrestige.toRoman()}") - put(ChocolateFactoryStat.CURRENT, "§eCurrent Chocolate: §6${ChocolateAmount.CURRENT.formatted}") + val maxSuffix = if (ChocolateFactoryAPI.isMax()) { + " §cMax!" + } else "" + put(ChocolateFactoryStat.CURRENT, "§eCurrent Chocolate: §6${ChocolateAmount.CURRENT.formatted}$maxSuffix") put(ChocolateFactoryStat.THIS_PRESTIGE, "§eThis Prestige: §6${ChocolateAmount.PRESTIGE.formatted}") put(ChocolateFactoryStat.ALL_TIME, "§eAll-time: §6${ChocolateAmount.ALL_TIME.formatted}") diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/GuardianReminder.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/GuardianReminder.kt index 216cbf7c6ba8..32157adf7ebe 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/GuardianReminder.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/GuardianReminder.kt @@ -8,6 +8,7 @@ import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.ChatUtils import at.hannibal2.skyhanni.utils.ColorUtils.withAlpha +import at.hannibal2.skyhanni.utils.DelayedRun import at.hannibal2.skyhanni.utils.HypixelCommands import at.hannibal2.skyhanni.utils.InventoryUtils import at.hannibal2.skyhanni.utils.LorenzUtils @@ -37,12 +38,17 @@ object GuardianReminder { fun onInventory(event: InventoryFullyOpenedEvent) { if (!isEnabled()) return if (event.inventoryName != "Experimentation Table") return - if (ExperimentationTableAPI.petNamePattern.matches(PetAPI.currentPet)) return - lastInventoryOpen = SimpleTimeMark.now() + DelayedRun.runDelayed(200.milliseconds, ::warn) + } + + private fun warn() { + if (ExperimentationTableAPI.petNamePattern.matches(PetAPI.currentPet)) return + if (lastWarn.passedSince() < 5.seconds) return lastWarn = SimpleTimeMark.now() + ChatUtils.clickToActionOrDisable( "Use a §9§lGuardian Pet §efor more Exp in the Experimentation Table.", config::guardianReminder, diff --git a/src/main/java/at/hannibal2/skyhanni/features/mining/KingTalismanHelper.kt b/src/main/java/at/hannibal2/skyhanni/features/mining/KingTalismanHelper.kt index 057d2f476948..b9f205984f38 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/mining/KingTalismanHelper.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/mining/KingTalismanHelper.kt @@ -2,9 +2,11 @@ package at.hannibal2.skyhanni.features.mining import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.data.IslandType +import at.hannibal2.skyhanni.data.MiningAPI import at.hannibal2.skyhanni.data.ProfileStorageData import at.hannibal2.skyhanni.events.GuiRenderEvent import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent +import at.hannibal2.skyhanni.events.LorenzChatEvent import at.hannibal2.skyhanni.events.SecondPassedEvent import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.ChatUtils @@ -16,6 +18,7 @@ import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland import at.hannibal2.skyhanni.utils.LorenzVec import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher +import at.hannibal2.skyhanni.utils.RegexUtils.matches import at.hannibal2.skyhanni.utils.RenderUtils.renderStrings import at.hannibal2.skyhanni.utils.SkyBlockTime import at.hannibal2.skyhanni.utils.TimeUtils.format @@ -31,11 +34,27 @@ object KingTalismanHelper { private val config get() = SkyHanniMod.feature.mining.kingTalisman private val storage get() = ProfileStorageData.profileSpecific?.mining - private val kingPattern by RepoPattern.pattern( - "mining.kingtalisman.king", + private val patternGroup = RepoPattern.group("mining.kingtalisman") + + /** + * REGEX-TEST: §6§lKing Brammor + * REGEX-TEST: §6§lKing Emkam + * REGEX-TEST: §6§lKing Kevin + * REGEX-TEST: §6§lKing Redros + */ + private val kingPattern by patternGroup.pattern( + "king", "§6§lKing (?.*)" ) + /** + * REGEX-TEST: §7You have received a §r§fKing Talisman§r§7! + */ + private val talismanPattern by patternGroup.pattern( + "talisman", + "§7You have received a §r§fKing Talisman§r§7!" + ) + private var currentOffset: Int? = null private var skyblockYear = 0 @@ -66,7 +85,8 @@ object KingTalismanHelper { private var farDisplay = "" private var display = emptyList() - private fun isNearby() = IslandType.DWARVEN_MINES.isInIsland() && LorenzUtils.skyBlockArea == "Royal Palace" && + private fun isNearby() = IslandType.DWARVEN_MINES.isInIsland() && + LorenzUtils.skyBlockArea == "Royal Palace" && kingLocation.distanceToPlayer() < 10 @SubscribeEvent @@ -86,7 +106,7 @@ object KingTalismanHelper { return } - update(kingsTalkedTo) + update() display = if (nearby) allKingsDisplay else Collections.singletonList(farDisplay) } @@ -103,7 +123,8 @@ object KingTalismanHelper { skyblockYear = SkyBlockTime.now().year } - fun isEnabled() = config.enabled && LorenzUtils.inSkyBlock && + fun isEnabled() = config.enabled && + LorenzUtils.inSkyBlock && (IslandType.DWARVEN_MINES.isInIsland() || config.outsideMines) @SubscribeEvent @@ -118,12 +139,13 @@ object KingTalismanHelper { val kingsTalkedTo = storage.kingsTalkedTo if (currentKing !in kingsTalkedTo) { kingsTalkedTo.add(currentKing) - update(kingsTalkedTo) + update() display = allKingsDisplay } } - private fun update(kingsTalkedTo: MutableList) { + private fun update() { + val kingsTalkedTo = storage?.kingsTalkedTo ?: return if (kingsTalkedTo.size == kingCircles.size) { allKingsDisplay = Collections.singletonList("§eAll Kings found.") farDisplay = "" @@ -198,4 +220,15 @@ object KingTalismanHelper { config.position.renderStrings(display, posLabel = "King Talisman Helper") } + + @SubscribeEvent + fun onChat(event: LorenzChatEvent) { + if (!isEnabled()) return + if (!MiningAPI.inDwarvenMines) return + + if (talismanPattern.matches(event.message)) { + storage?.kingsTalkedTo = kingCircles.toMutableList() + update() + } + } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/mining/eventtracker/MiningEventTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/mining/eventtracker/MiningEventTracker.kt index a076ba68f0c3..d5ee14ec92e3 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/mining/eventtracker/MiningEventTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/mining/eventtracker/MiningEventTracker.kt @@ -200,7 +200,8 @@ object MiningEventTracker { canRequestAt = SimpleTimeMark.now() + 20.minutes if (LorenzUtils.debug) { ErrorManager.logErrorWithData( - e, "Receiving mining event data was unsuccessful", + e, + "Failed to load Mining Event data!", ) } return@launch @@ -208,11 +209,17 @@ object MiningEventTracker { val miningEventData = ConfigManager.gson.fromJson(data, MiningEventDataReceive::class.java) if (!miningEventData.success) { - ErrorManager.logErrorWithData( - Exception("PostFailure"), "Receiving mining event data was unsuccessful", - "cause" to miningEventData.cause, - "recievedData" to data - ) + if (data.toString() == "{}") { + ChatUtils.chat("§cFailed loading Mining Event data!\n" + + "Please wait until the server problem fixes itself! There is nothing else to do at the moment.") + } else { + ErrorManager.logErrorWithData( + Exception("miningEventData.success = false"), + "Failed to load Mining Event data!", + "cause" to miningEventData.cause, + "recievedData" to data + ) + } return@launch } apiErrorCount = 0 diff --git a/src/main/java/at/hannibal2/skyhanni/features/mining/powdertracker/PowderChestReward.kt b/src/main/java/at/hannibal2/skyhanni/features/mining/powdertracker/PowderChestReward.kt index b2b449563a5f..ac824abd38f8 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/mining/powdertracker/PowderChestReward.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/mining/powdertracker/PowderChestReward.kt @@ -4,10 +4,6 @@ import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern enum class PowderChestReward(val displayName: String, pattern: String) { - MITHRIL_POWDER( - "§aMithril Powder", - " {4}§r§2Mithril Powder(?: §r§8x(?.*))?", - ), GEMSTONE_POWDER( "§dGemstone Powder", " {4}§r§dGemstone Powder(?: §r§8x(?.*))?", @@ -119,6 +115,8 @@ enum class PowderChestReward(val displayName: String, pattern: String) { "§9FTX 3070", " {4}§r§9FTX 3070(?: §r§8x(?.*))?", ), + + // TODO: Fix typo ELECTRON_TRANSIMTTER( "§9Electron Transmitter", " {4}§r§9Electron Transmitter(?: §r§8x(?.*))?", diff --git a/src/main/java/at/hannibal2/skyhanni/features/mining/powdertracker/PowderTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/mining/powdertracker/PowderTracker.kt index da9dbb2fbdab..4c27f195a895 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/mining/powdertracker/PowderTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/mining/powdertracker/PowderTracker.kt @@ -140,8 +140,7 @@ object PowderTracker { } } - private val tracker = - SkyHanniTracker("Powder Tracker", { Data() }, { it.powderTracker }) { formatDisplay(drawDisplay(it)) } + private val tracker = SkyHanniTracker("Powder Tracker", { Data() }, { it.powderTracker }) { formatDisplay(drawDisplay(it)) } class Data : TrackerData() { @@ -199,7 +198,7 @@ object PowderTracker { } for (reward in PowderChestReward.entries) { - if (reward == PowderChestReward.MITHRIL_POWDER || reward == PowderChestReward.GEMSTONE_POWDER) continue + if (reward == PowderChestReward.GEMSTONE_POWDER) continue reward.chatPattern.matchMatcher(msg) { tracker.modify { val count = it.rewards[reward] ?: 0 @@ -217,7 +216,6 @@ object PowderTracker { tracker.modify { val reward = when (event.powder) { HotmAPI.PowderType.GEMSTONE -> PowderChestReward.GEMSTONE_POWDER - HotmAPI.PowderType.MITHRIL -> PowderChestReward.MITHRIL_POWDER else -> return@modify } it.rewards.addOrPut(reward, event.amount) @@ -275,6 +273,17 @@ object PowderTracker { } newList } + + event.transform(61, "mining.powderTracker.textFormat") { element -> + val newList = JsonArray() + for (entry in element.asJsonArray) { + if (entry is JsonNull) continue + if (entry.asString.let { it != "MITHRIL_POWDER" }) { + newList.add(entry) + } + } + newList + } } @SubscribeEvent @@ -297,7 +306,6 @@ object PowderTracker { private fun drawDisplay(data: Data): List = buildList { calculate(data, gemstoneInfo, PowderChestReward.GEMSTONE_POWDER) - calculate(data, mithrilInfo, PowderChestReward.MITHRIL_POWDER) calculate(data, diamondEssenceInfo, PowderChestReward.DIAMOND_ESSENCE) calculate(data, goldEssenceInfo, PowderChestReward.GOLD_ESSENCE) calculateChest(data) @@ -307,13 +315,11 @@ object PowderTracker { addSearchString("§d${data.totalChestPicked.addSeparators()} Total Chests Picked §7($chestPerHour/h)") addSearchString("§bDouble Powder: ${if (doublePowder) "§aActive! §7($powderTimer)" else "§cInactive!"}") - val entries = PowderChestReward.entries val rewards = data.rewards - addPerHour(rewards, entries[0], mithrilInfo) - addPerHour(rewards, entries[1], gemstoneInfo) + addPerHour(rewards, PowderChestReward.GEMSTONE_POWDER, gemstoneInfo) addSearchString("") - addPerHour(rewards, entries[46], diamondEssenceInfo) - addPerHour(rewards, entries[47], goldEssenceInfo) + addPerHour(rewards, PowderChestReward.DIAMOND_ESSENCE, diamondEssenceInfo) + addPerHour(rewards, PowderChestReward.GOLD_ESSENCE, goldEssenceInfo) addSearchString("") val hardStonePerHour = format(hardStoneInfo.perHour) addSearchString("§b${data.totalHardStoneCompacted.addSeparators()} §fHard Stone §bCompacted §7($hardStonePerHour/h)", "Hard Stone") @@ -338,7 +344,14 @@ object PowderTracker { } var totalParts = 0L - for (reward in entries.subList(26, 32)) { // robots part + for (reward in listOf( + PowderChestReward.FTX_3070, + PowderChestReward.ELECTRON_TRANSIMTTER, + PowderChestReward.ROBOTRON_REFLECTOR, + PowderChestReward.SUPERLITE_MOTOR, + PowderChestReward.CONTROL_SWITCH, + PowderChestReward.SYNTHETIC_HEART, + )) { val count = rewards.getOrDefault(reward, 0) totalParts += count val name = reward.displayName @@ -353,7 +366,17 @@ object PowderTracker { val blueEgg = rewards.getOrDefault(PowderChestReward.BLUE_GOBLIN_EGG, 0) addSearchString("§3$blueEgg§7-§c$redEgg§7-§e$yellowEgg§f-§a$greenEgg§f-§9$goblinEgg §fGoblin Egg") - for (reward in entries.subList(37, 46)) { + for (reward in listOf( + PowderChestReward.WISHING_COMPASS, + PowderChestReward.SLUDGE_JUICE, + PowderChestReward.ASCENSION_ROPE, + PowderChestReward.TREASURITE, + PowderChestReward.JUNGLE_HEART, + PowderChestReward.PICKONIMBUS_2000, + PowderChestReward.YOGGIE, + PowderChestReward.PREHISTORIC_EGG, + PowderChestReward.OIL_BARREL, + )) { val count = rewards.getOrDefault(reward, 0).addSeparators() val name = reward.displayName addSearchString("§b$count $name", name) diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/IslandAreas.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/IslandAreas.kt index 439e434c146e..dfa60478a6c2 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/IslandAreas.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/IslandAreas.kt @@ -276,5 +276,5 @@ object IslandAreas { hasMoved = true } - fun isEnabled() = LorenzUtils.inSkyBlock && config.let { it.pathfinder.enabled || it.enterTitle || it.inWorld } + fun isEnabled() = LorenzUtils.inSkyBlock } 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 61f9a344923f..83f45e535d5c 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/NonGodPotEffectDisplay.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/NonGodPotEffectDisplay.kt @@ -76,6 +76,10 @@ object NonGodPotEffectDisplay { CURSE_OF_GREED("§4Curse of Greed I"), COLD_RESISTANCE_4("§bCold Resistance IV"), + + POWDER_PUMPKIN("§fPowder Pumpkin I"), + FILET_O_FORTUNE("§fFilet O' Fortune I"), + CHILLED_PRISTINE_POTATO("§fChilled Pristine Potato I"), } private val effectsCountPattern by RepoPattern.pattern( diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/TpsCounter.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/TpsCounter.kt index 01d84daa3fdc..1515ee3dcbd1 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/TpsCounter.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/TpsCounter.kt @@ -74,7 +74,7 @@ object TpsCounter { fun tpsCommand() { if (display.isEmpty()) { - ChatUtils.chat("§cNo tps data available, make sure you have the setting on.") + ChatUtils.userError("No tps data available, make sure you have the setting on.") return } ChatUtils.chat(display) @@ -101,7 +101,8 @@ object TpsCounter { config.tpsDisplayPosition.renderString(display, posLabel = "Tps Display") } - private fun isEnabled() = LorenzUtils.onHypixel && config.tpsDisplay && + private fun isEnabled() = LorenzUtils.onHypixel && + config.tpsDisplay && (LorenzUtils.inSkyBlock || OutsideSbFeature.TPS_DISPLAY.isSelected()) @SubscribeEvent diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValueCalculator.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValueCalculator.kt index 62abb1c8c52a..5797c50cd7b7 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValueCalculator.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValueCalculator.kt @@ -29,6 +29,7 @@ import at.hannibal2.skyhanni.utils.NumberUtil.shortFormat import at.hannibal2.skyhanni.utils.PrimitiveIngredient import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getAbilityScrolls +import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getAppliedPocketSackInASack import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getArmorDye import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getAttributes import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getBookwormBookCount @@ -98,6 +99,7 @@ object EstimatedItemValueCalculator { ::addManaDisintegrators, ::addPolarvoidBook, ::addBookwormBook, + ::addPocketSackInASack, // cosmetic ::addHelmetSkin, @@ -393,11 +395,20 @@ object EstimatedItemValueCalculator { return price } + private fun addPocketSackInASack(stack: ItemStack, list: MutableList): Double { + val count = stack.getAppliedPocketSackInASack() ?: return 0.0 + + val pocketSackInASack = "POCKET_SACK_IN_A_SACK".asInternalName() + val price = pocketSackInASack.getPrice() * count + list.add("§7Pocket Sack-in-a-Sack: §e$count§7/§e3 §7(§6" + price.shortFormat() + "§7)") + return price + } + private fun addBookwormBook(stack: ItemStack, list: MutableList): Double { val count = stack.getBookwormBookCount() ?: return 0.0 - val tfHardcodedItemAgain = "BOOKWORM_BOOK".asInternalName() - val price = tfHardcodedItemAgain.getPrice() * count + val bookwormBook = "BOOKWORM_BOOK".asInternalName() + val price = bookwormBook.getPrice() * count list.add("§7Bookworm's Favorite Book: §e$count§7/§e5 §7(§6" + price.shortFormat() + "§7)") return price } diff --git a/src/main/java/at/hannibal2/skyhanni/features/nether/PabloHelper.kt b/src/main/java/at/hannibal2/skyhanni/features/nether/PabloHelper.kt index 04f5e6113576..eb4962549f70 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/nether/PabloHelper.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/nether/PabloHelper.kt @@ -4,6 +4,7 @@ import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.api.GetFromSackAPI import at.hannibal2.skyhanni.events.LorenzChatEvent import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.utils.DelayedRun import at.hannibal2.skyhanni.utils.InventoryUtils import at.hannibal2.skyhanni.utils.ItemUtils.name import at.hannibal2.skyhanni.utils.LorenzUtils @@ -51,10 +52,12 @@ object PabloHelper { if (InventoryUtils.countItemsInLowerInventory { it.name.contains(itemName) } > 0) return - GetFromSackAPI.getFromChatMessageSackItems( - itemName.asInternalName().makePrimitiveStack(), - "Click here to grab an $itemName from sacks!", - ) + DelayedRun.runNextTick { + GetFromSackAPI.getFromChatMessageSackItems( + itemName.asInternalName().makePrimitiveStack(), + "Click here to grab an $itemName from sacks!", + ) + } lastSentMessage = SimpleTimeMark.now() } diff --git a/src/main/java/at/hannibal2/skyhanni/features/rift/area/westvillage/RiftGunthersRace.kt b/src/main/java/at/hannibal2/skyhanni/features/rift/area/westvillage/RiftGunthersRace.kt index cf729453fcb6..5a3638101a71 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/rift/area/westvillage/RiftGunthersRace.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/rift/area/westvillage/RiftGunthersRace.kt @@ -1,6 +1,7 @@ package at.hannibal2.skyhanni.features.rift.area.westvillage import at.hannibal2.skyhanni.data.jsonobjects.repo.ParkourJson +import at.hannibal2.skyhanni.events.CheckRenderEntityEvent import at.hannibal2.skyhanni.events.ConfigLoadEvent import at.hannibal2.skyhanni.events.IslandChangeEvent import at.hannibal2.skyhanni.events.LorenzChatEvent @@ -11,9 +12,11 @@ import at.hannibal2.skyhanni.features.rift.RiftAPI import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.ColorUtils.toChromaColor import at.hannibal2.skyhanni.utils.ConditionalUtils +import at.hannibal2.skyhanni.utils.EntityUtils.isNPC import at.hannibal2.skyhanni.utils.ParkourHelper import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern +import net.minecraft.client.entity.EntityOtherPlayerMP import net.minecraftforge.fml.common.eventhandler.SubscribeEvent @SkyHanniModule @@ -105,6 +108,18 @@ object RiftGunthersRace { } } + @SubscribeEvent + fun onCheckRender(event: CheckRenderEntityEvent<*>) { + if (!isEnabled()) return + if (!config.hidePlayers) return + if (!RiftAPI.inRiftRace) return + + val entity = event.entity + if (entity is EntityOtherPlayerMP && !entity.isNPC()) { + event.cancel() + } + } + @SubscribeEvent fun onRenderWorld(event: LorenzRenderWorldEvent) { if (!isEnabled() || !RiftAPI.inRiftRace) return diff --git a/src/main/java/at/hannibal2/skyhanni/mixins/hooks/FontRendererHook.kt b/src/main/java/at/hannibal2/skyhanni/mixins/hooks/FontRendererHook.kt index db9c1c07e1c2..b52407b65233 100644 --- a/src/main/java/at/hannibal2/skyhanni/mixins/hooks/FontRendererHook.kt +++ b/src/main/java/at/hannibal2/skyhanni/mixins/hooks/FontRendererHook.kt @@ -28,7 +28,7 @@ object FontRendererHook { private var currentDrawState: ChromaFontRenderer? = null private var previewChroma = false - private var chromaPreviewText: String + var chromaPreviewText: String var cameFromChat = false diff --git a/src/main/java/at/hannibal2/skyhanni/mixins/hooks/MixinPatcherFontRendererHookHook.kt b/src/main/java/at/hannibal2/skyhanni/mixins/hooks/MixinPatcherFontRendererHookHook.kt index 25d415889b0d..25697e0ee633 100644 --- a/src/main/java/at/hannibal2/skyhanni/mixins/hooks/MixinPatcherFontRendererHookHook.kt +++ b/src/main/java/at/hannibal2/skyhanni/mixins/hooks/MixinPatcherFontRendererHookHook.kt @@ -11,9 +11,25 @@ class MixinPatcherFontRendererHookHook { fun overridePatcherFontRenderer(string: String, shadow: Boolean, cir: CallbackInfoReturnable) { if (!LorenzUtils.onHypixel) return - if (ChromaManager.config.enabled.get()) { - cir.cancel() + if (ChromaManager.config.allChroma) { cir.returnValue = false + return + } + + if (string == FontRendererHook.chromaPreviewText) { + cir.returnValue = false + return + } + + if (string.contains("§#§")) { + cir.returnValue = false + return + } + if (ChromaManager.config.enabled.get()) { + if (string.contains("§z") || string.contains("§Z")) { + cir.returnValue = false + return + } } } } diff --git a/src/main/java/at/hannibal2/skyhanni/mixins/transformers/gui/MixinGuiScreen.java b/src/main/java/at/hannibal2/skyhanni/mixins/transformers/gui/MixinGuiScreen.java index b3338acf5032..3f0371f07f7f 100644 --- a/src/main/java/at/hannibal2/skyhanni/mixins/transformers/gui/MixinGuiScreen.java +++ b/src/main/java/at/hannibal2/skyhanni/mixins/transformers/gui/MixinGuiScreen.java @@ -8,6 +8,7 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; @@ -33,4 +34,9 @@ public void getTooltip(ItemStack stack, int x, int y, CallbackInfo ci, List) { SkyHanniMod.coroutineScope.launch { - ChatUtils.chat(runCommand(args), false) + ChatUtils.chat(runCommand(args)) } lastCommand = args } @@ -223,7 +223,9 @@ object SkyHanniConfigSearchResetCommand { val className = obj.getClassName() if (!classFilter(className)) continue val objectName = obj.getObjectName() - if (obj !is Runnable && objectName.startsWith(className) && (objectName.startsWith("at.hannibal2.skyhanni.config.features.") || + if (obj !is Runnable && + objectName.startsWith(className) && + (objectName.startsWith("at.hannibal2.skyhanni.config.features.") || objectName.startsWith("at.hannibal2.skyhanni.config.storage.Storage")) ) { "" @@ -275,7 +277,14 @@ object SkyHanniConfigSearchResetCommand { val newObj = field.makeAccessible().get(obj) map[fieldName] = newObj @Suppress("ComplexCondition") - if (newObj != null && newObj !is Boolean && newObj !is String && newObj !is Long && newObj !is Int && newObj !is Double && newObj !is Position && !newObj.javaClass.isEnum) { + if (newObj != null && + newObj !is Boolean && + newObj !is String && + newObj !is Long && + newObj !is Int && + newObj !is Double && + newObj !is Position && + !newObj.javaClass.isEnum) { map.putAll(loadAllFields(fieldName, newObj, depth + 1)) } } diff --git a/src/main/java/at/hannibal2/skyhanni/test/command/ErrorManager.kt b/src/main/java/at/hannibal2/skyhanni/test/command/ErrorManager.kt index df3d85267677..25b485c5a0f1 100644 --- a/src/main/java/at/hannibal2/skyhanni/test/command/ErrorManager.kt +++ b/src/main/java/at/hannibal2/skyhanni/test/command/ErrorManager.kt @@ -1,6 +1,10 @@ package at.hannibal2.skyhanni.test.command import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.data.jsonobjects.repo.RepoErrorData +import at.hannibal2.skyhanni.data.jsonobjects.repo.RepoErrorJson +import at.hannibal2.skyhanni.events.RepositoryReloadEvent +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.ChatUtils import at.hannibal2.skyhanni.utils.KeyboardManager import at.hannibal2.skyhanni.utils.LorenzUtils @@ -9,14 +13,17 @@ import at.hannibal2.skyhanni.utils.StringUtils import at.hannibal2.skyhanni.utils.StringUtils.removeColor import at.hannibal2.skyhanni.utils.TimeLimitedSet import net.minecraft.client.Minecraft +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import kotlin.time.Duration.Companion.minutes +@SkyHanniModule object ErrorManager { // random id -> error message private val errorMessages = mutableMapOf() private val fullErrorMessages = mutableMapOf() private var cache = TimeLimitedSet>(10.minutes) + private var repoErrors: List = emptyList() private val breakAfter = listOf( "at at.hannibal2.skyhanni.config.commands.Commands\$createCommand", @@ -149,19 +156,62 @@ object ErrorManager { val extraDataString = buildExtraDataString(extraData) val rawMessage = message.removeColor() - errorMessages[randomId] = - "```\nSkyHanni ${SkyHanniMod.version}: $rawMessage\n \n$stackTrace\n$extraDataString```" + errorMessages[randomId] = "```\nSkyHanni ${SkyHanniMod.version}: $rawMessage\n \n$stackTrace\n$extraDataString```" fullErrorMessages[randomId] = "```\nSkyHanni ${SkyHanniMod.version}: $rawMessage\n(full stack trace)\n \n$fullStackTrace\n$extraDataString```" + val finalMessage = buildFinalMessage(message) ?: return ChatUtils.clickableChat( - "§c[SkyHanni-${SkyHanniMod.version}]: $message§c. Click here to copy the error into the clipboard.", + "§c[SkyHanni-${SkyHanniMod.version}]: $finalMessage Click here to copy the error into the clipboard.", onClick = { copyError(randomId) }, "§eClick to copy!", prefix = false, ) } + private fun buildFinalMessage(message: String): String? { + var finalMessage = message + val rawMessage = message.removeColor() + + var hideError = false + for (repoError in repoErrors) { + for (string in repoError.messageStartsWith) { + if (rawMessage.startsWith(string)) { + hideError = true + } + } + for (string in repoError.messageExact) { + if (rawMessage == string) { + hideError = true + } + } + if (hideError) { + repoError.replaceMessage?.let { + finalMessage = it + hideError = false + } + repoError.customMessage?.let { + ChatUtils.userError(it) + return null + } + break + } + } + + if (finalMessage.last() !in ".?!") { + finalMessage += "§c." + } + return if (hideError) null else finalMessage + } + + @SubscribeEvent + fun onRepoReload(event: RepositoryReloadEvent) { + val data = event.getConstant("ChangedChatErrors") + val version = SkyHanniMod.version + + repoErrors = data.changedErrorMessages.filter { version in it.affectedVersions } + } + private fun buildExtraDataString(extraData: Array>): String { val extraDataString = if (extraData.isNotEmpty()) { val builder = StringBuilder() diff --git a/src/main/java/at/hannibal2/skyhanni/tweaker/DownloadSourceChecker.java b/src/main/java/at/hannibal2/skyhanni/tweaker/DownloadSourceChecker.java index 2c417909e6a2..7947b6ebc9e1 100644 --- a/src/main/java/at/hannibal2/skyhanni/tweaker/DownloadSourceChecker.java +++ b/src/main/java/at/hannibal2/skyhanni/tweaker/DownloadSourceChecker.java @@ -1,5 +1,7 @@ package at.hannibal2.skyhanni.tweaker; +import at.hannibal2.skyhanni.utils.OSUtils; + import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.JPanel; @@ -32,7 +34,7 @@ public class DownloadSourceChecker { }; public static void init() { - if (!TweakerUtils.isOnWindows()) return; + if (!OSUtils.INSTANCE.isWindows()) return; URI host = getDangerousHost(); if (host != null) { openMenu(host); diff --git a/src/main/java/at/hannibal2/skyhanni/tweaker/TweakerUtils.java b/src/main/java/at/hannibal2/skyhanni/tweaker/TweakerUtils.java index b9070e0c16bb..ffd415c10133 100644 --- a/src/main/java/at/hannibal2/skyhanni/tweaker/TweakerUtils.java +++ b/src/main/java/at/hannibal2/skyhanni/tweaker/TweakerUtils.java @@ -11,10 +11,6 @@ public class TweakerUtils { - public static boolean isOnWindows() { - return System.getProperty("os.name").toLowerCase().contains("win"); - } - public static void openUrl(String url) { try { Desktop.getDesktop().browse(new URI(url)); diff --git a/src/main/java/at/hannibal2/skyhanni/utils/ChatUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/ChatUtils.kt index 18519a364b1e..a8941c95aed8 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/ChatUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/ChatUtils.kt @@ -12,6 +12,7 @@ import at.hannibal2.skyhanni.utils.chat.Text.command import at.hannibal2.skyhanni.utils.chat.Text.hover import at.hannibal2.skyhanni.utils.chat.Text.onClick import at.hannibal2.skyhanni.utils.chat.Text.prefix +import at.hannibal2.skyhanni.utils.chat.Text.send import at.hannibal2.skyhanni.utils.chat.Text.url import at.hannibal2.skyhanni.utils.compat.getFormattedTextCompat import net.minecraft.client.Minecraft @@ -110,6 +111,7 @@ object ChatUtils { * @param expireAt When the click action should expire, default never * @param prefix Whether to prefix the message with the chat prefix, default true * @param prefixColor Color that the prefix should be, default yellow (§e) + * @param replaceSameMessage Replace the old message with this new message if they are identical * * @see CHAT_PREFIX */ @@ -121,14 +123,30 @@ object ChatUtils { prefix: Boolean = true, prefixColor: String = "§e", oneTimeClick: Boolean = false, + replaceSameMessage: Boolean = false, ) { val msgPrefix = if (prefix) prefixColor + CHAT_PREFIX else "" - chat(Text.text(msgPrefix + message) { + + val rawText = msgPrefix + message + val text = Text.text(rawText) { this.onClick(expireAt, oneTimeClick, onClick) this.hover = hover.asComponent() - }) + } + if (replaceSameMessage) { + text.send(getUniqueMessageIdForString(rawText)) + } else { + chat(text) + } } + val uniqueMessageIdStorage = mutableMapOf() + + fun getUniqueMessageIdForString(string: String) = uniqueMessageIdStorage.getOrPut(string) { getUniqueMessageId() } + + var lastUniqueMessageId = 123242 + + fun getUniqueMessageId() = lastUniqueMessageId++ + /** * Sends a message to the user that they can click and run a command * @param message The message to be sent @@ -260,7 +278,7 @@ object ChatUtils { fun clickToActionOrDisable(message: String, option: KMutableProperty0<*>, actionName: String, action: () -> Unit) { - ChatUtils.clickableChat( + clickableChat( "$message\n§e[CLICK to $actionName or disable this feature]", onClick = { if (KeyboardManager.isShiftKeyDown() || KeyboardManager.isModifierKeyDown()) { @@ -271,6 +289,7 @@ object ChatUtils { }, hover = "§eClick to $actionName!\n" + "§eShift-Click or Control-Click to disable this feature!", + replaceSameMessage = true, ) } } diff --git a/src/main/java/at/hannibal2/skyhanni/utils/ComputerEnvDebug.kt b/src/main/java/at/hannibal2/skyhanni/utils/ComputerEnvDebug.kt new file mode 100644 index 000000000000..ca4eeeb71118 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/utils/ComputerEnvDebug.kt @@ -0,0 +1,107 @@ +package at.hannibal2.skyhanni.utils + +import at.hannibal2.skyhanni.events.DebugDataCollectEvent +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.test.command.ErrorManager +import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher +import at.hannibal2.skyhanni.utils.system.PlatformUtils +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +@SkyHanniModule +object ComputerEnvDebug { + + @SubscribeEvent + fun onDebugDataCollect(event: DebugDataCollectEvent) { + os(event) + java(event) + launcher(event) + } + + private fun launcher(event: DebugDataCollectEvent) { + event.title("Computer Minecraft Launcher") + + val firstStack = getFirstStack() ?: run { + event.addData("Could not load data!") + return + } + + val (launcher, relevant) = findLauncher(firstStack) + + launcher?.let { + if (relevant) { + event.addData(it) + } else { + event.addIrrelevant(it) + } + return + } + + event.addData { + add("Unknown launcher!") + add("firstStack: '$firstStack'") + } + } + + // TODO put into repo + private fun findLauncher(firstStack: String): Pair { + if (firstStack.contains("net.fabricmc.devlaunchinjector.Main.main")) { + return Pair("Dev Env", false) + } + if (firstStack.contains("net.minecraft.launchwrapper.Launch.main")) { + return Pair("Vanilla Launcher", false) + } + if (firstStack.contains("org.prismlauncher.EntryPoint.main")) { + return Pair("Prism", false) + } + if (firstStack.contains("net.digitalingot.vendor.")) { + return Pair("Feather Client", true) + } + return Pair(null, true) + } + + private fun getFirstStack(): String? { + val firstStack = try { + Thread.currentThread().stackTrace.last().toString() + } catch (e: Exception) { + ErrorManager.logErrorWithData(e, "Failed loading current thread stack trace info") + null + } + return firstStack + } + + private fun java(event: DebugDataCollectEvent) { + event.title("Computer Java Version") + val version = System.getProperty("java.version") + val pattern = "1\\.8\\.0_(?.*)".toPattern() + pattern.matchMatcher(version) { + group("update").toIntOrNull()?.let { + val devEnvironment = PlatformUtils.isDevEnvironment + if (it < 300 && !devEnvironment) { + event.addData("Old update: $it") + } else { + if (devEnvironment) { + event.addIrrelevant("Update version: $it (dev env)") + } else { + event.addIrrelevant("New update: $it") + } + } + return + } + } + event.addData("Unknwon java version: '$version'") + } + + private fun os(event: DebugDataCollectEvent) { + event.title("Computer Operating System") + val osType = OSUtils.getOperatingSystem() + val exactName = OSUtils.getOperatingSystemRaw() + if (osType != OSUtils.OperatingSystem.UNKNOWN) { + event.addIrrelevant { + add("OS type: $osType") + add("Exact name: $exactName") + } + } else { + event.addData("Unknwon OS: '$exactName'") + } + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/utils/ComputerTimeOffset.kt b/src/main/java/at/hannibal2/skyhanni/utils/ComputerTimeOffset.kt index 83ea15ecc437..c0f65645a1f3 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/ComputerTimeOffset.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/ComputerTimeOffset.kt @@ -112,11 +112,16 @@ object ComputerTimeOffset { @SubscribeEvent fun onDebugCollect(event: DebugDataCollectEvent) { event.title("Time Offset") - val relevant = offsetMillis?.absoluteValue?.let { it < 100.milliseconds } ?: true + val offset = offsetMillis ?: run { + event.addIrrelevant("not calculated yet") + return + } + + val relevant = offset.absoluteValue > 500.milliseconds if (relevant) { - event.addData(offsetMillis.toString()) + event.addData(offset.toString()) } else { - event.addIrrelevant(offsetMillis.toString()) + event.addIrrelevant(offset.toString()) } } } diff --git a/src/main/java/at/hannibal2/skyhanni/utils/InventoryUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/InventoryUtils.kt index 7ff17f96506b..0f025e50ba50 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/InventoryUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/InventoryUtils.kt @@ -41,6 +41,8 @@ object InventoryUtils { fun inInventory() = Minecraft.getMinecraft().currentScreen is GuiChest + fun inContainer() = Minecraft.getMinecraft().currentScreen is GuiContainer + fun ContainerChest.getInventoryName() = this.lowerChestInventory.displayName.unformattedText.trim() fun getWindowId(): Int? = (Minecraft.getMinecraft().currentScreen as? GuiChest)?.inventorySlots?.windowId diff --git a/src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt b/src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt index a7abe6527bdc..75c6173ba57e 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt @@ -12,6 +12,8 @@ import at.hannibal2.skyhanni.test.command.ErrorManager import at.hannibal2.skyhanni.utils.CollectionUtils.addOrPut import at.hannibal2.skyhanni.utils.ItemBlink.checkBlinkItem import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName +import at.hannibal2.skyhanni.utils.ItemUtils.getInternalNameOrNull +import at.hannibal2.skyhanni.utils.ItemUtils.name import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName import at.hannibal2.skyhanni.utils.NumberUtil.isInt import at.hannibal2.skyhanni.utils.PrimitiveIngredient.Companion.toPrimitiveItemStacks @@ -259,7 +261,16 @@ object NEUItems { AdjustStandardItemLighting.adjust() // Compensate for z scaling - Minecraft.getMinecraft().renderItem.renderItemIntoGUI(item, 0, 0) + try { + Minecraft.getMinecraft().renderItem.renderItemIntoGUI(item, 0, 0) + } catch (e: Exception) { + println(" ") + println("item: $item") + println("name: ${item.name}") + println("getInternalNameOrNull: ${item.getInternalNameOrNull()}") + println(" ") + e.printStackTrace() + } RenderHelper.disableStandardItemLighting() GlStateManager.popMatrix() diff --git a/src/main/java/at/hannibal2/skyhanni/utils/OSUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/OSUtils.kt index 5b42c5dc640f..ecd0f0650adf 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/OSUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/OSUtils.kt @@ -7,15 +7,37 @@ import java.net.URI object OSUtils { + enum class OperatingSystem { + LINUX, + SOLARIS, + WINDOWS, + MACOS, + UNKNOWN, + } + + fun getOperatingSystemRaw(): String = System.getProperty("os.name") + + fun getOperatingSystem(): OperatingSystem { + val osName = getOperatingSystemRaw().lowercase() + return when { + osName.contains("win") -> OperatingSystem.WINDOWS + osName.contains("mac") -> OperatingSystem.MACOS + osName.contains("solaris") || osName.contains("sunos") -> OperatingSystem.SOLARIS + osName.contains("linux") || osName.contains("unix") -> OperatingSystem.LINUX + + else -> OperatingSystem.UNKNOWN + } + } + val isWindows: Boolean val isMac: Boolean val isLinux: Boolean init { - val os = System.getProperty("os.name") - isWindows = os.contains("win", ignoreCase = true) - isMac = os.contains("mac", ignoreCase = true) - isLinux = os.contains("linux", ignoreCase = true) + val os = getOperatingSystem() + isWindows = os == OperatingSystem.WINDOWS + isMac = os == OperatingSystem.MACOS + isLinux = os == OperatingSystem.LINUX } @JvmStatic diff --git a/src/main/java/at/hannibal2/skyhanni/utils/RenderUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/RenderUtils.kt index cf2339bf3c42..309f17f686e2 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/RenderUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/RenderUtils.kt @@ -591,10 +591,11 @@ object RenderUtils { } fun Position.renderRenderable( - renderable: Renderable, + renderable: Renderable?, posLabel: String, addToGuiManager: Boolean = true, ) { + if (renderable == null) return GlStateManager.pushMatrix() val (x, y) = transform() Renderable.withMousePosition(x, y) { diff --git a/src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt index f118d5d665c0..c6de8c13fced 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt @@ -569,4 +569,9 @@ object StringUtils { false } } + + fun optionalAn(string: String): String { + if (string.isEmpty()) return "" + return if (string[0] in "aeiou") "an" else "a" + } }