diff --git a/.github/workflows/illegal-imports.txt b/.github/workflows/illegal-imports.txt
index f53a5da78e25..83354f622960 100644
--- a/.github/workflows/illegal-imports.txt
+++ b/.github/workflows/illegal-imports.txt
@@ -5,7 +5,8 @@
at/hannibal2/skyhanni/ scala.
at/hannibal2/skyhanni/ jline.
-at/hannibal2/skyhanni/ io.github.moulberry.notenoughupdates.util.Constants
at/hannibal2/skyhanni/ io.github.moulberry.notenoughupdates.events.SlotClickEvent
at/hannibal2/skyhanni/ io.github.moulberry.notenoughupdates.events.ReplaceItemEvent
+at/hannibal2/skyhanni/ io.github.moulberry.notenoughupdates.util.Constants
+at/hannibal2/skyhanni/ io.github.moulberry.notenoughupdates.util.Utils
at/hannibal2/skyhanni/ java.util.function.Supplier
diff --git a/.gitignore b/.gitignore
index d77f4bd8b6f0..7f4081e02e52 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,7 @@
!.idea/icon.svg
!.idea/dictionaries/default_user.xml
!.idea/scopes/Mixins.xml
+!.idea/liveTemplates/SkyHanni.xml
.vscode/
run/
build/
diff --git a/.idea/dictionaries/default_user.xml b/.idea/dictionaries/default_user.xml
index cb91301718f0..a0017ca5e3e0 100644
--- a/.idea/dictionaries/default_user.xml
+++ b/.idea/dictionaries/default_user.xml
@@ -254,6 +254,7 @@
superpairs
tablist
terracottas
+ tessellator
thaumaturgist
thaumaturgy
townsquare
@@ -277,4 +278,4 @@
yolkar
-
+
\ No newline at end of file
diff --git a/.idea/liveTemplates/SkyHanni.xml b/.idea/liveTemplates/SkyHanni.xml
new file mode 100644
index 000000000000..08c6737b5ce2
--- /dev/null
+++ b/.idea/liveTemplates/SkyHanni.xml
@@ -0,0 +1,101 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/build.gradle.kts b/build.gradle.kts
index e8464ada27e8..add2df4e77e2 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -18,6 +18,7 @@ plugins {
kotlin("plugin.power-assert")
`maven-publish`
id("moe.nea.shot") version "1.0.0"
+ id("net.kyori.blossom")
}
val target = ProjectTarget.values().find { it.projectPath == project.path }!!
@@ -159,9 +160,9 @@ dependencies {
exclude(module = "unspecified")
isTransitive = false
}
- // June 3, 2024, 9:30 PM AEST
- // https://github.com/NotEnoughUpdates/NotEnoughUpdates/tree/2.3.0
- devenvMod("com.github.NotEnoughUpdates:NotEnoughUpdates:2.3.0:all") {
+ // August 27, 2024, 4:30 PM AEST
+ // https://github.com/NotEnoughUpdates/NotEnoughUpdates/tree/2.3.3
+ devenvMod("com.github.NotEnoughUpdates:NotEnoughUpdates:2.3.3:all") {
exclude(module = "unspecified")
isTransitive = false
}
@@ -312,12 +313,18 @@ if (!MultiVersionStage.activeState.shouldCompile(target)) {
onlyIf { false }
}
}
+
preprocess {
vars.put("MC", target.minecraftVersion.versionNumber)
vars.put("FORGE", if (target.forgeDep != null) 1 else 0)
vars.put("JAVA", target.minecraftVersion.javaVersion)
patternAnnotation.set("at.hannibal2.skyhanni.utils.compat.Pattern")
}
+
+blossom {
+ replaceToken("@MOD_VERSION@", version)
+}
+
val sourcesJar by tasks.creating(Jar::class) {
destinationDirectory.set(layout.buildDirectory.dir("badjars"))
archiveClassifier.set("src")
diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
index f42ddfffc477..33d0b77c7433 100644
--- a/docs/CHANGELOG.md
+++ b/docs/CHANGELOG.md
@@ -16,6 +16,7 @@
+ Added a "Get from Sack" button in the forge recipe menu to retrieve ingredients. - minhperry (https://github.com/hannibal002/SkyHanni/pull/2106)
+ Added Tracker for Glacite Corpses. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2306)
+ Tracks overall loot and loot per type.
++ Hides tooltips of items inside the Fossil Excavator in Glacite Tunnels. - Cuz_Im_Clicks (https://github.com/hannibal002/SkyHanni/pull/2539)
#### Rift Features
@@ -46,6 +47,12 @@
+ Use /shhoppitystats for live stats.
+ Added optional warning when Hoppity calls you with a rabbit to sell. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2272)
+ Added hotkey for picking up Abiphone calls from Hoppity. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2272)
++ Added a draggable list for Hoppity's Collection menu rabbit highlighting. - the1divider (https://github.com/hannibal002/SkyHanni/pull/2438)
+ + Factory/Shop milestones = Yellow/Gold.
+ + Stray rabbits = Dark Aqua.
+ + 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)
#### The Carnival Features
@@ -80,6 +87,12 @@
+ Added Accessory magical power display as stack size. - minhperry (https://github.com/hannibal002/SkyHanni/pull/2243)
+ Only works inside the Accessory Bag and Auction House.
+ Added `/gfs` to fix a broken Piggy Bank. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2150)
++ Added Superpair Display. - ILike2WatchMemes (https://github.com/hannibal002/SkyHanni/pull/2171)
+ + Displays found and matched pairs, power-ups, and missing pairs/normals.
++ Added Experiments Dry-Streak Display. - ILike2WatchMemes (https://github.com/hannibal002/SkyHanni/pull/2171)
+ + Shows attempts and XP since the last ULTRA-RARE.
++ Added Experiments Profit Tracker. - ILike2WatchMemes (https://github.com/hannibal002/SkyHanni/pull/2171)
+ + Tracks profits in Coins and Enchanting XP.
#### Chat Features
@@ -110,6 +123,10 @@
+ Added Broodmother spawn alert, countdown and stage change messages. - MTOnline (https://github.com/hannibal002/SkyHanni/pull/2325)
+ Countdown will not show until a spawning stage change is observed, and may be off by a few seconds.
+ Added Broodmother support to the Damage Indicator. - MTOnline (https://github.com/hannibal002/SkyHanni/pull/2325)
++ Added Carry Tracker. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2185)
+ + Use `/shcarry` to add carries to a customer, and set a price for a slayer boss.
+ + Automatically counts slayer bosses you carry.
+ + Automatically tracks coins received from customers via `/trade`.
#### Fishing Features
@@ -133,6 +150,13 @@
+ Added option to hide pet nametag text. - Empa + j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/1880)
+ Added Transfer Cooldown Prevention. - Cuz_Im_Clicks (https://github.com/hannibal002/SkyHanni/pull/1751)
+ Wait for the transfer cooldown to complete before sending commands like warp/is/hub.
++ Added highlighting for the active Beacon Effect. - Cuz_Im_Clicks (https://github.com/hannibal002/SkyHanni/pull/2546)
++ Added navigation command. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2575)
+ + Use `/shnavigate ` to find interesting locations on your current SkyBlock island by searching for them.
+ + Displays a pathfinder to the location.
+ + Works with NPCs, points of interest, areas, slayer spots, emissaries, crimson mini-bosses, spots to mine ores, break crops, and kill mobs.
+ + Does not yet work with Spider's Den and Dungeon Hub (still needs to be mapped out).
++ Added a message to warp to Winter Island spawn when a Reindrake spawns. - Cuz_Im_Clicks (https://github.com/hannibal002/SkyHanni/pull/2569)
### Improvements
@@ -144,6 +168,9 @@
+ Some icons in the Mining Event Display now use the texture of the item they represent. - Thunderblade73 (https://github.com/hannibal002/SkyHanni/pull/2425)
+ E.g., Raffle Event -> Raffle Ticket.
+ Changed how Powder Tracker works to account for powder buffs. - Jordyrat + Empa (https://github.com/hannibal002/SkyHanni/pull/2394)
++ 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)
#### Diana Improvements
@@ -151,6 +178,7 @@
+ 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)
#### Scoreboard Improvements
@@ -190,6 +218,9 @@
+ Added config option to disable rarity in Compact Hoppity messages. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2383)
+ Chocolate Factory: Shows "time to next milestone" instead of "max milestone" when you are at Prestige 6. - minhperry (https://github.com/hannibal002/SkyHanni/pull/2503)
++ 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)
#### Combat Improvements
@@ -209,21 +240,30 @@
+ Changed suggested cactus speed to 464 again. - DarkDash (https://github.com/hannibal002/SkyHanni/pull/2424)
+ Since the cactus knife now allows 500 max speed.
+ 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)
#### 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)
#### Dungeon Improvements
+ Added dungeon stars and crimson stars to estimated item value. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2492)
+#### The Carnival Improvements
+
++ Updated the Zombie Shootout Diamond color to be a deeper blue. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2511)
+
#### Misc Improvements
+ Updated Last Server to also alert for servers you have just left. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2494)
+ Added search functionality to some SkyHanni GUIs. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2477)
+ Search works in all SkyHanni Trackers and the Sack Display.
+ In your inventory, hover over the GUI with your mouse, then start typing to search.
++ Improved the performance of pathfinding logic in Area Navigation. - nea (https://github.com/hannibal002/SkyHanni/pull/2537)
++ Added a toggle to force the `en_US` locale for number formatting. - martimavocado (https://github.com/hannibal002/SkyHanni/pull/2563)
++ Queued GfS will now always fall back to a default amount if one is not specified. - Luna (https://github.com/hannibal002/SkyHanni/pull/2584)
### Fixes
@@ -253,6 +293,9 @@
+ Fixed the Auction House Price Comparison appearing in your own inventory as well. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2483)
+ Fixed "click to show tunnel map" from the Glacite Mines commission menu appearing in the inventory. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2485)
+ Fixed Mouse Keys not working as Wardrobe Slot Hotkeys. - j10a1n15, ThatGravyBoat (https://github.com/hannibal002/SkyHanni/pull/2506)
++ Fixed Estimated Item Value incorrectly showing all Kuudra armor as starred. - Luna (https://github.com/hannibal002/SkyHanni/pull/2550)
++ Fixed Experiments Profit Tracker & Superpair Data. - ILike2WatchMemes (https://github.com/hannibal002/SkyHanni/pull/2560)
++ Fixed price per unit for Stonk of Stonks auction not working for the bracket you are in. - Thunderblade73 (https://github.com/hannibal002/SkyHanni/pull/2572)
#### Mining Fixes
@@ -262,6 +305,21 @@
+ Fixed Powder for 10 Levels overflowing over the max level. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2422)
+ Fixed Glacite Tunnel Maps repeatedly showing the last commission goal even when there is no new commission. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2432)
+ Fixed Mineshaft Pity Counter not working with some ore types. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2436)
++ Fixed Tungsten Ore and Hardstone detection after the mining update. - Empa (https://github.com/hannibal002/SkyHanni/pull/2437)
++ Fixed item category errors after the new mining update. - Thunderblade73 (https://github.com/hannibal002/SkyHanni/pull/2529)
++ Fixed blocks mined by Efficient Miner not being detected. - Empa (https://github.com/hannibal002/SkyHanni/pull/2526)
++ Fixed Corpse Tracker resetting items between restarts. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2528)
++ Fixed the Corpse Tracker not displaying while in the Mineshaft. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2516)
++ Fixed Hardstone and Tungsten not being properly detected in Mineshafts. - Empa (https://github.com/hannibal002/SkyHanni/pull/2536)
++ Fixed Heart of the Mountain showing outdated perks and powder information. - Tryp0xd (https://github.com/hannibal002/SkyHanni/pull/2543)
++ Fixed Sky Mall perks not being read correctly after the Hypixel update. - Luna (https://github.com/hannibal002/SkyHanni/pull/2551)
++ Fixed Mining Commission Blocks Color not working properly with Connected Textures. - Empa (https://github.com/hannibal002/SkyHanni/pull/2553)
++ Fixed Gemstone Gauntlet item category. - Luna (https://github.com/hannibal002/SkyHanni/pull/2534)
++ Fixed Glacite powder being tracked as Glacite in Corpse Tracker. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2557)
++ Fixed "Mining Commissions Block Color" disabling OptiFine connected textures. - nopo (https://github.com/hannibal002/SkyHanni/pull/2559)
++ Fixed some blocks in the Crystal Hollows being detected as Mithril instead of Hard Stone. - Luna (https://github.com/hannibal002/SkyHanni/pull/2580)
++ Fixed "Mining Commissions Block Color" causing OptiFine connected textures not to connect properly. - nopo (https://github.com/hannibal002/SkyHanni/pull/2577)
++ Fixed the Mineshaft Pity Counter not working in the Great Glacite Lake. - martimavocado (https://github.com/hannibal002/SkyHanni/pull/2565)
#### Scoreboard Fixes
@@ -280,6 +338,10 @@
+ Fixed Custom Scoreboard errors while doing Carnival activities. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2455)
+ Fixed Custom Scoreboard error while in a Dungeon Queue. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2441)
+ Fixed Custom Scoreboard Error during the Barry Protestors Quest. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2480)
++ Fixed a Custom Scoreboard error during the Magma Boss Fight and Goblin Raid. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2531)
++ Fixed a Custom Scoreboard error while in the Dojo. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2519)
++ 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)
#### Hoppity Fixes
@@ -288,6 +350,7 @@
+ Fixed "Highlight Requirement Rabbits" requiring "Hoppity Collection Stats" to function. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2398)
+ Fixed minor formatting issues with Hoppity Event Summary. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2416)
+ Fixed Hoppity Event stats resetting. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2489)
++ Fixed an issue where Fish the Rabbit and El Dorado did not have compacted chat messages. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2488)
#### Chat Fixes
@@ -312,6 +375,22 @@
#### Garden Fixes
+ 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)
+
+#### Combat Fixes
+
++ Updated Ghost Counter bestiary tiers to reflect Hypixel reducing the max kills needed from 250K to 100K. - Luna (https://github.com/hannibal002/SkyHanni/pull/2533)
++ Fixed a case where the Broodmother countdown could be wildly inaccurate. - MTOnline (https://github.com/hannibal002/SkyHanni/pull/2513)
+
+#### The Carnival Fixes
+
++ Fixed two "Catch a Fish" carnival goals not being properly detected from chat. - Luna (https://github.com/hannibal002/SkyHanni/pull/2517)
++ Fixed the bounding box of baby zombies in Zombie Shootout. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2512)
+
+#### Fishing Fixes
+
++ Fixed error messages while using the Chum Bucket Hider feature. - nea89 (https://github.com/hannibal002/SkyHanni/pull/2587)
#### Misc Fixes
@@ -327,6 +406,12 @@
+ Fixed performance issues with a high number of dungeon runs in one session. - Thunderblade73 (https://github.com/hannibal002/SkyHanni/pull/2504)
+ Fixed `/shedittracker duplex` not working. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2501)
+ Fixed "Last Server Joined" spamming the chat. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2495)
++ Fixed lag spikes in Path Finder. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2525)
++ Fixed old mayor perks not being marked as inactive when the mayor changes. - Luna (https://github.com/hannibal002/SkyHanni/pull/2524)
++ Fixed direct GitHub downloads triggering the source checker. - ThatGravyBoat (https://github.com/hannibal002/SkyHanni/pull/2548)
++ Fixed reforge display not working with new mining stats. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2555)
++ Fixed Totem of Corruption expiry warning not working in some cases. - Luna (https://github.com/hannibal002/SkyHanni/pull/2554)
++ Fixed a few typos in the config. - rdbt (https://github.com/hannibal002/SkyHanni/pull/2585)
### Technical Details
@@ -366,6 +451,44 @@
+ Updated HandleEvent onlyOnIslands to handle multiple islands. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2502)
+ Added an abstract "bucketed" tracker that can store where items came from. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2306)
+ Takes an enum in instantiation and has built-in logic for swapping display types.
++ Graph Editor improvements. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2515)
+ + Code cleanup in Graph Editor, moving node lists into their own class.
+ + Fixed searchable tag list.
+ + Added more graph node tags; only display certain tags on specific islands in the editor.
+ + Added an option to limit the maximum render range of nodes and edges in the Graph Editor for better performance.
++ Hoppity's Collection highlighting now updates on event triggers instead of every frame. - the1divider (https://github.com/hannibal002/SkyHanni/pull/2438)
++ Added `select near look` keybind in Graph Editor. - nea (https://github.com/hannibal002/SkyHanni/pull/2537)
++ Added checks to avoid creating bugs with the area structure in Graph Editor. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2537)
++ Added options to the graph node list to hide nodes with certain tags. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2537)
++ Removed the use of `LorenzChatEvent()` for 'manually' adding data to Hoppity Chat Compact. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2488)
+ + Now uses `EggFoundEvent()`.
++ The Renderable Wrapped String now has an option to align text inside the wrapped string box. - Thunderblade73 (https://github.com/hannibal002/SkyHanni/pull/2372)
++ Improved handling of unknown stats for ReforgeAPI. - Thunderblade73 (https://github.com/hannibal002/SkyHanni/pull/2562)
++ Added `AreaChangeEvent`. - Empa (https://github.com/hannibal002/SkyHanni/pull/2535)
++ Updated `HandleEvent` to allow `onlyOnIsland` usage for a single island without brackets. - Empa (https://github.com/hannibal002/SkyHanni/pull/2535)
++ Created a Text method to display a paginated list. - CalMWolfs (https://github.com/hannibal002/SkyHanni/pull/2583)
+ + Moved existing paged lists in `/shcommands` and `/shremind` to use this.
++ Node Tags filter list in Graph Editor now sorts by nodes per tag. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2575)
++ Additional code cleanup around ingredients. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2576)
++ Removed duplicate rounding functions. - CalMWolfs (https://github.com/hannibal002/SkyHanni/pull/1931)
++ Added HTTP Request Patching. - CalMWolfs (https://github.com/hannibal002/SkyHanni/pull/2578)
++ Removed references to NEU code, especially code from the Utils class in NEU. - CalMWolfs (https://github.com/hannibal002/SkyHanni/pull/2419)
++ Banned importing `io.github.moulberry.notenoughupdates.util.Utils`. - CalMWolfs (https://github.com/hannibal002/SkyHanni/pull/2419)
++ Added common live templates. - Thunderblade73 (https://github.com/hannibal002/SkyHanni/pull/2463)
+ + These can be automatically imported via the plugin "Live Templates Sharing".
++ Created and used primitive recipe and ingredient classes. - CalMWolfs (https://github.com/hannibal002/SkyHanni/pull/2460)
+ + These are added as a layer between SkyHanni and NEU so that we are not reliant on NEU functions.
++ Added Blossom Gradle plugin for token replacement in code. - ThatGravyBoat (https://github.com/hannibal002/SkyHanni/pull/2558)
+ + `@MOD_VERSION@` is now a token that will be replaced.
+
+### Removed Features
+
++ Removed Wild Strawberry Dye notification. - MTOnline (https://github.com/hannibal002/SkyHanni/pull/2520)
+ + Artist's Abode now sends a lobby-wide message for dye drops, making the notification obsolete.
++ Removed `Only Requirement Not Met` and `Highlight Requirement Rabbits` config options. - the1divider (https://github.com/hannibal002/SkyHanni/pull/2438)
+ + 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.
## Version 0.26
diff --git a/docs/FEATURES.md b/docs/FEATURES.md
index 9c67c0de1246..0783d9e09f82 100644
--- a/docs/FEATURES.md
+++ b/docs/FEATURES.md
@@ -864,6 +864,7 @@ Use `/sh` or `/skyhanni` to open the SkyHanni config in game.
+ Option to show the walls also when inside the Nucleus.
+ Fossil Excavator Solver. - CalMWolfs (https://github.com/hannibal002/SkyHanni/pull/1427)
+ Shows where to next click for optimal chance of solving the fossil. If there is a fossil this will find it within 18 moves.
++ Hides tooltips of items inside the Fossil Excavator in Glacite Tunnels. - Cuz_Im_Clicks (https://github.com/hannibal002/SkyHanni/pull/2539)
+ Excavation Profit Tracker. - hannibal2 + Empa (https://github.com/hannibal002/SkyHanni/pull/1432)
+ Count all drops you gain while excavating in the Fossil Research Center.
+ Track Glacite Powder gained as well (no profit, but progress).
@@ -989,6 +990,12 @@ Use `/sh` or `/skyhanni` to open the SkyHanni config in game.
+ Use /shhoppitystats for live stats.
+ Added optional warning when Hoppity calls you with a rabbit to sell. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2272)
+ Added hotkey for picking up Abiphone calls from Hoppity. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2272)
++ Added a draggable list for Hoppity's Collection menu rabbit highlighting. - the1divider (https://github.com/hannibal002/SkyHanni/pull/2438)
+ + Factory/Shop milestones = Yellow/Gold.
+ + Stray rabbits = Dark Aqua.
+ + 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)
### The Carnival
@@ -1150,6 +1157,7 @@ Use `/sh` or `/skyhanni` to open the SkyHanni config in game.
+ Customizable GUI
+ Option to hide the chat messages
+ While on the Winter Island, show a timer until Jerry's Workshop closes. - hannibal2
++ Added a message to warp to Winter Island spawn when a Reindrake spawns. - Cuz_Im_Clicks (https://github.com/hannibal002/SkyHanni/pull/2569)
+ **Custom Text Box** - CalMWolfs
+ Write fancy text into a gui element to show on your screen at all time
+ Supports color codes
@@ -1322,9 +1330,16 @@ Use `/sh` or `/skyhanni` to open the SkyHanni config in game.
+ Added to the Item Number list.
+ Added Compact Experimentation Table chat rewards. - ILike2WatchMemes (https://github.com/hannibal002/SkyHanni/pull/2209)
+ Uses a compact chat message of rewards gained from Add-ons/Experiments.
++ Added Superpair Display. - ILike2WatchMemes (https://github.com/hannibal002/SkyHanni/pull/2171)
+ + Displays found and matched pairs, power-ups, and missing pairs/normals.
++ Added Experiments Dry-Streak Display. - ILike2WatchMemes (https://github.com/hannibal002/SkyHanni/pull/2171)
+ + Shows attempts and XP since the last ULTRA-RARE.
++ Added Experiments Profit Tracker. - ILike2WatchMemes (https://github.com/hannibal002/SkyHanni/pull/2171)
+ + Tracks profits in Coins and Enchanting XP.
+ In-Water Display. - Stella (https://github.com/hannibal002/SkyHanni/pull/1892)
+ Useful when using a Prismarine Blade in Stranded Mode.
+ Added Beacon Power Display. - Empa (https://github.com/hannibal002/SkyHanni/pull/1901)
++ Added highlighting for the active Beacon Effect. - Cuz_Im_Clicks (https://github.com/hannibal002/SkyHanni/pull/2546)
+ Added Hide Useless Armor Stands. - Empa (https://github.com/hannibal002/SkyHanni/pull/1962)
+ Hides armor stands that briefly appear on Hypixel.
+ **Custom Wardrobe**, a new look for the wardrobe. - j10an15, Empa (https://github.com/hannibal002/SkyHanni/pull/2039)
@@ -1361,12 +1376,21 @@ Use `/sh` or `/skyhanni` to open the SkyHanni config in game.
+ Get a title warning when entering an area.
+ See area names in the world.
+ Does not yet work with Spider's Den and Dungeon Hub. Only partial support for Farming Islands and the Rift.
++ Added navigation command. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2575)
+ + Use `/shnavigate ` to find interesting locations on your current SkyBlock island by searching for them.
+ + Displays a pathfinder to the location.
+ + Works with NPCs, points of interest, areas, slayer spots, emissaries, crimson mini-bosses, spots to mine ores, break crops, and kill mobs.
+ + Does not yet work with Spider's Den and Dungeon Hub (still needs to be mapped out).
+ Added `/gfs` to fix a broken Piggy Bank. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2150)
+ Added Broodmother spawn alert, countdown and stage change messages. - MTOnline (https://github.com/hannibal002/SkyHanni/pull/2325)
+ Countdown will not show until a spawning stage change is observed, and may be off by a few seconds.
+ Added option to hide pet nametag text. - Empa + j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/1880)
+ Added Transfer Cooldown Prevention. - Cuz_Im_Clicks (https://github.com/hannibal002/SkyHanni/pull/1751)
+ Wait for the transfer cooldown to complete before sending commands like warp/is/hub.
++ Added Carry Tracker. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2185)
+ + Use `/shcarry` to add carries to a customer, and set a price for a slayer boss.
+ + Automatically counts slayer bosses you carry.
+ + Automatically tracks coins received from customers via `/trade`.
diff --git a/root.gradle.kts b/root.gradle.kts
index ebdebe043c9b..5baae39e2ba7 100644
--- a/root.gradle.kts
+++ b/root.gradle.kts
@@ -3,6 +3,7 @@ import com.replaymod.gradle.preprocess.Node
plugins {
id("dev.deftu.gradle.preprocess") version "0.6.1"
+ id("net.kyori.blossom") version "1.3.2" apply false
id("gg.essential.loom") version "1.6.+" apply false
kotlin("jvm") version "2.0.0" apply false
kotlin("plugin.power-assert") version "2.0.0" apply false
@@ -12,7 +13,7 @@ plugins {
allprojects {
group = "at.hannibal2.skyhanni"
- version = "0.27.Beta.8"
+ version = "0.27.Beta.12"
}
preprocess {
diff --git a/settings.gradle.kts b/settings.gradle.kts
index aaf0f02cf6d6..adee2acba161 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -14,6 +14,7 @@ pluginManagement {
maven("https://repo.nea.moe/releases")
maven("https://repo.sk1er.club/repository/maven-releases/")
maven("https://maven.deftu.dev/releases")
+ maven("https://maven.teamresourceful.com/repository/maven-private/") // Blossom
maven("https://jitpack.io") {
content {
includeGroupByRegex("(com|io)\\.github\\..*")
diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt
index 09a293829e25..45d02f5445f6 100644
--- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt
+++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt
@@ -42,7 +42,7 @@ import org.apache.logging.log4j.Logger
clientSideOnly = true,
useMetadata = true,
guiFactory = "at.hannibal2.skyhanni.config.ConfigGuiForgeInterop",
- version = "0.27.Beta.8",
+ version = "@MOD_VERSION@",
)
class SkyHanniMod {
diff --git a/src/main/java/at/hannibal2/skyhanni/api/GetFromSackAPI.kt b/src/main/java/at/hannibal2/skyhanni/api/GetFromSackAPI.kt
index 7407dd66053a..89ccfd656f07 100644
--- a/src/main/java/at/hannibal2/skyhanni/api/GetFromSackAPI.kt
+++ b/src/main/java/at/hannibal2/skyhanni/api/GetFromSackAPI.kt
@@ -173,8 +173,6 @@ object GetFromSackAPI {
// The last parameter could be "2*3". This does not support ending with ")", but it is good enough
val argsNull = !args.last().last().isDigit()
val arguments = if (argsNull) {
- if (!config.defaultGFS) return CommandResult.WRONG_ARGUMENT to null
-
args + config.defaultAmountGFS.toString()
} else args
diff --git a/src/main/java/at/hannibal2/skyhanni/api/HotmAPI.kt b/src/main/java/at/hannibal2/skyhanni/api/HotmAPI.kt
index 97e041a89475..6217c56c21d0 100644
--- a/src/main/java/at/hannibal2/skyhanni/api/HotmAPI.kt
+++ b/src/main/java/at/hannibal2/skyhanni/api/HotmAPI.kt
@@ -91,10 +91,10 @@ object HotmAPI {
var mineshaftMayhem: MayhemPerk? = null
enum class SkymallPerk(chat: String, itemString: String) {
- MINING_SPEED("Gain §r§a\\+100 §r§6⸕ Mining Speed§r§f\\.", "Gain §a\\+100 §6⸕ Mining Speed§7\\."),
- MINING_FORTUNE("Gain §r§a\\+50 §r§6☘ Mining Fortune§r§f\\.", "Gain §a\\+50 §6☘ Mining Fortune§7\\."),
+ MINING_SPEED("Gain §r§6\\+100⸕ Mining Speed§r§f\\.", "Gain §6\\+100⸕ Mining Speed§7\\."),
+ MINING_FORTUNE("Gain §r§6\\+50☘ Mining Fortune§r§f\\.", "Gain §6\\+50☘ Mining Fortune§7\\."),
EXTRA_POWDER("Gain §r§a\\+15% §r§fmore Powder while mining\\.", "Gain §a\\+15% §7more Powder while mining\\."),
- ABILITY_COOLDOWN("Reduce Pickaxe Ability cooldown by §r§a20%§r§f\\.", "Reduce Pickaxe Ability cooldown by"),
+ ABILITY_COOLDOWN("§r§a-20%§r§f Pickaxe Ability cooldowns\\.", "§a-20%§7 Pickaxe Ability cooldowns\\."),
GOBLIN_CHANCE("§r§a10x §r§fchance to find Golden and Diamond Goblins\\.", "§a10x §7chance to find Golden and"),
TITANIUM("Gain §r§a5x §r§9Titanium §r§fdrops", "Gain §a5x §9Titanium §7drops\\.")
;
diff --git a/src/main/java/at/hannibal2/skyhanni/api/ReforgeAPI.kt b/src/main/java/at/hannibal2/skyhanni/api/ReforgeAPI.kt
index 987a864af77e..534d38d47c82 100644
--- a/src/main/java/at/hannibal2/skyhanni/api/ReforgeAPI.kt
+++ b/src/main/java/at/hannibal2/skyhanni/api/ReforgeAPI.kt
@@ -5,6 +5,7 @@ import at.hannibal2.skyhanni.data.model.SkyblockStat
import at.hannibal2.skyhanni.data.model.SkyblockStatList
import at.hannibal2.skyhanni.events.NeuRepositoryReloadEvent
import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule
+import at.hannibal2.skyhanni.test.command.ErrorManager
import at.hannibal2.skyhanni.utils.ItemCategory
import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName
import at.hannibal2.skyhanni.utils.ItemUtils.getItemCategoryOrNull
@@ -176,7 +177,18 @@ object ReforgeAPI {
while (reader.hasNext()) {
val name = reader.nextName()
val value = reader.nextDouble()
- list[SkyblockStat.valueOf(name.uppercase())] = value
+
+ val stat = SkyblockStat.getValueOrNull(name.uppercase()) ?: run {
+ ErrorManager.logErrorStateWithData(
+ "Unknown stat: '${name.uppercase()}'",
+ "Stat list could not parse stat",
+ "failed" to name.uppercase(),
+ betaOnly = true,
+ )
+ continue
+ }
+
+ list[stat] = value
}
reader.endObject()
return list
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 78769060accf..4b4c008523e2 100644
--- a/src/main/java/at/hannibal2/skyhanni/api/event/EventHandler.kt
+++ b/src/main/java/at/hannibal2/skyhanni/api/event/EventHandler.kt
@@ -130,6 +130,13 @@ class EventHandler private constructor(val name: String, priv
val invoker: Consumer,
val options: HandleEvent,
val generic: Class<*>?,
- val onlyOnIslandTypes: Set = options.onlyOnIslands.toSet(),
- )
+ ) {
+ val onlyOnIslandTypes: Set = getIslands(options)
+
+ companion object {
+ private fun getIslands(options: HandleEvent): Set =
+ if (options.onlyOnIslands.isEmpty()) setOf(options.onlyOnIsland)
+ else options.onlyOnIslands.toSet()
+ }
+ }
}
diff --git a/src/main/java/at/hannibal2/skyhanni/api/event/HandleEvent.kt b/src/main/java/at/hannibal2/skyhanni/api/event/HandleEvent.kt
index c07239dc2ae9..a88f7f33724c 100644
--- a/src/main/java/at/hannibal2/skyhanni/api/event/HandleEvent.kt
+++ b/src/main/java/at/hannibal2/skyhanni/api/event/HandleEvent.kt
@@ -12,8 +12,15 @@ annotation class HandleEvent(
/**
* If the event should only be received while on a specific skyblock island.
+ * To specify multiple islands, use [onlyOnIslands] instead.
*/
- vararg val onlyOnIslands: IslandType = [IslandType.ANY],
+ val onlyOnIsland: IslandType = IslandType.ANY,
+
+ /**
+ * If the event should only be received while being on specific skyblock islands.
+ * To specify only one island, use [onlyOnIsland] instead.
+ */
+ vararg val onlyOnIslands: IslandType = [],
/**
* The priority of when the event will be called, lower priority will be called first, see the companion object.
diff --git a/src/main/java/at/hannibal2/skyhanni/api/event/SkyHanniEvent.kt b/src/main/java/at/hannibal2/skyhanni/api/event/SkyHanniEvent.kt
index 4f3685c8bdff..c05b438cde20 100644
--- a/src/main/java/at/hannibal2/skyhanni/api/event/SkyHanniEvent.kt
+++ b/src/main/java/at/hannibal2/skyhanni/api/event/SkyHanniEvent.kt
@@ -1,5 +1,8 @@
package at.hannibal2.skyhanni.api.event
+/**
+ * Use @[HandleEvent]
+ */
abstract class SkyHanniEvent protected constructor() {
var isCancelled: Boolean = false
diff --git a/src/main/java/at/hannibal2/skyhanni/config/ConfigManager.kt b/src/main/java/at/hannibal2/skyhanni/config/ConfigManager.kt
index 4ac3f7925ce5..bf0f2ba0a4a4 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/ConfigManager.kt
+++ b/src/main/java/at/hannibal2/skyhanni/config/ConfigManager.kt
@@ -104,6 +104,7 @@ class ConfigManager {
// commands
"features.garden.GardenConfig.cropSpeedMeterPos",
"features.misc.MiscConfig.collectionCounterPos",
+ "features.misc.MiscConfig.carryPosition",
"features.misc.MiscConfig.lockedMouseDisplay",
// debug features
diff --git a/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt b/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt
index c881cc578ba4..b9f21ca2255c 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 = 57
+ const val CONFIG_VERSION = 59
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/commands/Commands.kt b/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt
index d0f58f0829d9..9f2e3cc3fd71 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt
+++ b/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt
@@ -57,12 +57,14 @@ import at.hannibal2.skyhanni.features.garden.pests.PestFinder
import at.hannibal2.skyhanni.features.garden.pests.PestProfitTracker
import at.hannibal2.skyhanni.features.garden.visitor.GardenVisitorDropStatistics
import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactoryStrayTracker
+import at.hannibal2.skyhanni.features.inventory.experimentationtable.ExperimentsProfitTracker
import at.hannibal2.skyhanni.features.mining.KingTalismanHelper
import at.hannibal2.skyhanni.features.mining.MineshaftPityDisplay
import at.hannibal2.skyhanni.features.mining.fossilexcavator.ExcavatorProfitTracker
import at.hannibal2.skyhanni.features.mining.glacitemineshaft.CorpseTracker
import at.hannibal2.skyhanni.features.mining.powdertracker.PowderTracker
import at.hannibal2.skyhanni.features.minion.MinionFeatures
+import at.hannibal2.skyhanni.features.misc.CarryTracker
import at.hannibal2.skyhanni.features.misc.CollectionTracker
import at.hannibal2.skyhanni.features.misc.LockMouseLook
import at.hannibal2.skyhanni.features.misc.MarkedPlayerManager
@@ -70,6 +72,7 @@ import at.hannibal2.skyhanni.features.misc.TpsCounter
import at.hannibal2.skyhanni.features.misc.discordrpc.DiscordRPCManager
import at.hannibal2.skyhanni.features.misc.limbo.LimboTimeTracker
import at.hannibal2.skyhanni.features.misc.massconfiguration.DefaultConfigFeatures
+import at.hannibal2.skyhanni.features.misc.pathfind.NavigationHelper
import at.hannibal2.skyhanni.features.misc.reminders.ReminderManager
import at.hannibal2.skyhanni.features.misc.update.UpdateManager
import at.hannibal2.skyhanni.features.misc.visualwords.VisualWordGui
@@ -77,7 +80,6 @@ import at.hannibal2.skyhanni.features.rift.area.westvillage.VerminTracker
import at.hannibal2.skyhanni.features.rift.everywhere.PunchcardHighlight
import at.hannibal2.skyhanni.features.slayer.SlayerProfitTracker
import at.hannibal2.skyhanni.test.DebugCommand
-import at.hannibal2.skyhanni.test.GraphEditor
import at.hannibal2.skyhanni.test.PacketTest
import at.hannibal2.skyhanni.test.SkyBlockIslandTest
import at.hannibal2.skyhanni.test.SkyHanniConfigSearchResetCommand
@@ -92,7 +94,8 @@ import at.hannibal2.skyhanni.test.command.CopyScoreboardCommand
import at.hannibal2.skyhanni.test.command.TestChatCommand
import at.hannibal2.skyhanni.test.command.TrackParticlesCommand
import at.hannibal2.skyhanni.test.command.TrackSoundsCommand
-import at.hannibal2.skyhanni.utils.APIUtil
+import at.hannibal2.skyhanni.test.graph.GraphEditor
+import at.hannibal2.skyhanni.utils.APIUtils
import at.hannibal2.skyhanni.utils.ChatUtils
import at.hannibal2.skyhanni.utils.ExtendedChatColor
import at.hannibal2.skyhanni.utils.ItemPriceUtils
@@ -180,9 +183,9 @@ object Commands {
)
registerCommand("shremind", "Set a reminder for yourself") { ReminderManager.command(it) }
registerCommand("shwords", "Opens the config list for modifying visual words") { openVisualWords() }
+ registerCommand("shnavigate", "Using path finder to go to locatons") { NavigationHelper.onCommand(it) }
}
-
private fun usersNormal() {
registerCommand(
"shmarkplayer",
@@ -191,8 +194,7 @@ object Commands {
registerCommand("shtrackcollection", "Tracks your collection gain over time") { CollectionTracker.command(it) }
registerCommand(
"shcroptime",
- "Calculates with your current crop per second speed " +
- "how long you need to farm a crop to collect this amount of items",
+ "Calculates with your current crop per second speed how long you need to farm a crop to collect this amount of items",
) { GardenCropTimeCommand.onCommand(it) }
registerCommand(
"shcropsin",
@@ -249,8 +251,7 @@ object Commands {
) { FarmingWeightDisplay.lookUpCommand(it) }
registerCommand(
"shcopytranslation",
- "Copy the English translation of a message in another language to the clipboard.\n" +
- "Uses a 2 letter language code that can be found at the end of a translation message.",
+ "Copy the English translation of a message in another language to the clipboard.\n" + "Uses a 2 letter language code that can be found at the end of a translation message.",
) { Translator.fromEnglish(it) }
registerCommand(
"shtranslate",
@@ -276,6 +277,10 @@ object Commands {
"shresetpestprofittracker",
"Resets the Pest Profit Tracker",
) { PestProfitTracker.resetCommand() }
+ registerCommand(
+ "shresetexperimentsprofittracker",
+ "Resets the Experiments Profit Tracker",
+ ) { ExperimentsProfitTracker.resetCommand() }
registerCommand(
"shresetmythologicalcreaturetracker",
"Resets the Mythological Creature Tracker",
@@ -362,8 +367,12 @@ object Commands {
) { ColorFormattingHelper.printColorCodeList() }
registerCommand(
"shtps",
- "Informs in chat about the server ticks per second (TPS)."
+ "Informs in chat about the server ticks per second (TPS).",
) { TpsCounter.tpsCommand() }
+ registerCommand(
+ "shcarry",
+ "Keep track of carries you do.",
+ ) { CarryTracker.onCommand(it) }
}
private fun usersBugFix() {
@@ -375,7 +384,7 @@ object Commands {
registerCommand(
"shtogglehypixelapierrors",
"Show/hide hypixel api error messages in chat",
- ) { APIUtil.toggleApiErrorMessages() }
+ ) { APIUtils.toggleApiErrorMessages() }
registerCommand(
"shclearcropspeed",
"Reset garden crop speed data and best crop time data",
@@ -485,7 +494,7 @@ object Commands {
) { SkyBlockIslandTest.onCommand(it) }
registerCommand(
"shdebugprice",
- "Debug different price sources for an item."
+ "Debug different price sources for an item.",
) { ItemPriceUtils.debugItemPrice(it) }
registerCommand(
"shdebugscoreboard",
@@ -580,9 +589,7 @@ object Commands {
) { TitleManager.command(it) }
registerCommand(
"shresetconfig",
- "Reloads the config manager and rendering processors of MoulConfig. " +
- "This §cWILL RESET §7your config, but also updating the java config files " +
- "(names, description, orderings and stuff).",
+ "Reloads the config manager and rendering processors of MoulConfig. " + "This §cWILL RESET §7your config, but also updating the java config files " + "(names, description, orderings and stuff).",
) { SkyHanniDebugsAndTests.resetConfigCommand() }
registerCommand(
"shreadcropmilestonefromclipboard",
@@ -659,8 +666,7 @@ object Commands {
else -> currentStream
}
- val switchingToBeta = updateStream == UpdateStream.BETA &&
- (currentStream != UpdateStream.BETA || !UpdateManager.isCurrentlyBeta())
+ val switchingToBeta = updateStream == UpdateStream.BETA && (currentStream != UpdateStream.BETA || !UpdateManager.isCurrentlyBeta())
if (switchingToBeta) {
ChatUtils.clickableChat(
"Are you sure you want to switch to beta? These versions may be less stable.",
diff --git a/src/main/java/at/hannibal2/skyhanni/config/core/config/gui/GuiPositionEditor.kt b/src/main/java/at/hannibal2/skyhanni/config/core/config/gui/GuiPositionEditor.kt
index 3e64d5f5abff..ba3a576754dc 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/core/config/gui/GuiPositionEditor.kt
+++ b/src/main/java/at/hannibal2/skyhanni/config/core/config/gui/GuiPositionEditor.kt
@@ -27,11 +27,10 @@ import at.hannibal2.skyhanni.data.OtherInventoryData
import at.hannibal2.skyhanni.mixins.transformers.gui.AccessorGuiContainer
import at.hannibal2.skyhanni.utils.GuiRenderUtils
import at.hannibal2.skyhanni.utils.KeyboardManager
-import at.hannibal2.skyhanni.utils.LorenzUtils.round
+import at.hannibal2.skyhanni.utils.NumberUtil.roundTo
import at.hannibal2.skyhanni.utils.compat.GuiScreenUtils
import at.hannibal2.skyhanni.utils.compat.SkyhanniBaseScreen
import net.minecraft.client.Minecraft
-import net.minecraft.client.gui.ScaledResolution
import net.minecraft.client.gui.inventory.GuiContainer
import net.minecraft.client.renderer.GlStateManager
import org.lwjgl.input.Keyboard
@@ -100,7 +99,7 @@ class GuiPositionEditor(
}
val pos = positions[displayPos]
- val location = "§7x: §e${pos.rawX}§7, y: §e${pos.rawY}§7, scale: §e${pos.scale.round(2)}"
+ val location = "§7x: §e${pos.rawX}§7, y: §e${pos.rawY}§7, scale: §e${pos.scale.roundTo(2)}"
GuiRenderUtils.drawStringCentered("§b" + pos.internalName, getScaledWidth() / 2, 18)
GuiRenderUtils.drawStringCentered(location, getScaledWidth() / 2, 28)
if (pos.canJumpToConfigOptions())
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/combat/ghostcounter/textformatting/BestiaryFormattingConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/combat/ghostcounter/textformatting/BestiaryFormattingConfig.java
index 46a02e9b21e3..ac9f6e0b210a 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/combat/ghostcounter/textformatting/BestiaryFormattingConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/combat/ghostcounter/textformatting/BestiaryFormattingConfig.java
@@ -30,7 +30,7 @@ public class BestiaryFormattingConfig {
@ConfigOption(name = "Progress to Max", desc = "Text to show progress when the §eMaxed Bestiary §7option is §aON\n" +
"§e%currentKill% §7is replaced with your current total kill.")
@ConfigEditorText
- public String showMax_progress = "%currentKill%/250k (%percentNumber%%)";
+ public String showMax_progress = "%currentKill%/100k (%percentNumber%%)";
@Expose
@ConfigOption(name = "Progress", desc = "Text to show progress when the §eMaxed Bestiary §7option is §cOFF\n" +
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/dev/DevConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/dev/DevConfig.java
index b62c88efc61f..6daf37cfda74 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/dev/DevConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/dev/DevConfig.java
@@ -108,6 +108,13 @@ public class DevConfig {
@ConfigEditorBoolean
public boolean fancySbaContributors = false;
+ @Expose
+ @ConfigOption(
+ name = "Number Format Override",
+ desc = "Forces the number format to use the en_US locale.")
+ @ConfigEditorBoolean
+ public boolean numberFormatOverride = false;
+
@Expose
@Category(name = "Minecraft Console", desc = "Minecraft Console Settings")
public MinecraftConsoleConfig minecraftConsoles = new MinecraftConsoleConfig();
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/dev/GraphConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/dev/GraphConfig.java
index 9eed8233c995..dda1ddb1e50c 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/dev/GraphConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/dev/GraphConfig.java
@@ -4,6 +4,7 @@
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.ConfigEditorSlider;
import io.github.notenoughupdates.moulconfig.annotations.ConfigLink;
import io.github.notenoughupdates.moulconfig.annotations.ConfigOption;
import org.lwjgl.input.Keyboard;
@@ -31,6 +32,11 @@ public class GraphConfig {
@ConfigEditorKeybind(defaultKey = -98) // Middle Mouse
public int selectKey = -98;
+ @Expose
+ @ConfigOption(name = "Select near look", desc = "Select the node closest to where you are looking.")
+ @ConfigEditorKeybind(defaultKey = Keyboard.KEY_NONE)
+ public int selectRaycastKey = Keyboard.KEY_NONE;
+
@Expose
@ConfigOption(name = "Connect Key", desc = "Connect the nearest node with the active node. If the nodes are already connected removes the connection.")
@ConfigEditorKeybind(defaultKey = Keyboard.KEY_C)
@@ -99,6 +105,17 @@ public class GraphConfig {
@ConfigLink(owner = GraphConfig.class, field = "enabled")
public Position namedNodesList = new Position(20, 20);
+ @Expose
+ @ConfigOption(
+ name = "Max Node Distance",
+ desc = "Only render nodes below this distance to the player.")
+ @ConfigEditorSlider(
+ minValue = 10,
+ maxValue = 500,
+ minStep = 10
+ )
+ public int maxNodeDistance = 50;
+
@Expose
@ConfigOption(name = "Shows Stats", desc = "Show funny extra statistics on save. May lag the game a bit.")
@ConfigEditorBoolean
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/dungeon/ObjectHighlighterConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/dungeon/ObjectHighlighterConfig.java
index 385c162c6623..a1c29cd4482f 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/dungeon/ObjectHighlighterConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/dungeon/ObjectHighlighterConfig.java
@@ -14,13 +14,13 @@ public class ObjectHighlighterConfig {
// TODO move some stuff from DungeonConfig into this
@Expose
- @ConfigOption(name = "Stared", desc = "")
+ @ConfigOption(name = "Starred Mobs", desc = "")
@Accordion
public StarredConfig starred = new StarredConfig();
public static class StarredConfig {
@Expose
- @ConfigOption(name = "Highlight Starred", desc = "Highlights all starred mobs in one colour.")
+ @ConfigOption(name = "Highlight Starred", desc = "Highlights starred mobs in a color.")
@ConfigEditorBoolean
@FeatureToggle
public Property highlight = Property.of(true);
@@ -40,7 +40,7 @@ public static class StarredConfig {
public String info;
@Expose
- @ConfigOption(name = "Colour", desc = "Color in which the stared mobs are highlighted.")
+ @ConfigOption(name = "Color", desc = "The color used to highlight starred mobs.")
@ConfigEditorColour
public Property colour = Property.of("0:60:255:255:0");
}
@@ -53,18 +53,18 @@ public static class StarredConfig {
public static class FelConfig {
@Expose
- @ConfigOption(name = "Highlight Fels Skull", desc = "Highlights fels that are not yet active.")
+ @ConfigOption(name = "Highlight Fels Skull", desc = "Highlights fels that are not active.")
@ConfigEditorBoolean
@FeatureToggle
public Property highlight = Property.of(true);
@Expose
- @ConfigOption(name = "Draw Line", desc = "Draws a line to fels skulls. Works only if the highlight is enabled.")
+ @ConfigOption(name = "Draw Line", desc = "Draws a line to fels skulls. Requires highlight to be enabled.")
@ConfigEditorBoolean
public Boolean line = false;
@Expose
- @ConfigOption(name = "Colour", desc = "Color for the fel skull and line.")
+ @ConfigOption(name = "Color", desc = "The color used to highlight fel skulls and draw the line.")
@ConfigEditorColour
public Property colour = Property.of("0:200:255:0:255");
}
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 b438d83f5c3b..8bbaa962ca26 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
@@ -197,6 +197,11 @@ public String toString() {
}
}
+ @Expose
+ @ConfigOption(name = "Show Duplicate Count", desc = "Show the number of previous finds of a duplicate Hoppity rabbit in chat messages.")
+ @ConfigEditorBoolean
+ public boolean showDuplicateNumber = false;
+
@Expose
@ConfigOption(
name = "Rabbit Pet Warning",
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/event/winter/WinterConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/event/winter/WinterConfig.java
index 837f4c7ea811..550ceaeee0ec 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/event/winter/WinterConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/event/winter/WinterConfig.java
@@ -46,4 +46,10 @@ public class WinterConfig {
@FeatureToggle
public boolean newYearCakeReminder = true;
+ @Expose
+ @ConfigOption(name = "Reindrake Warp Helper", desc = "Sends a clickable message in chat to warp to the Winter Island spawn when a Reindrake spawns.")
+ @ConfigEditorBoolean
+ @FeatureToggle
+ public boolean reindrakeWarpHelper = true;
+
}
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/garden/GardenConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/garden/GardenConfig.java
index b39f5f01ce63..8aa9aa6a1124 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/garden/GardenConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/garden/GardenConfig.java
@@ -158,12 +158,6 @@ public class GardenConfig {
@FeatureToggle
public boolean burrowingSporesNotification = true;
- @Expose
- @ConfigOption(name = "Wild Strawberry", desc = "Show a notification when a Wild Strawberry Dye drops while farming.")
- @ConfigEditorBoolean
- @FeatureToggle
- public boolean wildStrawberryDyeNotification = true;
-
@Expose
@ConfigOption(
name = "FF for Contest",
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/gui/GUIConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/gui/GUIConfig.java
index 74ab755c9940..37f3d3c42037 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/gui/GUIConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/gui/GUIConfig.java
@@ -36,7 +36,7 @@ public class GUIConfig {
@Accordion
public ChromaConfig chroma = new ChromaConfig();
- @ConfigOption(name = "Edit GUI Locations", desc = "Change the position of SkyHanni's overlays.")
+ @ConfigOption(name = "Edit GUI Locations", desc = "Opens the Position Editor, allows changing the position of SkyHanni's overlays.")
@ConfigEditorButton(buttonText = "Edit")
public Runnable positions = () -> GuiEditManager.openGuiPositionEditor(true);
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/GetFromSackConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/GetFromSackConfig.java
index ee77d6664317..f4b16343fef0 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/GetFromSackConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/GetFromSackConfig.java
@@ -25,11 +25,6 @@ public class GetFromSackConfig {
@FeatureToggle
public boolean superCraftGFS = true;
- @Expose
- @ConfigOption(name = "Default GfS", desc = "If you don't provide an amount, a default one will be used instead. Queued GfS needs to be on in order for this to work.")
- @ConfigEditorBoolean
- public boolean defaultGFS = false;
-
@Expose
@ConfigOption(name = "Default Amount GfS", desc = "The default amount of items used when an amount isn't provided.")
@ConfigEditorSlider(minValue = 1, maxValue = 64, minStep = 1)
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 cf162ad7b6a8..510f953ca2f9 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
@@ -4,6 +4,7 @@
import at.hannibal2.skyhanni.config.HasLegacyId;
import at.hannibal2.skyhanni.config.features.inventory.chocolatefactory.ChocolateFactoryConfig;
import at.hannibal2.skyhanni.config.features.inventory.customwardrobe.CustomWardrobeConfig;
+import at.hannibal2.skyhanni.config.features.inventory.experimentationtable.ExperimentationTableConfig;
import at.hannibal2.skyhanni.config.features.inventory.helper.HelperConfig;
import at.hannibal2.skyhanni.config.features.itemability.ItemAbilityConfig;
import at.hannibal2.skyhanni.config.features.misc.EstimatedItemValueConfig;
@@ -38,6 +39,10 @@ public class InventoryConfig {
@Category(name = "Bazaar", desc = "Be smart when buying or selling many items in the Bazaar.")
public BazaarConfig bazaar = new BazaarConfig();
+ @Expose
+ @Category(name = "Experimentation Table", desc = "QOL features for the Experimentation Table.")
+ public ExperimentationTableConfig experimentationTable = new ExperimentationTableConfig();
+
@Expose
@Category(name = "Enchant Parsing", desc = "Settings for SkyHanni's Enchant Parsing")
public EnchantParsingConfig enchantParsing = new EnchantParsingConfig();
@@ -61,6 +66,7 @@ public class InventoryConfig {
@Expose
@ConfigOption(name = "Item Pickup Log", desc = "Logs all the picked up and dropped items")
@Accordion
+ // TODO remove the suffix "config"
public ItemPickupLogConfig itemPickupLogConfig = new ItemPickupLogConfig();
@Expose
@@ -286,4 +292,10 @@ public String toString() {
@ConfigEditorBoolean
@FeatureToggle
public boolean hexAsColorInLore = true;
+
+ @Expose
+ @ConfigOption(name = "Highlight Active Beacon Effect", desc = "Highlights the currently selected beacon effect in the beacon inventory.")
+ @ConfigEditorBoolean
+ @FeatureToggle
+ public boolean highlightActiveBeaconEffect = true;
}
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/chocolatefactory/ChocolateFactoryConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/chocolatefactory/ChocolateFactoryConfig.java
index e35bc4d7e790..5d1c63f8d7e1 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/chocolatefactory/ChocolateFactoryConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/chocolatefactory/ChocolateFactoryConfig.java
@@ -2,6 +2,7 @@
import at.hannibal2.skyhanni.config.FeatureToggle;
import at.hannibal2.skyhanni.config.core.config.Position;
+import at.hannibal2.skyhanni.features.event.hoppity.HoppityCollectionStats.HighlightRabbitTypes;
import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactoryStats.ChocolateFactoryStat;
import com.google.gson.annotations.Expose;
import io.github.notenoughupdates.moulconfig.annotations.Accordion;
@@ -174,18 +175,27 @@ public class ChocolateFactoryConfig {
public boolean hoppityMenuShortcut = true;
@Expose
- @ConfigOption(name = "Highlight Requirement Rabbits", desc = "Highlight rabbits that have requirements.\n" +
- "§cRed: Requirement not met.\n" +
- "§aGreen: Requirement met.")
+ @ConfigOption(name = "Highlight Found Rabbits", desc = "Highlight rabbits that have already been found.")
@ConfigEditorBoolean
@FeatureToggle
- public boolean highlightRabbitsWithRequirement = false;
+ public boolean highlightFoundRabbits = false;
@Expose
- @ConfigOption(name = "Only Requirement Not Met", desc = "Only highlight the rabbits you don't have the requirement for.")
+ @ConfigOption(name = "Highlight Rabbits", desc = "Highlight specific rabbit types in Hoppity's Collection.")
+ @ConfigEditorDraggableList
+ public List highlightRabbits = new ArrayList<>(Arrays.asList(
+ HighlightRabbitTypes.ABI,
+ HighlightRabbitTypes.FACTORY,
+ HighlightRabbitTypes.MET,
+ HighlightRabbitTypes.NOT_MET,
+ HighlightRabbitTypes.SHOP,
+ HighlightRabbitTypes.STRAYS
+ ));
+
+ @Expose
+ @ConfigOption(name = "Re-color Missing Rabbit Dyes", desc = "Replace the gray dye in Hoppity's Collection with a color for the rarity of the rabbit.")
@ConfigEditorBoolean
- @FeatureToggle
- public boolean onlyHighlightRequirementNotMet = true;
+ public boolean rarityDyeRecolor = true;
@Expose
@ConfigOption(
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/experimentationtable/ExperimentationTableConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/experimentationtable/ExperimentationTableConfig.java
new file mode 100644
index 000000000000..dfdad248256e
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/experimentationtable/ExperimentationTableConfig.java
@@ -0,0 +1,50 @@
+package at.hannibal2.skyhanni.config.features.inventory.experimentationtable;
+
+import at.hannibal2.skyhanni.config.FeatureToggle;
+import at.hannibal2.skyhanni.config.core.config.Position;
+import com.google.gson.annotations.Expose;
+import io.github.notenoughupdates.moulconfig.annotations.Accordion;
+import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean;
+import io.github.notenoughupdates.moulconfig.annotations.ConfigLink;
+import io.github.notenoughupdates.moulconfig.annotations.ConfigOption;
+
+public class ExperimentationTableConfig {
+
+ @Expose
+ @ConfigOption(name = "Profit Tracker", desc = "")
+ @Accordion
+ public ExperimentsProfitTrackerConfig experimentsProfitTracker = new ExperimentsProfitTrackerConfig();
+
+ @Expose
+ @ConfigOption(name = "Dry-Streak Display", desc = "")
+ @Accordion
+ public ExperimentsDryStreakConfig dryStreak = new ExperimentsDryStreakConfig();
+
+ @Expose
+ @ConfigOption(name = "Superpair Data", desc = "Shows a display with useful information while doing the Superpair experiment.")
+ @ConfigEditorBoolean
+ @FeatureToggle
+ public boolean superpairDisplay = false;
+
+ @Expose
+ @ConfigLink(owner = ExperimentationTableConfig.class, field = "superpairDisplay")
+ public Position superpairDisplayPosition = new Position(-372, 161, false, true);
+
+ @Expose
+ @ConfigOption(name = "Superpairs Clicks Alert", desc = "Display an alert when you reach the maximum clicks gained from Chronomatron or Ultrasequencer.")
+ @ConfigEditorBoolean
+ @FeatureToggle
+ public boolean superpairsClicksAlert = false;
+
+ @Expose
+ @ConfigOption(name = "ULTRA-RARE Book Alert", desc = "Send a chat message, title and sound when you find an ULTRA-RARE book.")
+ @ConfigEditorBoolean
+ @FeatureToggle
+ public boolean ultraRareBookAlert = false;
+
+ @Expose
+ @ConfigOption(name = "Guardian Reminder", desc = "Sends a warning when opening the Experimentation Table without a §9§lGuardian Pet §7equipped.")
+ @ConfigEditorBoolean
+ @FeatureToggle
+ public boolean guardianReminder = false;
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/experimentationtable/ExperimentsDryStreakConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/experimentationtable/ExperimentsDryStreakConfig.java
new file mode 100644
index 000000000000..dfba626a764f
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/experimentationtable/ExperimentsDryStreakConfig.java
@@ -0,0 +1,31 @@
+package at.hannibal2.skyhanni.config.features.inventory.experimentationtable;
+
+import at.hannibal2.skyhanni.config.FeatureToggle;
+import at.hannibal2.skyhanni.config.core.config.Position;
+import com.google.gson.annotations.Expose;
+import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean;
+import io.github.notenoughupdates.moulconfig.annotations.ConfigLink;
+import io.github.notenoughupdates.moulconfig.annotations.ConfigOption;
+
+public class ExperimentsDryStreakConfig {
+
+ @Expose
+ @ConfigOption(name = "Enabled", desc = "Display attempts and or XP since your last ULTRA-RARE.")
+ @ConfigEditorBoolean
+ @FeatureToggle
+ public boolean enabled = false;
+
+ @Expose
+ @ConfigOption(name = "Attempts", desc = "Display Attempts since.")
+ @ConfigEditorBoolean
+ public boolean attemptsSince = true;
+
+ @Expose
+ @ConfigOption(name = "XP", desc = "Display XP since.")
+ @ConfigEditorBoolean
+ public boolean xpSince = true;
+
+ @Expose
+ @ConfigLink(owner = ExperimentsDryStreakConfig.class, field = "enabled")
+ public Position position = new Position(200, -187, false, true);
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/experimentationtable/ExperimentsProfitTrackerConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/experimentationtable/ExperimentsProfitTrackerConfig.java
new file mode 100644
index 000000000000..62ee4f5407ba
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/experimentationtable/ExperimentsProfitTrackerConfig.java
@@ -0,0 +1,37 @@
+package at.hannibal2.skyhanni.config.features.inventory.experimentationtable;
+
+import at.hannibal2.skyhanni.config.FeatureToggle;
+import at.hannibal2.skyhanni.config.core.config.Position;
+import at.hannibal2.skyhanni.features.inventory.experimentationtable.ExperimentMessages;
+import com.google.gson.annotations.Expose;
+import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean;
+import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorDraggableList;
+import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorSlider;
+import io.github.notenoughupdates.moulconfig.annotations.ConfigLink;
+import io.github.notenoughupdates.moulconfig.annotations.ConfigOption;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ExperimentsProfitTrackerConfig {
+
+ @Expose
+ @ConfigOption(name = "Enabled", desc = "Tracker for drops/XP you get from experiments.")
+ @ConfigEditorBoolean
+ @FeatureToggle
+ public boolean enabled = false;
+
+ @Expose
+ @ConfigOption(name = "Hide Messages", desc = "Change the messages to be hidden after completing Add-on/Main experiments.")
+ @ConfigEditorDraggableList
+ public List hideMessages = new ArrayList<>();
+
+ @Expose
+ @ConfigOption(name = "Time displayed", desc = "Time displayed after completing an experiment.")
+ @ConfigEditorSlider(minValue = 5, maxValue = 60, minStep = 1)
+ public int timeDisplayed = 30;
+
+ @Expose
+ @ConfigLink(owner = ExperimentsProfitTrackerConfig.class, field = "enabled")
+ public Position position = new Position(20, 20, false, true);
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/helper/HelperConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/helper/HelperConfig.java
index 5f54e707d010..717dd76591de 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/helper/HelperConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/helper/HelperConfig.java
@@ -56,30 +56,4 @@ public static class HarpConfig {
@ConfigOption(name = "Reforge Helper", desc = "")
@Accordion
public ReforgeHelperConfig reforge = new ReforgeHelperConfig();
-
- @Expose
- @ConfigOption(name = "Enchanting", desc = "")
- @Accordion
- public EnchantingConfig enchanting = new EnchantingConfig();
-
- public static class EnchantingConfig {
- @Expose
- @ConfigOption(name = "Superpairs Clicks Alert", desc = "Display an alert when you reach the maximum clicks gained from Chronomatron or Ultrasequencer.")
- @ConfigEditorBoolean
- @FeatureToggle
- public boolean superpairsClicksAlert = false;
-
- @Expose
- @ConfigOption(name = "ULTRA-RARE Book Alert", desc = "Send a chat message, title and sound when you find an ULTRA-RARE book.")
- @ConfigEditorBoolean
- @FeatureToggle
- public boolean ultraRareBookAlert = false;
-
- @Expose
- @ConfigOption(name = "Guardian Reminder", desc = "Sends a warning when opening the Experimentation Table without a §9§lGuardian Pet §7equipped.")
- @ConfigEditorBoolean
- @FeatureToggle
- public boolean guardianReminder = false;
- }
-
}
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/mining/CorpseTrackerConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/mining/CorpseTrackerConfig.java
index 61d3b19594a7..229883c83352 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/mining/CorpseTrackerConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/mining/CorpseTrackerConfig.java
@@ -1,5 +1,6 @@
package at.hannibal2.skyhanni.config.features.mining;
+import at.hannibal2.skyhanni.config.FeatureToggle;
import at.hannibal2.skyhanni.config.core.config.Position;
import com.google.gson.annotations.Expose;
import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean;
@@ -11,6 +12,7 @@ public class CorpseTrackerConfig {
@Expose
@ConfigOption(name = "Enabled", desc = "Enable the Corpse Tracker overlay for Glacite Mineshafts.")
@ConfigEditorBoolean
+ @FeatureToggle
public boolean enabled = false;
@Expose
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/mining/ExcavatorTooltipHiderConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/mining/ExcavatorTooltipHiderConfig.java
new file mode 100644
index 000000000000..b1489ace876a
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/mining/ExcavatorTooltipHiderConfig.java
@@ -0,0 +1,21 @@
+package at.hannibal2.skyhanni.config.features.mining;
+
+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.ConfigOption;
+
+public class ExcavatorTooltipHiderConfig {
+
+ @Expose
+ @ConfigOption(name = "Hide Dirt", desc = "Hides tooltips of the Dirt inside of the Fossil Excavator.")
+ @ConfigEditorBoolean
+ @FeatureToggle
+ public boolean hideDirt = true;
+
+ @Expose
+ @ConfigOption(name = "Hide Everything", desc = "Hide all tooltips inside of the Fossil Excavator.")
+ @ConfigEditorBoolean
+ @FeatureToggle
+ public boolean hideEverything = false;
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/mining/FossilExcavatorConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/mining/FossilExcavatorConfig.java
index 176c8f3bda35..8445afe5336a 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/mining/FossilExcavatorConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/mining/FossilExcavatorConfig.java
@@ -18,6 +18,11 @@ public class FossilExcavatorConfig {
@Accordion
public ExcavatorProfitTrackerConfig profitTracker = new ExcavatorProfitTrackerConfig();
+ @Expose
+ @ConfigOption(name = "Excavator Tooltip Hider", desc = "")
+ @Accordion
+ public ExcavatorTooltipHiderConfig tooltipHider = new ExcavatorTooltipHiderConfig();
+
@Expose
@ConfigOption(
name = "Profit per Excavation",
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/mining/MiningConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/mining/MiningConfig.java
index 5f242ecd5f47..08c8ec894a71 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/mining/MiningConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/mining/MiningConfig.java
@@ -96,10 +96,4 @@ public class MiningConfig {
@ConfigEditorBoolean
@FeatureToggle
public boolean highlightYourGoldenGoblin = true;
-
- @Expose
- @ConfigOption(name = "Forge GfS", desc = "Get Forge ingredients of a recipe.")
- @ConfigEditorBoolean
- @FeatureToggle
- public boolean forgeGfs = false;
}
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 03b0bf779f61..9d503c3986be 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
@@ -144,6 +144,9 @@ public class MiscConfig {
@Expose
public Position collectionCounterPos = new Position(10, 10, false, true);
+ @Expose
+ public Position carryPosition = new Position(10, 10, false, true);
+
@Expose
@ConfigOption(name = "Brewing Stand Overlay", desc = "Display the item names directly inside the Brewing Stand.")
@ConfigEditorBoolean
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/rift/EnigmaSoulConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/rift/EnigmaSoulConfig.java
index 96c721539c1c..f64a42506043 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/rift/EnigmaSoulConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/rift/EnigmaSoulConfig.java
@@ -15,6 +15,11 @@ public class EnigmaSoulConfig {
@FeatureToggle
public boolean enabled = true;
+ @Expose
+ @ConfigOption(name = "Show Path Finder", desc = "Additionally show a pathfind to the Enigma Soul.")
+ @ConfigEditorBoolean
+ public boolean showPathFinder = true;
+
@ConfigOption(
name = "§aRift Guide",
desc = "Type §e/riftguide §7in chat or navigate through the SkyBlock Menu to open the §aRift Guide§7. " +
@@ -26,6 +31,5 @@ public class EnigmaSoulConfig {
@Expose
@ConfigOption(name = "Color", desc = "Color of the Enigma Souls.")
@ConfigEditorColour
- public String color = "0:120:13:49:255";
-
+ public String color = "0:245:219:27:198";
}
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 83e7ea47c254..754eea3bba59 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java
@@ -31,6 +31,7 @@
import at.hannibal2.skyhanni.features.garden.pests.VinylType;
import at.hannibal2.skyhanni.features.garden.visitor.VisitorReward;
import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactoryStrayTracker;
+import at.hannibal2.skyhanni.features.inventory.experimentationtable.ExperimentsProfitTracker;
import at.hannibal2.skyhanni.features.inventory.wardrobe.WardrobeAPI;
import at.hannibal2.skyhanni.features.mining.MineshaftPityDisplay;
import at.hannibal2.skyhanni.features.mining.fossilexcavator.ExcavatorProfitTracker;
@@ -65,6 +66,29 @@ private static SimpleTimeMark SimpleTimeMarkFarPast() {
@Expose
public String currentPet = "";
+ @Expose
+ public ExperimentationStorage experimentation = new ExperimentationStorage();
+
+ public static class ExperimentationStorage {
+
+ @Expose
+ public LorenzVec tablePos = new LorenzVec();
+
+ @Expose
+ public ExperimentsDryStreakStorage dryStreak = new ExperimentsDryStreakStorage();
+
+ public static class ExperimentsDryStreakStorage {
+ @Expose
+ public int attemptsSince = 0;
+
+ @Expose
+ public int xpSince = 0;
+ }
+
+ @Expose
+ public ExperimentsProfitTracker.Data experimentsProfitTracker = new ExperimentsProfitTracker.Data();
+ }
+
@Expose
public ChocolateFactoryStorage chocolateFactory = new ChocolateFactoryStorage();
diff --git a/src/main/java/at/hannibal2/skyhanni/data/HotmData.kt b/src/main/java/at/hannibal2/skyhanni/data/HotmData.kt
index 0392eab25af8..1d8182328b6e 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/HotmData.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/HotmData.kt
@@ -26,22 +26,21 @@ import at.hannibal2.skyhanni.utils.ItemUtils.getLore
import at.hannibal2.skyhanni.utils.ItemUtils.name
import at.hannibal2.skyhanni.utils.LorenzUtils
import at.hannibal2.skyhanni.utils.NumberUtil.formatLong
+import at.hannibal2.skyhanni.utils.RegexUtils.firstMatcher
import at.hannibal2.skyhanni.utils.RegexUtils.indexOfFirstMatch
-import at.hannibal2.skyhanni.utils.RegexUtils.matchFirst
import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher
import at.hannibal2.skyhanni.utils.RegexUtils.matches
import at.hannibal2.skyhanni.utils.StringUtils.allLettersFirstUppercase
import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern
import net.minecraft.inventory.Slot
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
-import kotlin.math.ceil
import kotlin.math.pow
-private fun calculatePeakOfTheMountainLoot(level: Int): Map = buildMap {
+private fun calculateCoreOfTheMountainLoot(level: Int): Map = buildMap {
for (i in 1..level) {
when (i) {
1, 5, 7 -> addOrPut(HotmReward.EXTRA_TOKENS, 1.0)
- 2 -> addOrPut(HotmReward.EXTRA_FORGE_SLOTS, 1.0)
+ 2 -> addOrPut(HotmReward.ABILITY_LEVEL, 1.0)
3 -> addOrPut(HotmReward.EXTRA_COMMISSION_SLOTS, 1.0)
4 -> addOrPut(HotmReward.MORE_BASE_MITHRIL_POWER, 1.0)
6 -> addOrPut(HotmReward.MORE_BASE_GEMSTONE_POWER, 2.0)
@@ -62,20 +61,14 @@ enum class HotmData(
MINING_SPEED(
"Mining Speed",
50,
- { level -> (level + 1.0).pow(3) },
+ { level -> (level + 1.0).pow(3.0) },
{ level -> mapOf(HotmReward.MINING_SPEED to level * 20.0) },
),
MINING_FORTUNE(
"Mining Fortune",
50,
{ level -> (level + 1.0).pow(3.05) },
- { level -> mapOf(HotmReward.MINING_FORTUNE to level * 5.0) },
- ),
- QUICK_FORGE(
- "Quick Forge",
- 20,
- { level -> (level + 1.0).pow(4) },
- { level -> mapOf(HotmReward.FORGE_TIME_DECREASE to if (level >= 20) 30.0 else 10.0 + (level * 0.5)) },
+ { level -> mapOf(HotmReward.MINING_FORTUNE to level * 2.0) },
),
TITANIUM_INSANIUM(
"Titanium Insanium",
@@ -83,40 +76,47 @@ enum class HotmData(
{ level -> (level + 1.0).pow(3.1) },
{ level -> mapOf(HotmReward.TITANIUM_CHANCE to 2.0 + (level * 0.1)) },
),
- DAILY_POWDER(
- "Daily Powder",
- 100,
- { level -> 200 + ((level - 1) * 18.0) },
- { level -> mapOf(HotmReward.DAILY_POWDER to (200.0 + ((level - 1.0) * 18.0)) * 2.0) },
- ),
LUCK_OF_THE_CAVE(
"Luck of the Cave",
45,
{ level -> (level + 1.0).pow(3.07) },
{ level -> mapOf(HotmReward.EXTRA_CHANCE_TRIGGER_RARE_OCCURRENCES to 5.0 + level) },
),
- CRYSTALLIZED(
- "Crystallized",
- 30,
- { level -> (level + 1.0).pow(3.4) },
- { level ->
- mapOf(
- HotmReward.MINING_SPEED to 20.0 + ((level - 1.0) * 6.0),
- HotmReward.MINING_FORTUNE to 20.0 + ((level - 1.0) * 5.0),
- )
- },
- ),
EFFICIENT_MINER(
"Efficient Miner",
100,
{ level -> (level + 1.0).pow(2.6) },
- { level -> mapOf(HotmReward.AVERAGE_BLOCK_BREAKS to (10.0 + (level * 0.4)) * (1.0 + (level * 0.05))) },
+ { level -> mapOf(HotmReward.MINING_SPREAD to 3.0 * level) },
),
- ORBITER(
- "Orbiter",
- 80,
- { level -> level * 70.0 },
- { level -> mapOf(HotmReward.CHANCE_EXTRA_XP_ORBS to 0.2 + (level * 0.01)) },
+ QUICK_FORGE(
+ "Quick Forge",
+ 20,
+ { level -> (level + 1.0).pow(3.2) },
+ { level -> mapOf(HotmReward.FORGE_TIME_DECREASE to if (level >= 20) 30.0 else 10.0 + (level * 0.5)) },
+ ),
+ OLD_SCHOOL(
+ "Old-School",
+ 20,
+ { level -> (level + 1.0).pow(4.0) },
+ { level -> mapOf(HotmReward.ORE_FORTUNE to level * 5.0) },
+ ),
+ PROFESSIONAL(
+ "Professional",
+ 140,
+ { level -> (level + 1.0).pow(2.3) },
+ { level -> mapOf(HotmReward.MINING_SPEED to 50.0 + (level * 5.0)) },
+ ),
+ MOLE(
+ "Mole",
+ 200,
+ { level -> (level + 1.0).pow(2.17883) },
+ { level -> mapOf(HotmReward.MINING_SPREAD to 50.0 + ((level - 1) * (350 / 199))) },
+ ),
+ GEM_LOVER(
+ "Gem Lover",
+ 20,
+ { level -> (level + 1.0).pow(4.0) },
+ { level -> mapOf(HotmReward.GEMSTONE_FORTUNE to 20.0 + (level * 4.0)) },
),
SEASONED_MINEMAN(
"Seasoned Mineman",
@@ -124,18 +124,25 @@ enum class HotmData(
{ level -> (level + 1.0).pow(2.3) },
{ level -> mapOf(HotmReward.MINING_WISDOM to 5.0 + (level * 0.1)) },
),
- MOLE(
- "Mole",
- 190,
- { level -> (level + 1.0).pow(2.2) },
- { level -> mapOf(HotmReward.AVERAGE_BLOCK_BREAKS to 1.0 + ((level + 9.0) * 0.05 * ((level + 8) % 20))) },
+ FORTUNATE_MINEMAN(
+ "Fortunate Mineman",
+ 50,
+ { level -> (level + 1.0).pow(3.2) },
+ { level -> mapOf(HotmReward.MINING_FORTUNE to level * 3.0) },
),
- PROFESSIONAL(
- "Professional",
- 140,
- { level -> (level + 1.0).pow(2.3) },
- { level -> mapOf(HotmReward.MINING_SPEED to 50.0 + (level * 5.0)) },
+ BLOCKHEAD(
+ "Blockhead",
+ 20,
+ { level -> (level + 1.0).pow(4.0) },
+ { level -> mapOf(HotmReward.BLOCK_FORTUNE to level * 5.0) },
+ ),
+ KEEP_IT_COOL(
+ "Keep It Cool",
+ 50,
+ { level -> (level + 1.0).pow(3.07) },
+ { level -> mapOf(HotmReward.HEAT_RESISTANCE to level * 0.4) },
),
+
LONESOME_MINER(
"Lonesome Miner",
45,
@@ -153,12 +160,7 @@ enum class HotmData(
)
},
),
- FORTUNATE(
- "Fortunate",
- 20,
- { level -> (level + 1.0).pow(3.05) },
- { level -> mapOf(HotmReward.MINING_FORTUNE to 20.0 + (level * 4.0)) },
- ),
+
POWDER_BUFF(
"Powder Buff",
50,
@@ -170,32 +172,32 @@ enum class HotmData(
)
},
),
- MINING_SPEED_II(
- "Mining Speed II",
+ SPEEDY_MINEMAN(
+ "Speedy Mineman",
50,
{ level -> (level + 1.0).pow(3.2) },
{ level -> mapOf(HotmReward.MINING_SPEED to level * 40.0) },
),
- MINING_FORTUNE_II(
- "Mining Fortune II",
- 50,
- { level -> (level + 1.0).pow(3.2) },
- { level -> mapOf(HotmReward.MINING_FORTUNE to level * 5.0) },
- ),
- // Static
- MINING_MADNESS(
- "Mining Madness",
- 1,
- { null },
- {
+
+
+ SUBTERRANEAN_FISHER(
+ "Subterranean Fisher",
+ 40,
+ { level -> (level + 1.0).pow(3.07) },
+ { level ->
mapOf(
- HotmReward.MINING_SPEED to 50.0,
- HotmReward.MINING_FORTUNE to 50.0,
+ HotmReward.FISHING_SPEED to 5 + (level * 0.5),
+ HotmReward.SEA_CREATURE_CHANCE to 1 + (level * 0.1),
)
},
+
),
+
+
+ // Static
+
SKY_MALL("Sky Mall", 1, { null }, { emptyMap() }),
PRECISION_MINING("Precision Mining", 1, { null }, { mapOf(HotmReward.MINING_SPEED_BOOST to 30.0) }),
FRONT_LOADED(
@@ -204,16 +206,14 @@ enum class HotmData(
{ null },
{
mapOf(
- HotmReward.MINING_SPEED to 100.0,
- HotmReward.MINING_FORTUNE to 100.0,
- HotmReward.MORE_BASE_MITHRIL_POWER to 2.0,
- HotmReward.MORE_BASE_GEMSTONE_POWER to 2.0,
+ HotmReward.MINING_SPEED to 250.0,
+ HotmReward.GEMSTONE_FORTUNE to 150.0,
+ HotmReward.MORE_GEMSTONE_POWER to 200.0,
)
},
),
- STAR_POWDER("Star Powder", 1, { null }, { mapOf(HotmReward.MORE_MITHRIL_POWER to 300.0) }),
- GOBLIN_KILLER("Goblin Killer", 1, { null }, { emptyMap() }),
-
+ DAILY_GRIND("Daily Grind", 1, { null }, { emptyMap() }),
+ DAILY_POWDER("Daily Powder", 1, { null }, { emptyMap() }),
// Abilities
PICKOBULUS(
@@ -222,8 +222,8 @@ enum class HotmData(
{ null },
{ level ->
mapOf(
- HotmReward.ABILITY_RADIUS to ceil(level * 0.5) + 1.0,
- HotmReward.ABILITY_COOLDOWN to 130.0 - 10.0 * level,
+ HotmReward.ABILITY_RADIUS to 3.0,
+ HotmReward.ABILITY_COOLDOWN to 60.0 - 10.0 * (level - 1),
)
},
),
@@ -233,66 +233,57 @@ enum class HotmData(
{ null },
{ level ->
mapOf(
- HotmReward.ABILITY_DURATION to level + 1.0,
- HotmReward.ABILITY_COOLDOWN to 10.0 + 5.0 * level,
+ HotmReward.MINING_SPEED_BOOST to 200.0 + 50.0 * (level - 1),
+ HotmReward.ABILITY_DURATION to 10.0 + 5 * (level - 1),
+ HotmReward.ABILITY_COOLDOWN to 120.0,
)
},
),
- VEIN_SEEKER(
- "Vein Seeker",
+ MANIAC_MINER(
+ "Maniac Miner",
3,
{ null },
{ level ->
mapOf(
- HotmReward.ABILITY_RADIUS to level + 1.0,
- HotmReward.ABILITY_DURATION to 10.0 + 2.0 * level,
+ HotmReward.ABILITY_DURATION to 20.0 + level * 5.0,
HotmReward.ABILITY_COOLDOWN to 60.0,
+ HotmReward.BREAKING_POWER to 1.0,
)
},
),
- MANIAC_MINER(
- "Maniac Miner",
+
+ SHEER_FORCE(
+ "Sheer Force",
3,
{ null },
{ level ->
mapOf(
- HotmReward.ABILITY_DURATION to 5.0 + level * 5.0,
- HotmReward.ABILITY_COOLDOWN to 60.0 - level,
+ HotmReward.ABILITY_DURATION to 20.0 + 5 * (level - 1),
+ HotmReward.MINING_SPREAD to 200.0,
)
},
),
- PEAK_OF_THE_MOUNTAIN(
- "Peak of the Mountain", 10, { null },
- { level -> calculatePeakOfTheMountainLoot(level) },
+ ANOMALOUS_DESIRE(
+ "Anomalous Desire",
+ 3,
+ { null },
+ { level ->
+ mapOf(
+ HotmReward.EXTRA_CHANCE_TRIGGER_RARE_OCCURRENCES to 30.0 + (level - 1) * 10.0,
+ HotmReward.ABILITY_COOLDOWN to 120.0 - (level - 1) * 10.0,
+ HotmReward.ABILITY_DURATION to 30.0,
+ )
+ },
),
- // Mining V3
- DAILY_GRIND(
- "Daily Grind",
- 100,
- { level -> 218 + (18 * (level - 1.0)) },
- { level -> mapOf(HotmReward.DAILY_POWDER to 50.0 * level) },
- ),
- DUST_COLLECTOR(
- "Dust Collector",
- 20,
- { level -> (level + 1.0).pow(4) },
- { level -> mapOf(HotmReward.FOSSIL_DUST to 1.0 * level) },
- ),
- WARM_HEARTED(
- "Warm Hearted",
- 50,
- { level -> (level + 1.0).pow(3.1) },
- { level -> mapOf(HotmReward.COLD_RESISTANCE to 0.2 * level) },
+ CORE_OF_THE_MOUNTAIN(
+ "Core of the Mountain", 10, { null },
+ { level -> calculateCoreOfTheMountainLoot(level) },
),
- STRONG_ARM(
- "Strong Arm",
- 100,
- { level -> (level + 1.0).pow(2.3) },
- { level -> mapOf(HotmReward.MINING_SPEED to 5.0 * level) },
- ),
+ // Mining V3
+
NO_STONE_UNTURNED(
"No Stone Unturned",
50,
@@ -300,63 +291,87 @@ enum class HotmData(
{ level -> mapOf(HotmReward.UNKNOWN to 0.5 * level) },
),
- SUB_ZERO_MINING(
- "SubZero Mining",
+ STRONG_ARM(
+ "Strong Arm",
100,
{ level -> (level + 1.0).pow(2.3) },
- { level -> mapOf(HotmReward.MINING_FORTUNE to 1.0 * level) },
+ { level -> mapOf(HotmReward.MINING_SPEED to 5.0 * level) },
+ ),
+ STEADY_HAND(
+ "Steady Hand",
+ 100,
+ { level -> (level + 1.0).pow(2.6) },
+ { level -> mapOf(HotmReward.GEMSTONE_SPREAD to 0.1 * level) },
+ ),
+ WARM_HEART(
+ "Warm Heart",
+ 50,
+ { level -> (level + 1.0).pow(3.1) },
+ { level -> mapOf(HotmReward.COLD_RESISTANCE to 0.4 * level) },
),
SURVEYOR(
"Surveyor",
20,
- { level -> (level + 1.0).pow(4) },
+ { level -> (level + 1.0).pow(4.0) },
{ level -> mapOf(HotmReward.MINESHAFT_CHANCE to 0.75 * level) },
),
+ METAL_HEAD(
+ "Metal Head",
+ 20,
+ { level -> (level + 1.0).pow(4.0) },
+ { level -> mapOf(HotmReward.DWARVEN_METAL_FORTUNE to 5.0 * level) },
+ ),
+ RAGS_TO_RICHES(
+ "Rags to Riches",
+ 50,
+ { level -> (level + 1.0).pow(3.05) },
+ { level -> mapOf(HotmReward.MINING_FORTUNE to 4.0 * level) },
+ ),
EAGER_ADVENTURER(
"Eager Adventurer",
100,
{ level -> (level + 1.0).pow(2.3) },
- { level -> mapOf(HotmReward.MINING_SPEED to 2.0 * level) },
+ { level -> mapOf(HotmReward.MINING_SPEED to 4.0 * level) },
),
-
- DEAD_MANS_CHEST(
- "Dead Man's Chest",
+ CRYSTALLINE(
+ "Crystalline",
50,
- { level -> (level + 1.0).pow(3.2) },
- { level -> mapOf(HotmReward.UNKNOWN to 1.0 * level) },
+ { level -> (level + 1.0).pow(3.3) },
+ { level -> mapOf(HotmReward.UNKNOWN to 0.5 * level) },
),
-
GIFTS_FROM_THE_DEPARTED(
"Gifts from the Departed",
100,
{ level -> (level + 1.0).pow(2.45) },
{ level -> mapOf(HotmReward.UNKNOWN to 0.2 * level) },
),
-
- EXCAVATOR(
- "Excavator",
+ MINING_MASTER(
+ "Mining Master",
+ 10,
+ { level -> (level + 7.0).pow(5.0) },
+ { level -> mapOf(HotmReward.PRISTINE to 0.1 * level) },
+ ),
+ DEAD_MANS_CHEST(
+ "Dead Man's Chest",
50,
- { level -> (level + 1.0).pow(3) },
- { level -> mapOf(HotmReward.UNKNOWN to 0.5 * level) },
+ { level -> (level + 1.0).pow(3.2) },
+ { level -> mapOf(HotmReward.UNKNOWN to 1.0 * level) },
),
- RAGS_TO_RICHES(
- "Rags to Riches",
+ VANGUARD_SEEKER(
+ "Vanguard Seeker",
50,
- { level -> (level + 1.0).pow(3.05) },
- { level -> mapOf(HotmReward.MINING_FORTUNE to 2.0 * level) },
+ { level -> (level + 1.0).pow(3.1) },
+ { level -> mapOf(HotmReward.UNKNOWN to 1.0 * level) },
),
- KEEN_EYE("Keen Eye", 1, { null }, { emptyMap() }),
MINESHAFT_MAYHEM("Mineshaft Mayhem", 1, { null }, { emptyMap() }),
- FROZEN_SOLID("Frozen Solid", 1, { null }, { emptyMap() }),
GEMSTONE_INFUSION("Gemstone Infusion", 1, { null }, { emptyMap() }),
- HAZARDOUS_MINER("Hazardous Miner", 1, { null }, { emptyMap() }),
-
+ MINERS_BLESSING("Miner's Blessing", 1, { null }, { mapOf(HotmReward.MAGIC_FIND to 30.0) }),
;
private val guiNamePattern by patternGroup.pattern("perk.name.${name.lowercase().replace("_", "")}", "§.$guiName")
- val printName = name.allLettersFirstUppercase()
+ val printName get() = name.allLettersFirstUppercase()
/** Level which are actually paid with powder (does exclude [blueEgg])*/
var rawLevel: Int
@@ -367,15 +382,15 @@ enum class HotmData(
/** Level for which the effect that is present (considers [enabled] and [blueEgg])*/
val activeLevel: Int
- get() = if (enabled) effectivLevel else 0
+ get() = if (enabled) effectiveLevel else 0
/** Level that considering [blueEgg]*/
- val effectivLevel: Int get() = storage?.perks?.get(this.name)?.level?.plus(blueEgg()) ?: 0
+ val effectiveLevel: Int get() = storage?.perks?.get(this.name)?.level?.plus(blueEgg()) ?: 0
val isMaxLevel: Boolean
- get() = effectivLevel >= maxLevel // >= to account for +1 from Blue Cheese
+ get() = effectiveLevel >= maxLevel // >= to account for +1 from Blue Cheese
- private fun blueEgg() = if (this != PEAK_OF_THE_MOUNTAIN && maxLevel != 1 && HotmAPI.isBlueEggActive) 1 else 0
+ private fun blueEgg() = if (this != CORE_OF_THE_MOUNTAIN && maxLevel != 1 && HotmAPI.isBlueEggActive) 1 else 0
var enabled: Boolean
get() = storage?.perks?.get(this.name)?.enabled ?: false
@@ -406,7 +421,7 @@ enum class HotmData(
val storage get() = ProfileStorageData.profileSpecific?.mining?.hotmTree
- val abilities = listOf(PICKOBULUS, MINING_SPEED_BOOST, VEIN_SEEKER, MANIAC_MINER, HAZARDOUS_MINER, GEMSTONE_INFUSION)
+ val abilities = listOf(PICKOBULUS, MINING_SPEED_BOOST, MANIAC_MINER, GEMSTONE_INFUSION, ANOMALOUS_DESIRE, SHEER_FORCE)
private val inventoryPattern by patternGroup.pattern(
"inventory",
@@ -514,10 +529,10 @@ enum class HotmData(
HotmAPI.MayhemPerk.entries.forEach {
it.chatPattern
}
- (0..PEAK_OF_THE_MOUNTAIN.maxLevel).forEach { level ->
+ (0..CORE_OF_THE_MOUNTAIN.maxLevel).forEach { level ->
val map = mutableMapOf()
if (level >= 1) map.addOrPut(HotmReward.EXTRA_TOKENS, 1.0)
- if (level >= 2) map.addOrPut(HotmReward.EXTRA_FORGE_SLOTS, 1.0)
+ if (level >= 2) map.addOrPut(HotmReward.ABILITY_LEVEL, 1.0)
if (level >= 3) map.addOrPut(HotmReward.EXTRA_COMMISSION_SLOTS, 1.0)
if (level >= 4) map.addOrPut(HotmReward.MORE_BASE_MITHRIL_POWER, 1.0)
if (level >= 5) map.addOrPut(HotmReward.EXTRA_TOKENS, 1.0)
@@ -527,7 +542,7 @@ enum class HotmData(
if (level >= 9) map.addOrPut(HotmReward.MINESHAFT_CHANCE, 10.0)
if (level >= 10) map.addOrPut(HotmReward.EXTRA_TOKENS, 2.0)
- peakOfTheMountainPerks[level] = map
+ coreOfTheMountainPerks[level] = map
}
}
@@ -551,7 +566,7 @@ enum class HotmData(
val lore = item.getLore().takeIf { it.isNotEmpty() } ?: return
- if (entry != PEAK_OF_THE_MOUNTAIN && notUnlockedPattern.matches(lore.last())) {
+ if (entry != CORE_OF_THE_MOUNTAIN && notUnlockedPattern.matches(lore.last())) {
entry.rawLevel = 0
entry.enabled = false
entry.isUnlocked = false
@@ -574,7 +589,7 @@ enum class HotmData(
)
}
- if (entry == PEAK_OF_THE_MOUNTAIN) {
+ if (entry == CORE_OF_THE_MOUNTAIN) {
entry.enabled = entry.rawLevel != 0
return
}
@@ -663,7 +678,7 @@ enum class HotmData(
fun onScoreboardUpdate(event: ScoreboardUpdateEvent) {
if (!LorenzUtils.inSkyBlock) return
- event.scoreboard.matchFirst(ScoreboardPattern.powderPattern) {
+ ScoreboardPattern.powderPattern.firstMatcher(event.scoreboard) {
val type = HotmAPI.PowderType.entries.firstOrNull { it.displayName == group("type") } ?: return
val amount = group("amount").formatLong()
val difference = amount - type.getCurrent()
@@ -690,7 +705,7 @@ enum class HotmData(
DelayedRun.runNextTick {
InventoryUtils.getItemsInOpenChest().forEach { it.parse() }
abilities.filter { it.isUnlocked }.forEach {
- it.rawLevel = if (PEAK_OF_THE_MOUNTAIN.rawLevel >= 1) 2 else 1
+ it.rawLevel = if (CORE_OF_THE_MOUNTAIN.rawLevel >= 1) 2 else 1
}
}
}
@@ -791,7 +806,7 @@ enum class HotmData(
}
}
-private val peakOfTheMountainPerks = mutableMapOf>()
+private val coreOfTheMountainPerks = mutableMapOf>()
private val patternGroup = RepoPattern.group("mining.hotm")
@@ -801,7 +816,6 @@ enum class HotmReward {
MINING_WISDOM,
FORGE_TIME_DECREASE,
TITANIUM_CHANCE,
- DAILY_POWDER,
MORE_BASE_MITHRIL_POWER,
MORE_BASE_GEMSTONE_POWER,
MORE_BASE_GLACITE_POWER,
@@ -811,17 +825,26 @@ enum class HotmReward {
CHANCE_OF_TREASURE_CHEST,
LOCKS_OF_TREASURE_CHEST,
EXTRA_CHANCE_TRIGGER_RARE_OCCURRENCES,
- AVERAGE_BLOCK_BREAKS,
- CHANCE_EXTRA_XP_ORBS,
MINING_SPEED_BOOST,
ABILITY_DURATION,
ABILITY_RADIUS,
ABILITY_COOLDOWN,
- FOSSIL_DUST,
+ ABILITY_LEVEL,
MINESHAFT_CHANCE,
EXTRA_TOKENS,
- EXTRA_FORGE_SLOTS,
EXTRA_COMMISSION_SLOTS,
UNKNOWN,
- COLD_RESISTANCE
+ COLD_RESISTANCE,
+ MINING_SPREAD,
+ GEMSTONE_SPREAD,
+ ORE_FORTUNE,
+ BLOCK_FORTUNE,
+ GEMSTONE_FORTUNE,
+ DWARVEN_METAL_FORTUNE,
+ HEAT_RESISTANCE,
+ MAGIC_FIND,
+ PRISTINE,
+ FISHING_SPEED,
+ SEA_CREATURE_CHANCE,
+ BREAKING_POWER,
}
diff --git a/src/main/java/at/hannibal2/skyhanni/data/HypixelData.kt b/src/main/java/at/hannibal2/skyhanni/data/HypixelData.kt
index 0cd806f577c7..b48805ef5bf5 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/HypixelData.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/HypixelData.kt
@@ -13,6 +13,7 @@ import at.hannibal2.skyhanni.events.ProfileJoinEvent
import at.hannibal2.skyhanni.events.ScoreboardUpdateEvent
import at.hannibal2.skyhanni.events.WidgetUpdateEvent
import at.hannibal2.skyhanni.events.minecraft.ClientDisconnectEvent
+import at.hannibal2.skyhanni.events.skyblock.ScoreboardAreaChangeEvent
import at.hannibal2.skyhanni.features.bingo.BingoAPI
import at.hannibal2.skyhanni.features.dungeon.DungeonAPI
import at.hannibal2.skyhanni.features.rift.RiftAPI
@@ -319,8 +320,13 @@ object HypixelData {
loop@ for (line in ScoreboardData.sidebarLinesFormatted) {
skyblockAreaPattern.matchMatcher(line) {
val originalLocation = group("area").removeColor()
- skyBlockArea = LocationFixData.fixLocation(skyBlockIsland) ?: originalLocation
+ val area = LocationFixData.fixLocation(skyBlockIsland) ?: originalLocation
skyBlockAreaWithSymbol = line.trim()
+ if (area != skyBlockArea) {
+ val previousArea = skyBlockArea
+ skyBlockArea = area
+ ScoreboardAreaChangeEvent(area, previousArea).post()
+ }
break@loop
}
}
diff --git a/src/main/java/at/hannibal2/skyhanni/data/IslandGraphs.kt b/src/main/java/at/hannibal2/skyhanni/data/IslandGraphs.kt
index 02a065abe63a..1f8e45afb749 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/IslandGraphs.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/IslandGraphs.kt
@@ -1,6 +1,7 @@
package at.hannibal2.skyhanni.data
import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.api.event.HandleEvent
import at.hannibal2.skyhanni.data.model.Graph
import at.hannibal2.skyhanni.data.model.GraphNode
import at.hannibal2.skyhanni.data.model.findShortestPathAsGraphWithDistance
@@ -10,45 +11,53 @@ import at.hannibal2.skyhanni.events.LorenzRenderWorldEvent
import at.hannibal2.skyhanni.events.LorenzTickEvent
import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent
import at.hannibal2.skyhanni.events.RepositoryReloadEvent
+import at.hannibal2.skyhanni.events.skyblock.ScoreboardAreaChangeEvent
import at.hannibal2.skyhanni.features.misc.IslandAreas
import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule
import at.hannibal2.skyhanni.test.SkyHanniDebugsAndTests
+import at.hannibal2.skyhanni.utils.DelayedRun
import at.hannibal2.skyhanni.utils.LocationUtils
import at.hannibal2.skyhanni.utils.LocationUtils.canBeSeen
import at.hannibal2.skyhanni.utils.LocationUtils.distanceSqToPlayer
import at.hannibal2.skyhanni.utils.LocationUtils.distanceToPlayer
import at.hannibal2.skyhanni.utils.LorenzColor
import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland
import at.hannibal2.skyhanni.utils.LorenzVec
+import at.hannibal2.skyhanni.utils.RegexUtils.matches
import at.hannibal2.skyhanni.utils.RenderUtils.draw3DLine
import at.hannibal2.skyhanni.utils.RenderUtils.draw3DPathWithWaypoint
import at.hannibal2.skyhanni.utils.RenderUtils.drawWaypointFilled
+import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import java.awt.Color
import java.io.File
import kotlin.math.abs
+import kotlin.time.Duration.Companion.milliseconds
/**
* TODO
* benefits of every island graphs:
* global:
* NEU's fairy souls
- * point of interest
- * slayer area
- * NEU's NPC's
+ * slayer area (not all there yet)
+ * NEU's NPC's (auto acitvate when searching via neu)
* races (end, park, winter, dungeon hub)
* jump pads between servers
* ring of love/romeo juliet quest
* death location
+ * % of island discvovered (every node was most closest node at least once)
* hub:
* 12 starter NPC's
* diana
* farming:
- * pelt farming
+ * pelt farming area
* rift:
- * enigma souls
* eyes
* big quests
+ * montezuma souls
+ * blood effigies
+ * avoid area around enderman
* spider:
* relicts + throw spot
* dwarven mines:
@@ -56,7 +65,7 @@ import kotlin.math.abs
* commssion areas
* events: raffle, goblin slayer, donpieresso
* deep
- * path to the bottom
+ * path to the bottom (Rhys NPC)
* end
* golem spawn
* dragon death spot
@@ -65,8 +74,17 @@ import kotlin.math.abs
* area mini bosses
* daily quests
* intro tutorials with elle
+ * fishing spots
+ * mineshaft
+ * different types mapped out
+ * paths to ladder and possible corpse locations, and known corpse locations
*
- * graph todo:
+ * Additional global things:
+ * use custom graphs for your island/garden
+ * suggest using warp points if closer
+ * support cross island paths (have a list of all node names in all islands)
+ *
+ * Changes in graph editor:
* fix rename not using tick but input event we have (+ create the input event in the first place)
* toggle distance to node by node path lengh, instead of eye of sight lenght
* press test button again to enable "true test mode", with graph math and hiding other stuff
@@ -94,26 +112,73 @@ object IslandGraphs {
private var fastestPath: Graph? = null
private var condition: () -> Boolean = { true }
+ private var inGlaciteTunnels: Boolean? = null
+
+ private val patternGroup = RepoPattern.group("data.island.navigation")
+
+ /**
+ * REGEX-TEST: Dwarven Base Camp
+ * REGEX-TEST: Forge
+ * REGEX-TEST: Fossil Research Center
+ */
+ private val glaciteTunnelsPattern by patternGroup.pattern(
+ "glacitetunnels",
+ "(Glacite Tunnels|Dwarven Base Camp|Great Glacite Lake|Fossil Research Center)",
+ )
@SubscribeEvent
fun onRepoReload(event: RepositoryReloadEvent) {
if (!LorenzUtils.inSkyBlock) return
- reloadFromJson(LorenzUtils.skyBlockIsland)
+ loadIsland(LorenzUtils.skyBlockIsland)
}
@SubscribeEvent
fun onIslandChange(event: IslandChangeEvent) {
- reloadFromJson(event.newIsland)
+ if (currentIslandGraph != null) return
+ if (event.newIsland == IslandType.NONE) return
+ loadIsland(event.newIsland)
}
@SubscribeEvent
fun onWorldChange(event: LorenzWorldChangeEvent) {
+ currentIslandGraph = null
reset()
}
- private fun reloadFromJson(newIsland: IslandType) {
- val islandName = newIsland.name
+ fun isGlaciteTunnelsArea(area: String?): Boolean = glaciteTunnelsPattern.matches(area)
+
+ @HandleEvent
+ fun onAreaChange(event: ScoreboardAreaChangeEvent) {
+ if (!IslandType.DWARVEN_MINES.isInIsland()) {
+ inGlaciteTunnels = null
+ return
+ }
+
+ val now = isGlaciteTunnelsArea(LorenzUtils.skyBlockArea)
+ if (inGlaciteTunnels != now) {
+ inGlaciteTunnels = now
+ loadDwarvenMines()
+ }
+ }
+
+ private fun loadDwarvenMines() {
+ if (isGlaciteTunnelsArea(LorenzUtils.skyBlockArea)) {
+ reloadFromJson("GLACITE_TUNNELS")
+ } else {
+ reloadFromJson("DWARVEN_MINES")
+ }
+ }
+
+ private fun loadIsland(newIsland: IslandType) {
+ if (newIsland == IslandType.DWARVEN_MINES) {
+ loadDwarvenMines()
+ } else {
+ reloadFromJson(newIsland.name)
+ }
+ }
+
+ private fun reloadFromJson(islandName: String) {
val constant = "island_graphs/$islandName"
val name = "constants/$constant.json"
val jsonFile = File(SkyHanniMod.repo.repoLocation, name)
@@ -127,8 +192,16 @@ object IslandGraphs {
}
fun setNewGraph(graph: Graph) {
+ IslandAreas.display = null
reset()
currentIslandGraph = graph
+
+ // calling various update functions to make swtiching between deep caverns and glacite tunnels bareable
+ handleTick()
+ IslandAreas.noteMoved()
+ DelayedRun.runDelayed(150.milliseconds) {
+ IslandAreas.updatePosition()
+ }
}
private fun reset() {
@@ -141,6 +214,10 @@ object IslandGraphs {
@SubscribeEvent
fun onTick(event: LorenzTickEvent) {
if (!LorenzUtils.inSkyBlock) return
+ handleTick()
+ }
+
+ private fun handleTick() {
val prevClosed = closedNote
val graph = currentIslandGraph ?: return
@@ -287,8 +364,7 @@ object IslandGraphs {
val nodes = graph.nodes
val potentialSkip =
- nodes.lastOrNull { it.position.canBeSeen(maxSkipDistance, -1.0) && abs(it.position.y - playerY) <= 2 }
- ?: return null
+ nodes.lastOrNull { it.position.canBeSeen(maxSkipDistance, -1.0) && abs(it.position.y - playerY) <= 2 } ?: return null
val angleSkip = if (potentialSkip == nodes.first()) {
false
diff --git a/src/main/java/at/hannibal2/skyhanni/data/LocationFixData.kt b/src/main/java/at/hannibal2/skyhanni/data/LocationFixData.kt
index 129e1cd956ec..20dfbb615722 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/LocationFixData.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/LocationFixData.kt
@@ -11,9 +11,9 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
@SkyHanniModule
object LocationFixData {
- private var locationFixes = mutableListOf()
+ private var locationFixes = mutableMapOf>()
- class LocationFix(val island: IslandType, val area: AxisAlignedBB, val realLocation: String)
+ private data class LocationFix(val area: AxisAlignedBB, val realLocation: String)
// priority set to low so that IslandType can load their island names from repo earlier
@SubscribeEvent(priority = EventPriority.LOW)
@@ -26,11 +26,18 @@ object LocationFixData {
val area = fix.a.axisAlignedTo(fix.b)
val realLocation = fix.realLocation
- locationFixes.add(LocationFix(island, area, realLocation))
+ val list = locationFixes[island]
+
+ val locationFix = LocationFix(area, realLocation)
+
+ if (list == null) locationFixes[island] = listOf(locationFix)
+ else locationFixes[island] = list + locationFix
}
}
- fun fixLocation(skyBlockIsland: IslandType) = locationFixes
- .firstOrNull { skyBlockIsland == it.island && it.area.isPlayerInside() }
- ?.realLocation
+ fun fixLocation(skyBlockIsland: IslandType): String? =
+ locationFixes[skyBlockIsland]
+ ?.find { it.area.isPlayerInside() }
+ ?.realLocation
+
}
diff --git a/src/main/java/at/hannibal2/skyhanni/data/MayorAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/MayorAPI.kt
index b4fb7eaa2dc8..469c48489245 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/MayorAPI.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/MayorAPI.kt
@@ -16,7 +16,7 @@ import at.hannibal2.skyhanni.events.LorenzChatEvent
import at.hannibal2.skyhanni.events.SecondPassedEvent
import at.hannibal2.skyhanni.features.fame.ReminderUtils
import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule
-import at.hannibal2.skyhanni.utils.APIUtil
+import at.hannibal2.skyhanni.utils.APIUtils
import at.hannibal2.skyhanni.utils.ChatUtils
import at.hannibal2.skyhanni.utils.CollectionUtils.nextAfter
import at.hannibal2.skyhanni.utils.CollectionUtils.put
@@ -216,7 +216,7 @@ object MayorAPI {
SkyHanniMod.coroutineScope.launch {
val url = "https://api.hypixel.net/v2/resources/skyblock/election"
- val jsonObject = withContext(dispatcher) { APIUtil.getJSONResponse(url) }
+ val jsonObject = withContext(dispatcher) { APIUtils.getJSONResponse(url) }
rawMayorData = ConfigManager.gson.fromJson(jsonObject)
val data = rawMayorData ?: return@launch
val map = mutableMapOf()
diff --git a/src/main/java/at/hannibal2/skyhanni/data/Mayors.kt b/src/main/java/at/hannibal2/skyhanni/data/Mayors.kt
index 78647944c9a0..335648dc5116 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/Mayors.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/Mayors.kt
@@ -146,6 +146,7 @@ enum class Mayor(
fun Mayor.addPerks(perks: List) {
perks.forEach { it.isActive = false }
+ activePerks.forEach { it.isActive = false }
activePerks.clear()
for (perk in perks.filter { perks.contains(it) }) {
perk.isActive = true
diff --git a/src/main/java/at/hannibal2/skyhanni/data/MiningAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/MiningAPI.kt
index ecf90172dc79..9d635b1b9a22 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/MiningAPI.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/MiningAPI.kt
@@ -1,8 +1,10 @@
package at.hannibal2.skyhanni.data
+import at.hannibal2.skyhanni.api.event.HandleEvent
import at.hannibal2.skyhanni.events.BlockClickEvent
import at.hannibal2.skyhanni.events.ColdUpdateEvent
import at.hannibal2.skyhanni.events.DebugDataCollectEvent
+import at.hannibal2.skyhanni.events.IslandChangeEvent
import at.hannibal2.skyhanni.events.LorenzChatEvent
import at.hannibal2.skyhanni.events.LorenzTickEvent
import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent
@@ -11,8 +13,10 @@ import at.hannibal2.skyhanni.events.ScoreboardUpdateEvent
import at.hannibal2.skyhanni.events.ServerBlockChangeEvent
import at.hannibal2.skyhanni.events.mining.OreMinedEvent
import at.hannibal2.skyhanni.events.player.PlayerDeathEvent
+import at.hannibal2.skyhanni.events.skyblock.ScoreboardAreaChangeEvent
import at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardPattern
import at.hannibal2.skyhanni.features.mining.OreBlock
+import at.hannibal2.skyhanni.features.mining.isTitanium
import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule
import at.hannibal2.skyhanni.utils.CollectionUtils.countBy
import at.hannibal2.skyhanni.utils.LocationUtils.distanceToPlayer
@@ -20,7 +24,9 @@ import at.hannibal2.skyhanni.utils.LorenzUtils
import at.hannibal2.skyhanni.utils.LorenzUtils.inAnyIsland
import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland
import at.hannibal2.skyhanni.utils.LorenzVec
+import at.hannibal2.skyhanni.utils.NumberUtil.formatInt
import at.hannibal2.skyhanni.utils.RegexUtils.firstMatcher
+import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher
import at.hannibal2.skyhanni.utils.RegexUtils.matches
import at.hannibal2.skyhanni.utils.SimpleTimeMark
import at.hannibal2.skyhanni.utils.TimeUtils.format
@@ -37,27 +43,71 @@ import kotlin.time.Duration.Companion.seconds
object MiningAPI {
private val group = RepoPattern.group("data.miningapi")
- private val glaciteAreaPattern by group.pattern("area.glacite", "Glacite Tunnels|Glacite Lake")
+ private val glaciteAreaPattern by group.pattern("area.glacite", "Glacite Tunnels|Great Glacite Lake")
private val dwarvenBaseCampPattern by group.pattern("area.basecamp", "Dwarven Base Camp")
- // TODO rename to include suffix "pattern", add regex test
- private val coldReset by group.pattern(
+ // TODO add regex test
+ private val coldResetPattern by group.pattern(
"cold.reset",
- "§6The warmth of the campfire reduced your §r§b❄ Cold §r§6to §r§a0§r§6!|§c ☠ §r§7You froze to death§r§7.",
+ "§6The warmth of the campfire reduced your §r§b❄ Cold §r§6to §r§a0§r§6!|§c ☠ §r§7You froze to death§r§7\\.",
)
- private data class MinedBlock(val ore: OreBlock, var confirmed: Boolean, val time: SimpleTimeMark = SimpleTimeMark.now())
+ private val pickbobulusGroup = group.group("pickobulus")
+
+ /**
+ * REGEX-TEST: §aYou used your §r§6Pickobulus §r§aPickaxe Ability!
+ */
+
+ private val pickobulusUsePattern by pickbobulusGroup.pattern(
+ "use",
+ "§aYou used your §r§6Pickobulus §r§aPickaxe Ability!",
+ )
+
+ // TODO add regex test
+ private val pickobulusEndPattern by pickbobulusGroup.pattern(
+ "end",
+ "§7Your §r§aPickobulus §r§7destroyed §r§e(?[\\d,.]+) §r§7blocks!",
+ )
+
+ /**
+ * REGEX-TEST: §7Your §r§aPickobulus §r§7didn't destroy any blocks!
+ */
+ private val pickobulusFailPattern by pickbobulusGroup.pattern(
+ "fail",
+ "§7Your §r§aPickobulus §r§7didn't destroy any blocks!"
+ )
+
+ private data class MinedBlock(val ore: OreBlock, var confirmed: Boolean) {
+ val time: SimpleTimeMark = SimpleTimeMark.now()
+ }
+
+ // normal mining
+ private val recentClickedBlocks = ConcurrentSet>()
+ private val surroundingMinedBlocks = ConcurrentLinkedQueue>()
private var lastInitSound = SimpleTimeMark.farPast()
- private var waitingForInitBlock = false
- private var waitingForInitBlockPos: LorenzVec? = null
+ private var initBlockPos: LorenzVec? = null
private var waitingForInitSound = true
private var waitingForEffMinerSound = false
private var waitingForEffMinerBlock = false
+ // pickobulus
+ private var lastPickobulusUse = SimpleTimeMark.farPast()
+ private var lastPickobulusExplosion = SimpleTimeMark.farPast()
+ private var pickobulusExplosionPos: LorenzVec? = null
+ private val pickobulusMinedBlocks = ConcurrentLinkedQueue>()
+
+ private val pickobulusActive get() = lastPickobulusUse.passedSince() < 2.seconds
+
+ private var pickobulusWaitingForSound = false
+ private var pickobulusWaitingForBlock = false
+
+ // oreblock data
var inGlacite = false
+ var inTunnels = false
+ var inMineshaft = false
var inDwarvenMines = false
var inCrystalHollows = false
var inCrimsonIsle = false
@@ -65,18 +115,17 @@ object MiningAPI {
var inSpidersDen = false
var currentAreaOreBlocks = setOf()
+ private set
- private var lastSkyblockArea: String? = null
-
- private val recentClickedBlocks = ConcurrentSet>()
- private val surroundingMinedBlocks = ConcurrentLinkedQueue>()
- private val allowedSoundNames = listOf("dig.glass", "dig.stone", "dig.gravel", "dig.cloth", "random.orb")
+ private val allowedSoundNames = setOf("dig.glass", "dig.stone", "dig.gravel", "dig.cloth", "random.orb")
var cold: Int = 0
private set
var lastColdUpdate = SimpleTimeMark.farPast()
+ private set
var lastColdReset = SimpleTimeMark.farPast()
+ private set
fun inGlaciteArea() = inGlacialTunnels() || IslandType.MINESHAFT.isInIsland()
@@ -116,6 +165,7 @@ object MiningAPI {
fun onBlockClick(event: BlockClickEvent) {
if (!inCustomMiningIsland()) return
if (event.clickType != ClickType.LEFT_CLICK) return
+ //println(event.getBlockState.properties)
if (OreBlock.getByStateOrNull(event.getBlockState) == null) return
recentClickedBlocks += event.position to SimpleTimeMark.now()
}
@@ -123,10 +173,29 @@ object MiningAPI {
@SubscribeEvent
fun onChat(event: LorenzChatEvent) {
if (!inColdIsland()) return
- if (coldReset.matches(event.message)) {
+ if (coldResetPattern.matches(event.message)) {
updateCold(0)
lastColdReset = SimpleTimeMark.now()
+ return
}
+ if (pickobulusUsePattern.matches(event.message)) {
+ lastPickobulusUse = SimpleTimeMark.now()
+ return
+ }
+ if (pickobulusFailPattern.matches(event.message)) {
+ resetPickobulusEvent()
+ pickobulusMinedBlocks.clear()
+ return
+ }
+ pickobulusEndPattern.matchMatcher(event.message) {
+ val amount = group("amount").formatInt()
+ resetPickobulusEvent()
+ val blocks = pickobulusMinedBlocks.take(amount).countBy { it.second }
+ if (blocks.isNotEmpty()) OreMinedEvent(null, blocks).post()
+ pickobulusMinedBlocks.clear()
+ return
+ }
+
}
@SubscribeEvent
@@ -140,14 +209,25 @@ object MiningAPI {
@SubscribeEvent
fun onPlaySound(event: PlaySoundEvent) {
if (!inCustomMiningIsland()) return
+ if (event.soundName == "random.explode" && lastPickobulusUse.passedSince() < 5.seconds) {
+ lastPickobulusExplosion = SimpleTimeMark.now()
+ pickobulusExplosionPos = event.location
+ pickobulusWaitingForSound = true
+ return
+ }
if (event.soundName !in allowedSoundNames) return
+ if (pickobulusActive && pickobulusWaitingForSound) {
+ pickobulusWaitingForSound = false
+ pickobulusWaitingForBlock = true
+ return
+ }
if (waitingForInitSound) {
if (event.soundName != "random.orb" && event.pitch == 0.7936508f) {
val pos = event.location.roundLocationToBlock()
if (recentClickedBlocks.none { it.first == pos }) return
waitingForInitSound = false
- waitingForInitBlock = true
- waitingForInitBlockPos = event.location.roundLocationToBlock()
+ waitingForEffMinerBlock = true
+ initBlockPos = event.location.roundLocationToBlock()
lastInitSound = SimpleTimeMark.now()
}
return
@@ -164,21 +244,35 @@ object MiningAPI {
@SubscribeEvent
fun onBlockChange(event: ServerBlockChangeEvent) {
if (!inCustomMiningIsland()) return
- if (event.newState.block.let { it != Blocks.air && it != Blocks.bedrock }) return
- if (event.oldState.block.let { it == Blocks.air || it == Blocks.bedrock }) return
- if (event.oldState.block == Blocks.air) return
+ val oldState = event.oldState
+ val newState = event.newState
+ val oldBlock = oldState.block
+ val newBlock = newState.block
+
+ if (oldState == newState) return
+ if (oldBlock == Blocks.air || oldBlock == Blocks.bedrock) return
+ if (newBlock != Blocks.air && newBlock != Blocks.bedrock && !isTitanium(newState)) return
+
val pos = event.location
- if (pos.distanceToPlayer() > 7) return
+ if (pickobulusActive && pickobulusWaitingForBlock) {
+ val explosionPos = pickobulusExplosionPos ?: return
+ if (explosionPos.distance(pos) > 15) return
+ val ore = OreBlock.getByStateOrNull(oldState) ?: return
+ if (pickobulusMinedBlocks.any { it.first == pos }) return
+ pickobulusMinedBlocks += pos to ore
+ pickobulusWaitingForBlock = false
+ pickobulusWaitingForSound = true
+ return
+ }
if (lastInitSound.passedSince() > 100.milliseconds) return
+ if (pos.distanceToPlayer() > 7) return
- val ore = OreBlock.getByStateOrNull(event.oldState) ?: return
+ val ore = OreBlock.getByStateOrNull(oldState) ?: return
- if (waitingForInitBlock) {
- if (waitingForInitBlockPos != pos) return
- waitingForInitBlock = false
+ if (initBlockPos == pos) {
surroundingMinedBlocks += MinedBlock(ore, true) to pos
- waitingForEffMinerBlock = true
+ runEvent()
return
}
if (waitingForEffMinerBlock) {
@@ -193,19 +287,33 @@ object MiningAPI {
@SubscribeEvent
fun onTick(event: LorenzTickEvent) {
if (!inCustomMiningIsland()) return
-
- if (LorenzUtils.lastWorldSwitch.passedSince() < 4.seconds) return
- updateLocation()
-
if (currentAreaOreBlocks.isEmpty()) return
// if somehow you take more than 20 seconds to mine a single block, congrats
recentClickedBlocks.removeIf { it.second.passedSince() >= 20.seconds }
surroundingMinedBlocks.removeIf { it.first.time.passedSince() >= 20.seconds }
- if (waitingForInitSound) return
- if (lastInitSound.passedSince() < 200.milliseconds) return
+ if (!waitingForInitSound && lastInitSound.passedSince() > 200.milliseconds) {
+ resetOreEvent()
+ }
+ if (!lastPickobulusUse.isFarPast() && lastPickobulusUse.passedSince() > 5.seconds) {
+ resetPickobulusEvent()
+ pickobulusMinedBlocks.clear()
+ }
+ }
+
+ @HandleEvent
+ fun onAreaChange(event: ScoreboardAreaChangeEvent) {
+ if (!inCustomMiningIsland()) return
+ updateLocation()
+ }
+ @SubscribeEvent
+ fun onIslandChange(event: IslandChangeEvent) {
+ updateLocation()
+ }
+
+ private fun runEvent() {
resetOreEvent()
if (surroundingMinedBlocks.isEmpty()) return
@@ -230,19 +338,28 @@ object MiningAPI {
lastColdReset = SimpleTimeMark.now()
recentClickedBlocks.clear()
surroundingMinedBlocks.clear()
+ pickobulusMinedBlocks.clear()
currentAreaOreBlocks = setOf()
resetOreEvent()
+ resetPickobulusEvent()
}
private fun resetOreEvent() {
lastInitSound = SimpleTimeMark.farPast()
waitingForInitSound = true
- waitingForInitBlock = false
- waitingForInitBlockPos = null
+ initBlockPos = null
waitingForEffMinerSound = false
waitingForEffMinerBlock = false
}
+ private fun resetPickobulusEvent() {
+ lastPickobulusUse = SimpleTimeMark.farPast()
+ lastPickobulusExplosion = SimpleTimeMark.farPast()
+ pickobulusExplosionPos = null
+ pickobulusWaitingForSound = false
+ pickobulusWaitingForBlock = false
+ }
+
@SubscribeEvent
fun onDebugDataCollect(event: DebugDataCollectEvent) {
event.title("Mining API")
@@ -258,8 +375,7 @@ object MiningAPI {
add("lastInitSound: ${lastInitSound.passedSince().format()}")
}
add("waitingForInitSound: $waitingForInitSound")
- add("waitingForInitBlock: $waitingForInitBlock")
- add("waitingForInitBlockPos: $waitingForInitBlockPos")
+ add("waitingForInitBlockPos: $initBlockPos")
add("waitingForEffMinerSound: $waitingForEffMinerSound")
add("waitingForEffMinerBlock: $waitingForEffMinerBlock")
add("recentlyClickedBlocks: ${recentClickedBlocks.joinToString { "(${it.first.toCleanString()}" }}")
@@ -275,12 +391,9 @@ object MiningAPI {
}
private fun updateLocation() {
- val currentArea = LorenzUtils.skyBlockArea
- // TODO add area change event with HypixelData.skyBlockArea instead
- if (currentArea == lastSkyblockArea) return
- lastSkyblockArea = currentArea
-
inGlacite = inGlaciteArea()
+ inTunnels = inGlacialTunnels()
+ inMineshaft = inMineshaft()
inDwarvenMines = inRegularDwarven()
inCrystalHollows = inCrystalHollows()
inCrimsonIsle = IslandType.CRIMSON_ISLE.isInIsland()
diff --git a/src/main/java/at/hannibal2/skyhanni/data/OtherPlayersSlayerAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/OtherPlayersSlayerAPI.kt
new file mode 100644
index 000000000000..0401746c4edb
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/data/OtherPlayersSlayerAPI.kt
@@ -0,0 +1,36 @@
+package at.hannibal2.skyhanni.data
+
+import at.hannibal2.skyhanni.data.mob.Mob
+import at.hannibal2.skyhanni.events.MobEvent
+import at.hannibal2.skyhanni.events.entity.slayer.SlayerDeathEvent
+import at.hannibal2.skyhanni.features.slayer.SlayerType
+import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule
+import at.hannibal2.skyhanni.test.command.ErrorManager
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+
+@SkyHanniModule
+object OtherPlayersSlayerAPI {
+
+ @SubscribeEvent
+ fun onMobDespawn(event: MobEvent.DeSpawn.SkyblockMob) {
+ val mob = event.mob
+
+ // no death, rather despawn because too far away
+ if (mob.baseEntity.health != 0f) return
+
+ if (mob.mobType != Mob.Type.SLAYER) return
+
+ val owner = mob.owner?.ownerName
+ val tier = mob.levelOrTier
+ val name = mob.name
+ val slayerType = SlayerType.getByName(name) ?: run {
+ ErrorManager.logErrorStateWithData(
+ "Unknown slayer type found", "unknown slayer",
+ "name" to name,
+ )
+ return
+ }
+
+ SlayerDeathEvent(slayerType, tier, owner).post()
+ }
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/data/QuiverAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/QuiverAPI.kt
index 88daf40b9520..2f516610ca51 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/QuiverAPI.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/QuiverAPI.kt
@@ -16,10 +16,10 @@ import at.hannibal2.skyhanni.utils.ItemUtils.getInternalNameOrNull
import at.hannibal2.skyhanni.utils.ItemUtils.getItemCategoryOrNull
import at.hannibal2.skyhanni.utils.ItemUtils.getLore
import at.hannibal2.skyhanni.utils.LorenzUtils
-import at.hannibal2.skyhanni.utils.LorenzUtils.round
import at.hannibal2.skyhanni.utils.NEUInternalName
import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName
import at.hannibal2.skyhanni.utils.NumberUtil.formatInt
+import at.hannibal2.skyhanni.utils.NumberUtil.roundTo
import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher
import at.hannibal2.skyhanni.utils.RegexUtils.matches
import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getExtraAttributes
@@ -236,7 +236,7 @@ object QuiverAPI {
}
}
- fun Int.asArrowPercentage() = ((this.toFloat() / MAX_ARROW_AMOUNT) * 100).round(1)
+ fun Int.asArrowPercentage() = ((this.toFloat() / MAX_ARROW_AMOUNT) * 100).roundTo(1)
fun hasBowInInventory() = hasBow
diff --git a/src/main/java/at/hannibal2/skyhanni/data/ScoreboardData.kt b/src/main/java/at/hannibal2/skyhanni/data/ScoreboardData.kt
index 378fe03c6953..a8cafcf3d981 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/ScoreboardData.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/ScoreboardData.kt
@@ -51,16 +51,13 @@ object ScoreboardData {
val lastColor = start.lastColorCode() ?: ""
// Generate the list of color suffixes
- val colorSuffixes = generateSequence(lastColor) { it.dropLast(2) }
- .takeWhile { it.isNotEmpty() }
- .toMutableList()
+ val colorSuffixes = lastColor.chunked(2).toMutableList()
// Iterate through the colorSuffixes to remove matching prefixes from 'end'
for (suffix in colorSuffixes.toList()) {
if (end.startsWith(suffix)) {
end = end.removePrefix(suffix)
colorSuffixes.remove(suffix)
- break
}
}
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 29a16944c3d3..13044b7c3151 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/bazaar/HypixelBazaarFetcher.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/bazaar/HypixelBazaarFetcher.kt
@@ -6,7 +6,7 @@ import at.hannibal2.skyhanni.events.LorenzTickEvent
import at.hannibal2.skyhanni.features.inventory.bazaar.BazaarData
import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule
import at.hannibal2.skyhanni.test.command.ErrorManager
-import at.hannibal2.skyhanni.utils.APIUtil
+import at.hannibal2.skyhanni.utils.APIUtils
import at.hannibal2.skyhanni.utils.ChatUtils
import at.hannibal2.skyhanni.utils.ItemUtils.itemName
import at.hannibal2.skyhanni.utils.LorenzUtils
@@ -46,7 +46,7 @@ object HypixelBazaarFetcher {
val fetchType = if (nextFetchIsManual) "manual" else "automatic"
nextFetchIsManual = false
try {
- val jsonResponse = withContext(Dispatchers.IO) { APIUtil.getJSONResponse(URL) }.asJsonObject
+ val jsonResponse = withContext(Dispatchers.IO) { APIUtils.getJSONResponse(URL) }.asJsonObject
val response = ConfigManager.gson.fromJson(jsonResponse)
if (response.success) {
latestProductInformation = process(response.products)
diff --git a/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/CarryTrackerJson.kt b/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/CarryTrackerJson.kt
new file mode 100644
index 000000000000..1819b36b9517
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/CarryTrackerJson.kt
@@ -0,0 +1,8 @@
+package at.hannibal2.skyhanni.data.jsonobjects.repo
+
+import com.google.gson.annotations.Expose
+import com.google.gson.annotations.SerializedName
+
+data class CarryTrackerJson(
+ @Expose @SerializedName("slayer_names") val slayerNames: Map>,
+)
diff --git a/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/HoppityEggLocationsJson.kt b/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/HoppityEggLocationsJson.kt
index 4ad81b06a663..ead4eb83c298 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/HoppityEggLocationsJson.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/HoppityEggLocationsJson.kt
@@ -23,6 +23,13 @@ data class HoppityEggLocationsJson(
@Expose val maxRabbits: Int,
@Expose val maxPrestige: Int,
@Expose val chocolateMilestones: TreeSet,
+ @Expose val chocolateShopMilestones: List,
+ @Expose val chocolateFactoryMilestones: List,
@Expose val apiEggLocations: Map>,
@Expose val specialRabbits: List,
)
+
+data class MilestoneJson(
+ @Expose val amount: Long,
+ @Expose val rabbit: String,
+)
diff --git a/src/main/java/at/hannibal2/skyhanni/data/model/Graph.kt b/src/main/java/at/hannibal2/skyhanni/data/model/Graph.kt
index 8c63be891fb3..bc4be57a16d4 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/model/Graph.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/model/Graph.kt
@@ -1,7 +1,7 @@
package at.hannibal2.skyhanni.data.model
-import at.hannibal2.skyhanni.utils.LorenzUtils.round
import at.hannibal2.skyhanni.utils.LorenzVec
+import at.hannibal2.skyhanni.utils.NumberUtil.roundTo
import at.hannibal2.skyhanni.utils.json.SkyHanniTypeAdapters.registerTypeAdapter
import at.hannibal2.skyhanni.utils.json.fromJson
import com.google.gson.GsonBuilder
@@ -10,6 +10,7 @@ import com.google.gson.annotations.Expose
import com.google.gson.stream.JsonToken
import java.util.PriorityQueue
+// TODO: This class should be disambiguated into a NodePath and a Graph class
@JvmInline
value class Graph(
@Expose val nodes: List,
@@ -49,7 +50,7 @@ value class Graph(
out.name("Name").value(it)
}
- it.tagNames?.takeIf { it.isNotEmpty() }?.let {
+ it.tagNames.takeIf { list -> list.isNotEmpty() }?.let {
out.name("Tags")
out.beginArray()
for (tagName in it) {
@@ -62,7 +63,7 @@ value class Graph(
out.beginObject()
for ((node, weight) in it.neighbours) {
val id = node.id.toString()
- out.name(id).value(weight.round(2))
+ out.name(id).value(weight.roundTo(2))
}
out.endObject()
@@ -79,8 +80,8 @@ value class Graph(
reader.beginObject()
var position: LorenzVec? = null
var name: String? = null
- var tags: List? = null
- var neighbors = mutableListOf>()
+ var tags = emptyList()
+ val neighbors = mutableListOf>()
while (reader.hasNext()) {
if (reader.peek() != JsonToken.NAME) {
reader.skipValue()
@@ -140,10 +141,10 @@ value class Graph(
}
// The node object that gets parsed from/to json
-class GraphNode(val id: Int, val position: LorenzVec, val name: String? = null, val tagNames: List? = null) {
+class GraphNode(val id: Int, val position: LorenzVec, val name: String? = null, val tagNames: List = emptyList()) {
val tags: List by lazy {
- tagNames?.mapNotNull { GraphNodeTag.byId(it) } ?: emptyList()
+ tagNames.mapNotNull { GraphNodeTag.byId(it) }
}
/** Keys are the neighbours and value the edge weight (e.g. Distance) */
@@ -167,18 +168,50 @@ class GraphNode(val id: Int, val position: LorenzVec, val name: String? = null,
fun Graph.findShortestPathAsGraph(start: GraphNode, end: GraphNode): Graph = this.findShortestPathAsGraphWithDistance(start, end).first
-fun Graph.findShortestPathAsGraphWithDistance(start: GraphNode, end: GraphNode): Pair {
+data class DijkstraTree(
+ val origin: GraphNode,
+ /**
+ * A map of distances between the [origin] and each node in a graph. This distance map is only accurate for nodes closer to the
+ * origin than the [lastVisitedNode]. In case there is no early bailout, this map will be accurate for all nodes in the graph.
+ */
+ val distances: Map,
+ /**
+ * A map of nodes to the neighbouring node that is the quickest path towards the origin (the neighbouring node that has the lowest value
+ * in [distances])
+ */
+ val towardsOrigin: Map,
+ /**
+ * This is either the furthest away node in the graph, or the node that was bailed out on early because it fulfilled the search
+ * condition. In case the search condition matches nothing, this will *still* be the furthest away node, so an additional check might be
+ * necessary.
+ */
+ val lastVisitedNode: GraphNode,
+)
+
+/**
+ * Find a tree of distances to the [start] node using dijkstra's algorithm.
+ */
+fun Graph.findDijkstraDistances(
+ start: GraphNode,
+ /**
+ * Bail out early before collecting all the distances to all nodes in the graph. This will not collect valid distance data for *all*
+ * nodes for which bailout matches, but only the closest one.
+ */
+ bailout: (GraphNode) -> Boolean,
+): DijkstraTree {
val distances = mutableMapOf()
val previous = mutableMapOf()
val visited = mutableSetOf()
val queue = PriorityQueue(compareBy { distances.getOrDefault(it, Double.MAX_VALUE) })
+ var lastVisitedNode: GraphNode = start
distances[start] = 0.0
queue.add(start)
while (queue.isNotEmpty()) {
val current = queue.poll()
- if (current == end) break
+ lastVisitedNode = current
+ if (bailout(current)) break
visited.add(current)
@@ -194,16 +227,34 @@ fun Graph.findShortestPathAsGraphWithDistance(start: GraphNode, end: GraphNode):
}
}
- return Graph(
- buildList {
- var current = end
- while (current != start) {
- add(current)
- current = previous[current] ?: return Graph(emptyList()) to 0.0
- }
- add(start)
- }.reversed(),
- ) to distances[end]!!
+ return DijkstraTree(
+ start,
+ distances,
+ previous,
+ lastVisitedNode,
+ )
+}
+
+fun Graph.findAllShortestDistances(start: GraphNode): DijkstraTree {
+ return findDijkstraDistances(start) { false }
+}
+
+fun DijkstraTree.findPathToDestination(end: GraphNode): Pair {
+ val distances = this
+ val reversePath = buildList {
+ var current = end
+ while (true) {
+ add(current)
+ if (current == distances.origin) break
+ current = distances.towardsOrigin[current] ?: return Graph(emptyList()) to 0.0
+ }
+ }
+ return Graph(reversePath.reversed()) to distances.distances[end]!!
+}
+
+fun Graph.findShortestPathAsGraphWithDistance(start: GraphNode, end: GraphNode): Pair {
+ val distances = findDijkstraDistances(start) { it == end }
+ return distances.findPathToDestination(end)
}
fun Graph.findShortestPath(start: GraphNode, end: GraphNode): List = this.findShortestPathAsGraph(start, end).toPositionsList()
diff --git a/src/main/java/at/hannibal2/skyhanni/data/model/GraphNodeTag.kt b/src/main/java/at/hannibal2/skyhanni/data/model/GraphNodeTag.kt
index a7349801324a..6bf00edafcf6 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/model/GraphNodeTag.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/model/GraphNodeTag.kt
@@ -1,46 +1,87 @@
package at.hannibal2.skyhanni.data.model
+import at.hannibal2.skyhanni.data.IslandType
import at.hannibal2.skyhanni.utils.LorenzColor
-enum class GraphNodeTag(val internalName: String?, val color: LorenzColor, val cleanName: String, val description: String) {
+enum class GraphNodeTag(
+ val internalName: String,
+ val color: LorenzColor,
+ val cleanName: String,
+ val description: String,
+ val onlyIsland: IslandType? = null,
+) {
DEV("dev", LorenzColor.WHITE, "Dev", "Intentionally marked as dev."), // E.g. Spawn points, todos, etc
// Everywhere
- NPC("npc", LorenzColor.YELLOW, "NPC", "A NPC entity."), // also take from neu repo
+ NPC("npc", LorenzColor.YELLOW, "NPC", "A NPC to talk to."), // also take from neu repo
AREA("area", LorenzColor.DARK_GREEN, "Area", "A big SkyBlock area."),
SMALL_AREA("small_area", LorenzColor.GREEN, "Small Area", "A small SkyBlock area, e.g. a house."),
- POI("poi", LorenzColor.WHITE, "PoI", "Point of interest."),
- LAUNCH_PAD("launch", LorenzColor.WHITE, "Launch Pad", "Slime blocks sending you to another server."),
+ POI("poi", LorenzColor.WHITE, "Point of Interest", "A relevant spot or a landmark on the map."),
+ // LAUNCH_PAD("launch", LorenzColor.WHITE, "Launch Pad", "Slime blocks sending you to another server."),
+ TELEPORT("teleport", LorenzColor.BLUE, "Teleport", "A spot from/to teleport."),
// on multiple islands
- ROMEO("romeo", LorenzColor.WHITE, "Romeo & Juliette Quest", "Blocks related to the Romeo and Juliette/Ring of Love quest line."),
+ ROMEO("romeo", LorenzColor.WHITE, "Romeo & Juliette Quest", "Spots related to the Romeo and Juliette/Ring of Love quest line."),
RACE("race", LorenzColor.WHITE, "Race Start/Stop", "A race start or stop point."),
- SLAYER("slayer", LorenzColor.WHITE, "Slayer", "A Slayer area"),
+ SLAYER("slayer", LorenzColor.RED, "Slayer", "A Slayer area."),
+ HOPPITY("hoppity", LorenzColor.AQUA, "Hoppity Egg", "An egg location in Hoppity's Hunt."),
+ GRIND_MOBS("grind_mobs", LorenzColor.RED, "Mob Spawn Area", "An area where mobs spawn that can be killed."),
+ GRIND_ORES("grind_ores", LorenzColor.DARK_AQUA, "Ore Vein", "A regenerating ore vein that can be mined."),
+ GRIND_CROPS("grind_crops", LorenzColor.DARK_GREEN, "Crop Area", "An area where crops grow that can be farmed."),
// hoppity
// Hub
- HUB_12_STARTER("starter_npc", LorenzColor.WHITE, "Starter NPC", "One of the 12 starter NPC's you need to talk to."),
+ HUB_12_STARTER(
+ "starter_npc", LorenzColor.WHITE, "Starter NPC", "One of the 12 starter NPC's you need to talk to.",
+ onlyIsland = IslandType.HUB,
+ ),
// diana
// Farming Islands: Pelts
- FARMING_CROP("farming_crop", LorenzColor.WHITE, "Farming Crop", "A spot where you can break crops on farming islands."),
+// FARMING_CROP("farming_crop", LorenzColor.WHITE, "Farming Crop", "A spot where you can break crops on farming islands."),
// Rift
- RIFT_ENIGMA("rift_enigma", LorenzColor.DARK_PURPLE, "Enigma Soul", "Enigma Souls in the rift."),
- RIFT_EYE("rift_eye", LorenzColor.DARK_RED, "Eye", "An Eye in the rift to teleport to."),
+ RIFT_ENIGMA("rift_enigma", LorenzColor.DARK_PURPLE, "Enigma Soul", "Enigma Souls in the Rift.", onlyIsland = IslandType.THE_RIFT),
+ RIFT_EYE("rift_eye", LorenzColor.DARK_RED, "Rift Eye", "An Eye in the Rift to teleport to.", onlyIsland = IslandType.THE_RIFT),
+ RIFT_MONTEZUMA(
+ "rift_montezuma",
+ LorenzColor.GRAY,
+ "Montezuma Soul Piece",
+ "A piece of the Montezuma Soul.",
+ onlyIsland = IslandType.THE_RIFT,
+ ),
+ RIFT_EFFIGY("rift_effigy", LorenzColor.RED, "Blood Effigies", "Locations of the Blood Effigies.", onlyIsland = IslandType.THE_RIFT),
// Spider's Den
- SPIDER_RELIC("SPIDER_RELIC", LorenzColor.DARK_PURPLE, "Relic", "An relic in the Spider's Den."),
+ SPIDER_RELIC(
+ "SPIDER_RELIC",
+ LorenzColor.DARK_PURPLE,
+ "Spider's Relic",
+ "An relic in the Spider's Den.",
+ onlyIsland = IslandType.SPIDER_DEN,
+ ),
// Dwarven Mines
- MINES_EMISSARY("mines_emissary", LorenzColor.GOLD, "Emissary", "A Emissary from the king."),
+ MINES_EMISSARY("mines_emissary", LorenzColor.GOLD, "Mines Emissary", "An Emissary to the king.", onlyIsland = IslandType.DWARVEN_MINES),
// commission areas
+ // Crimson Isles
+ CRIMSON_MINIBOSS(
+ "crimson_miniboss",
+ LorenzColor.RED,
+ "Crimson Miniboss",
+ "A Miniboss in the Crimson Isle.",
+ onlyIsland = IslandType.CRIMSON_ISLE,
+ ),
+
+ // The End
+ END_GOLEM("end_golem", LorenzColor.RED, "Golem Spawn", "A spot where the golem can spawn in the End.", onlyIsland = IslandType.THE_END),
+
;
val displayName: String = color.getChatColor() + cleanName
companion object {
- fun byId(internalName: String?): GraphNodeTag? = values().firstOrNull { it.internalName == internalName }
+ fun byId(internalName: String?): GraphNodeTag? = entries.firstOrNull { it.internalName == internalName }
}
}
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 6fd65778ecfb..f31c95958659 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/model/SkyblockStat.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/model/SkyblockStat.kt
@@ -43,8 +43,18 @@ enum class SkyblockStat(val icon: String) {
PRISTINE("§5✧"),
FORAGING_FORTUNE("§☘"),
FARMING_FORTUNE("§6☘"),
+
+ MINING_SPREAD("§e▚"),
MINING_FORTUNE("§6☘"),
- FEAR("§a☠")
+ ORE_FORTUNE("§6☘"),
+ DWARVEN_METAL_FORTUNE("§6☘"),
+ BLOCK_FORTUNE("§6☘"),
+ GEMSTONE_FORTUNE("§6☘"),
+
+ FEAR("§a☠"),
+ HEAT_RESISTANCE("§c♨"),
+
+ UNKNOWN("§c?")
;
val capitalizedName = name.lowercase().allLettersFirstUppercase()
@@ -57,6 +67,10 @@ enum class SkyblockStat(val icon: String) {
val fontSizeOfLargestIcon by lazy {
entries.maxOf { Minecraft.getMinecraft().fontRendererObj.getStringWidth(it.icon) } + 1
}
+
+ fun getValueOrNull(string: String): SkyblockStat? = entries.firstOrNull { it.name == string }
+
+ fun getValue(string: String): SkyblockStat = getValueOrNull(string) ?: UNKNOWN
}
}
diff --git a/src/main/java/at/hannibal2/skyhanni/data/model/TextInput.kt b/src/main/java/at/hannibal2/skyhanni/data/model/TextInput.kt
index 0646b884cdec..15fcbe8a9a62 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/model/TextInput.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/model/TextInput.kt
@@ -111,7 +111,7 @@ class TextInput {
}
if (KeyboardManager.isPastingKeysDown()) {
runBlocking {
- textBox = OSUtils.readFromClipboard() ?: return@runBlocking
+ textBox = OSUtils.readFromClipboard()?.take(2024) ?: return@runBlocking
updated()
}
return
diff --git a/src/main/java/at/hannibal2/skyhanni/events/InventoryFullyOpenedEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/InventoryFullyOpenedEvent.kt
index d786445fbf5e..5374b95d3c2e 100644
--- a/src/main/java/at/hannibal2/skyhanni/events/InventoryFullyOpenedEvent.kt
+++ b/src/main/java/at/hannibal2/skyhanni/events/InventoryFullyOpenedEvent.kt
@@ -26,6 +26,17 @@ open class InventoryOpenEvent(private val inventory: OtherInventoryData.Inventor
val fullyOpenedOnce: Boolean get() = inventory.fullyOpenedOnce
}
+/**
+ * This event is getting fired after every slot in the newly opened inventory has item data.
+ *
+ * New inventory data gets first sent as an empty inventory from the server.
+ * Item stack slot information is sent afterwards, sometimes with a short delay.
+ *
+ * This approach is faster than to wait a fix duration after the inventory open packet is detected.
+ *
+ * Since this logic only works via packets, and the player inventory (pressing E) is client side,
+ * this event does not get fired when opening the invenotory via pressingE.
+ */
class InventoryFullyOpenedEvent(inventory: OtherInventoryData.Inventory) : InventoryOpenEvent(inventory)
class InventoryUpdatedEvent(inventory: OtherInventoryData.Inventory) : InventoryOpenEvent(inventory)
diff --git a/src/main/java/at/hannibal2/skyhanni/events/LorenzEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/LorenzEvent.kt
index c895b1058d7c..4a294a6779ca 100644
--- a/src/main/java/at/hannibal2/skyhanni/events/LorenzEvent.kt
+++ b/src/main/java/at/hannibal2/skyhanni/events/LorenzEvent.kt
@@ -12,6 +12,11 @@ import at.hannibal2.skyhanni.utils.system.PlatformUtils
import net.minecraftforge.common.MinecraftForge
import net.minecraftforge.fml.common.eventhandler.Event
import net.minecraftforge.fml.common.eventhandler.IEventListener
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+
+/**
+ * Use @[SubscribeEvent]
+ */
@Deprecated("Use SkyHanniEvent instead")
abstract class LorenzEvent : Event() {
diff --git a/src/main/java/at/hannibal2/skyhanni/events/NeuRepositoryReloadEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/NeuRepositoryReloadEvent.kt
index c2bd261ca0a1..9feb170c1f08 100644
--- a/src/main/java/at/hannibal2/skyhanni/events/NeuRepositoryReloadEvent.kt
+++ b/src/main/java/at/hannibal2/skyhanni/events/NeuRepositoryReloadEvent.kt
@@ -7,6 +7,7 @@ import at.hannibal2.skyhanni.data.repo.RepoUtils
import at.hannibal2.skyhanni.test.command.ErrorManager
import at.hannibal2.skyhanni.utils.NEUItems.manager
import at.hannibal2.skyhanni.utils.json.fromJson
+import at.hannibal2.skyhanni.utils.json.getJson
import com.google.gson.Gson
import com.google.gson.JsonObject
import com.google.gson.JsonSyntaxException
@@ -14,9 +15,7 @@ import java.io.File
import java.lang.reflect.Type
class NeuRepositoryReloadEvent : LorenzEvent() {
- fun getConstant(file: String): JsonObject? {
- return manager.getJsonFromFile(File(manager.repoLocation, "constants/$file.json"))
- }
+ fun getConstant(file: String): JsonObject? = File(manager.repoLocation, "constants/$file.json").getJson()
inline fun readConstant(file: String, gson: Gson = ConfigManager.gson): T {
val data = getConstant(file) ?: ErrorManager.skyHanniError("$file failed to load from neu repo!")
diff --git a/src/main/java/at/hannibal2/skyhanni/events/PlaySoundEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/PlaySoundEvent.kt
index 2f793ff28860..96f228a6ba85 100644
--- a/src/main/java/at/hannibal2/skyhanni/events/PlaySoundEvent.kt
+++ b/src/main/java/at/hannibal2/skyhanni/events/PlaySoundEvent.kt
@@ -1,8 +1,8 @@
package at.hannibal2.skyhanni.events
import at.hannibal2.skyhanni.utils.LocationUtils.distanceToPlayer
-import at.hannibal2.skyhanni.utils.LorenzUtils.round
import at.hannibal2.skyhanni.utils.LorenzVec
+import at.hannibal2.skyhanni.utils.NumberUtil.roundTo
import net.minecraftforge.fml.common.eventhandler.Cancelable
@Cancelable
@@ -11,10 +11,8 @@ class PlaySoundEvent(val soundName: String, val location: LorenzVec, val pitch:
val distanceToPlayer by lazy { location.distanceToPlayer() }
override fun toString(): String {
- return "PlaySoundEvent(soundName='$soundName', pitch=$pitch, volume=$volume, location=${location.round(1)}, distanceToPlayer=${
- distanceToPlayer.round(
- 1
- )
+ return "PlaySoundEvent(soundName='$soundName', pitch=$pitch, volume=$volume, location=${location.roundTo(1)}, distanceToPlayer=${
+ distanceToPlayer.roundTo(1)
})"
}
}
diff --git a/src/main/java/at/hannibal2/skyhanni/events/ReceiveParticleEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/ReceiveParticleEvent.kt
index ef296326da84..75fe8af8a3c2 100644
--- a/src/main/java/at/hannibal2/skyhanni/events/ReceiveParticleEvent.kt
+++ b/src/main/java/at/hannibal2/skyhanni/events/ReceiveParticleEvent.kt
@@ -1,8 +1,8 @@
package at.hannibal2.skyhanni.events
import at.hannibal2.skyhanni.utils.LocationUtils.distanceToPlayer
-import at.hannibal2.skyhanni.utils.LorenzUtils.round
import at.hannibal2.skyhanni.utils.LorenzVec
+import at.hannibal2.skyhanni.utils.NumberUtil.roundTo
import net.minecraft.util.EnumParticleTypes
import net.minecraftforge.fml.common.eventhandler.Cancelable
@@ -21,12 +21,12 @@ class ReceiveParticleEvent(
val distanceToPlayer by lazy { location.distanceToPlayer() }
override fun toString(): String {
- return "ReceiveParticleEvent(type='$type', location=${location.round(1)}, count=$count, speed=$speed, offset=${
- offset.round(
+ return "ReceiveParticleEvent(type='$type', location=${location.roundTo(1)}, count=$count, speed=$speed, offset=${
+ offset.roundTo(
1
)
}, longDistance=$longDistance, particleArgs=${particleArgs.contentToString()}, distanceToPlayer=${
- distanceToPlayer.round(
+ distanceToPlayer.roundTo(
1
)
})"
diff --git a/src/main/java/at/hannibal2/skyhanni/events/ServerBlockChangeEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/ServerBlockChangeEvent.kt
index 07aa7630ed37..106ee2821cb3 100644
--- a/src/main/java/at/hannibal2/skyhanni/events/ServerBlockChangeEvent.kt
+++ b/src/main/java/at/hannibal2/skyhanni/events/ServerBlockChangeEvent.kt
@@ -7,7 +7,7 @@ import at.hannibal2.skyhanni.utils.toLorenzVec
import net.minecraft.block.state.IBlockState
import net.minecraft.util.BlockPos
-class ServerBlockChangeEvent(private val blockPos: BlockPos, private val blockState: IBlockState) : LorenzEvent() {
+class ServerBlockChangeEvent(blockPos: BlockPos, blockState: IBlockState) : LorenzEvent() {
val location by lazy { blockPos.toLorenzVec() }
val old by lazy { location.getBlockAt().toString().getName() }
@@ -17,7 +17,7 @@ class ServerBlockChangeEvent(private val blockPos: BlockPos, private val blockSt
companion object {
- val pattern = "Block\\{minecraft:(?.*)}".toPattern()
+ private val pattern = "Block\\{minecraft:(?.*)}".toPattern()
private fun String.getName() = pattern.matchMatcher(this) {
group("name")
diff --git a/src/main/java/at/hannibal2/skyhanni/events/entity/slayer/SlayerDeathEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/entity/slayer/SlayerDeathEvent.kt
new file mode 100644
index 000000000000..620e4fb3e703
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/events/entity/slayer/SlayerDeathEvent.kt
@@ -0,0 +1,6 @@
+package at.hannibal2.skyhanni.events.entity.slayer
+
+import at.hannibal2.skyhanni.api.event.SkyHanniEvent
+import at.hannibal2.skyhanni.features.slayer.SlayerType
+
+class SlayerDeathEvent(val slayerType: SlayerType, val tier: Int, val owner: String?) : SkyHanniEvent()
diff --git a/src/main/java/at/hannibal2/skyhanni/events/hoppity/EggFoundEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/hoppity/EggFoundEvent.kt
new file mode 100644
index 000000000000..2cd81811f272
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/events/hoppity/EggFoundEvent.kt
@@ -0,0 +1,10 @@
+package at.hannibal2.skyhanni.events.hoppity
+
+import at.hannibal2.skyhanni.api.event.SkyHanniEvent
+import at.hannibal2.skyhanni.features.event.hoppity.HoppityEggType
+
+class EggFoundEvent(
+ val type: HoppityEggType,
+ val slotIndex: Int?,
+ val note: String?,
+) : SkyHanniEvent()
diff --git a/src/main/java/at/hannibal2/skyhanni/events/mining/OreMinedEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/mining/OreMinedEvent.kt
index a97402a4179a..d74e65eced2a 100644
--- a/src/main/java/at/hannibal2/skyhanni/events/mining/OreMinedEvent.kt
+++ b/src/main/java/at/hannibal2/skyhanni/events/mining/OreMinedEvent.kt
@@ -3,4 +3,4 @@ package at.hannibal2.skyhanni.events.mining
import at.hannibal2.skyhanni.api.event.SkyHanniEvent
import at.hannibal2.skyhanni.features.mining.OreBlock
-class OreMinedEvent(val originalOre: OreBlock, val extraBlocks: Map) : SkyHanniEvent()
+class OreMinedEvent(val originalOre: OreBlock?, val extraBlocks: Map) : SkyHanniEvent()
diff --git a/src/main/java/at/hannibal2/skyhanni/events/skyblock/AreaChangeEvents.kt b/src/main/java/at/hannibal2/skyhanni/events/skyblock/AreaChangeEvents.kt
new file mode 100644
index 000000000000..b262ea9fbe44
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/events/skyblock/AreaChangeEvents.kt
@@ -0,0 +1,6 @@
+package at.hannibal2.skyhanni.events.skyblock
+
+import at.hannibal2.skyhanni.api.event.SkyHanniEvent
+
+// Detect area changes by looking at the scoreboard.
+class ScoreboardAreaChangeEvent(val area: String, val previousArea: String?) : SkyHanniEvent()
diff --git a/src/main/java/at/hannibal2/skyhanni/features/bingo/FirstMinionTier.kt b/src/main/java/at/hannibal2/skyhanni/features/bingo/FirstMinionTier.kt
index e4bae4f05f8d..e94fb8d840d0 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/bingo/FirstMinionTier.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/bingo/FirstMinionTier.kt
@@ -1,13 +1,12 @@
package at.hannibal2.skyhanni.features.bingo
import at.hannibal2.skyhanni.test.command.ErrorManager
-import at.hannibal2.skyhanni.utils.ItemUtils.name
import at.hannibal2.skyhanni.utils.NEUInternalName
-import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName
import at.hannibal2.skyhanni.utils.NEUItems
import at.hannibal2.skyhanni.utils.NEUItems.getCachedIngredients
+import at.hannibal2.skyhanni.utils.NEUItems.getItemStackOrNull
+import at.hannibal2.skyhanni.utils.PrimitiveRecipe
import at.hannibal2.skyhanni.utils.StringUtils.removeColor
-import io.github.moulberry.notenoughupdates.recipes.CraftingRecipe
object FirstMinionTier {
@@ -30,20 +29,20 @@ object FirstMinionTier {
) {
for (minionId in tierOneMinionsFiltered) {
for (recipe in NEUItems.getRecipes(minionId)) {
- if (recipe !is CraftingRecipe) continue
+ if (!recipe.isCraftingRecipe()) continue
checkOne(recipe, help, minions, minionId)
}
}
}
private fun checkOne(
- recipe: CraftingRecipe,
+ recipe: PrimitiveRecipe,
help: Map,
minions: MutableMap,
minionId: NEUInternalName,
) {
- if (recipe.getCachedIngredients().any { help.contains(it.internalItemId.asInternalName()) }) {
- val name = recipe.output.itemStack.name.removeColor()
+ if (recipe.getCachedIngredients().any { help.contains(it.internalName) }) {
+ val name = recipe.output?.internalName?.getItemStackOrNull()?.displayName?.removeColor() ?: return
val abc = name.replace(" I", " 0")
minions[abc] = minionId.replace("_1", "_0")
}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/bingo/MinionCraftHelper.kt b/src/main/java/at/hannibal2/skyhanni/features/bingo/MinionCraftHelper.kt
index c12bafc39ea3..6f7a062f85e5 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/bingo/MinionCraftHelper.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/bingo/MinionCraftHelper.kt
@@ -7,6 +7,7 @@ import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent
import at.hannibal2.skyhanni.events.LorenzTickEvent
import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent
import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule
+import at.hannibal2.skyhanni.utils.CollectionUtils.addOrPut
import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName
import at.hannibal2.skyhanni.utils.ItemUtils.hasEnchantments
import at.hannibal2.skyhanni.utils.ItemUtils.itemName
@@ -18,13 +19,13 @@ import at.hannibal2.skyhanni.utils.NEUItems
import at.hannibal2.skyhanni.utils.NEUItems.getCachedIngredients
import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators
import at.hannibal2.skyhanni.utils.NumberUtil.romanToDecimalIfNecessary
+import at.hannibal2.skyhanni.utils.PrimitiveIngredient.Companion.toPrimitiveItemStacks
import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher
import at.hannibal2.skyhanni.utils.RenderUtils.renderStrings
import at.hannibal2.skyhanni.utils.StringUtils.removeColor
import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern
import com.google.gson.JsonArray
import com.google.gson.JsonObject
-import io.github.moulberry.notenoughupdates.recipes.CraftingRecipe
import net.minecraft.client.Minecraft
import net.minecraft.item.ItemStack
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
@@ -139,7 +140,7 @@ object MinionCraftHelper {
for (recipe in recipes) {
for (ingredient in recipe.getCachedIngredients()) {
- val ingredientInternalName = ingredient.internalItemId.asInternalName()
+ val ingredientInternalName = ingredient.internalName
if (ingredientInternalName == internalName) return true
val ingredientPrimitive = NEUItems.getPrimitiveMultiplier(ingredientInternalName)
@@ -169,10 +170,10 @@ object MinionCraftHelper {
if (internalName.contains("_GENERATOR_")) {
for (recipe in NEUItems.getRecipes(internalName)) {
- if (recipe !is CraftingRecipe) continue
+ if (!recipe.isCraftingRecipe()) continue
for (ingredient in recipe.getCachedIngredients()) {
- val id = ingredient.internalItemId.asInternalName()
+ val id = ingredient.internalName
if (!id.contains("_GENERATOR_") && !allIngredients.contains(id)) {
allIngredients.add(id)
}
@@ -194,17 +195,13 @@ object MinionCraftHelper {
newDisplay.add(minionName)
val nextMinionId = minionId.addOneToId()
for (recipe in NEUItems.getRecipes(nextMinionId)) {
- if (recipe !is CraftingRecipe) continue
- val output = recipe.output
- val internalItemId = output.internalItemId.asInternalName()
- if (!internalItemId.contains("_GENERATOR_")) continue
+ if (!recipe.isCraftingRecipe()) continue
+ val output = recipe.output ?: continue
+ if (!output.internalName.contains("_GENERATOR_")) continue
val map = mutableMapOf()
- for (input in recipe.inputs) {
- val itemId = input.internalItemId.asInternalName()
+ for ((itemId, count) in recipe.ingredients.toPrimitiveItemStacks()) {
if (minionId != itemId) {
- val count = input.count.toInt()
- val old = map.getOrDefault(itemId, 0)
- map[itemId] = old + count
+ map.addOrPut(itemId, count)
}
}
var allDone = true
diff --git a/src/main/java/at/hannibal2/skyhanni/features/chat/ChatFilterGui.kt b/src/main/java/at/hannibal2/skyhanni/features/chat/ChatFilterGui.kt
index 0fee71849b4f..6a5f22b6635a 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/chat/ChatFilterGui.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/chat/ChatFilterGui.kt
@@ -5,7 +5,8 @@ import at.hannibal2.skyhanni.utils.ChatUtils
import at.hannibal2.skyhanni.utils.KeyboardManager
import at.hannibal2.skyhanni.utils.OSUtils
import at.hannibal2.skyhanni.utils.StringUtils.stripHypixelMessage
-import io.github.moulberry.notenoughupdates.util.Utils
+import at.hannibal2.skyhanni.utils.renderables.Renderable
+import at.hannibal2.skyhanni.utils.renderables.RenderableTooltips
import io.github.notenoughupdates.moulconfig.internal.GlScissorStack
import io.github.notenoughupdates.moulconfig.internal.RenderUtils
import net.minecraft.client.Minecraft
@@ -42,7 +43,7 @@ class ChatFilterGui(private val history: List
+ RenderableTooltips.setTooltipForRender(tooltip.map { Renderable.string(it) })
}
GlStateManager.color(1f, 1f, 1f, 1f)
}
@@ -98,7 +99,7 @@ class ChatFilterGui(private val history: List mob.killNeededForNextLevel
else -> 0
}
- val percentage = ((currentKill.toDouble() / killNeeded) * 100).roundToPrecision(2)
+ val percentage = ((currentKill.toDouble() / killNeeded) * 100).roundTo(2)
val suffix = if (type == DisplayTypeEntry.GLOBAL_NEXT) "§ato level ${mob.getNextLevel()}" else ""
"§7(§b${currentKill.formatNumber()}§7/§b${killNeeded.formatNumber()}§7) §a$percentage§6% $suffix"
}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/combat/BroodmotherFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/combat/BroodmotherFeatures.kt
index e087fdd1934e..dd7c088b0b7e 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/combat/BroodmotherFeatures.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/combat/BroodmotherFeatures.kt
@@ -60,9 +60,7 @@ object BroodmotherFeatures {
private fun onStageUpdate() {
ChatUtils.debug("New Broodmother stage: $currentStage")
- if (lastStage == null) {
- if (onServerJoin()) return
- }
+ if (lastStage == null && onServerJoin()) return
// ignore Hypixel bug where the stage may temporarily revert to Imminent after the Broodmother's death
if (currentStage == StageEntry.IMMINENT && lastStage == StageEntry.ALIVE) return
@@ -72,23 +70,23 @@ object BroodmotherFeatures {
return
}
- val timeUntilSpawn = currentStage?.minutes?.minutes
- broodmotherSpawnTime = SimpleTimeMark.now() + timeUntilSpawn!!
-
if (currentStage == StageEntry.IMMINENT && config.imminentWarning) {
playImminentWarning()
return
}
- if (config.stages.contains(currentStage) && lastStage != null) {
- if (currentStage == StageEntry.SLAIN) {
- onBroodmotherSlain()
- } else {
- val pluralize = StringUtils.pluralize(timeUntilSpawn.toInt(DurationUnit.MINUTES), "minute")
- ChatUtils.chat(
- "Broodmother: $lastStage §e-> $currentStage§e. §b${timeUntilSpawn.inWholeMinutes} $pluralize §euntil it spawns!"
- )
- }
+ val lastStage = lastStage ?: return
+ val timeUntilSpawn = currentStage?.minutes?.minutes ?: return
+ broodmotherSpawnTime = SimpleTimeMark.now() + timeUntilSpawn
+
+ if (currentStage !in config.stages) return
+ if (currentStage == StageEntry.SLAIN) {
+ onBroodmotherSlain()
+ } else {
+ val pluralize = StringUtils.pluralize(timeUntilSpawn.toInt(DurationUnit.MINUTES), "minute")
+ ChatUtils.chat(
+ "Broodmother: $lastStage §e-> $currentStage§e. §b${timeUntilSpawn.inWholeMinutes} $pluralize §euntil it spawns!"
+ )
}
}
@@ -99,7 +97,7 @@ object BroodmotherFeatures {
val pluralize = StringUtils.pluralize(currentStage?.minutes ?: 0, "minute")
var message = "The Broodmother's current stage in this server is ${currentStage.toString().replace("!", "")}§e."
if (currentStage?.minutes != 0) {
- message += " It will spawn within §b${currentStage?.minutes} $pluralize§e."
+ message += " It will spawn §bwithin ${currentStage?.minutes} $pluralize§e."
}
ChatUtils.chat(message)
return true
@@ -161,7 +159,7 @@ object BroodmotherFeatures {
if (!isCountdownEnabled()) return
if (broodmotherSpawnTime.isFarPast()) {
- if (lastStage != null) {
+ if (lastStage != null && currentStage == StageEntry.ALIVE) {
display = "§4Broodmother spawned!"
}
} else {
diff --git a/src/main/java/at/hannibal2/skyhanni/features/combat/damageindicator/DamageIndicatorManager.kt b/src/main/java/at/hannibal2/skyhanni/features/combat/damageindicator/DamageIndicatorManager.kt
index b7af2d72b2d4..0391e40a3697 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/combat/damageindicator/DamageIndicatorManager.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/combat/damageindicator/DamageIndicatorManager.kt
@@ -34,10 +34,10 @@ import at.hannibal2.skyhanni.utils.LocationUtils.distanceToPlayer
import at.hannibal2.skyhanni.utils.LorenzColor
import at.hannibal2.skyhanni.utils.LorenzUtils
import at.hannibal2.skyhanni.utils.LorenzUtils.baseMaxHealth
-import at.hannibal2.skyhanni.utils.LorenzUtils.round
import at.hannibal2.skyhanni.utils.LorenzVec
import at.hannibal2.skyhanni.utils.NumberUtil
import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators
+import at.hannibal2.skyhanni.utils.NumberUtil.roundTo
import at.hannibal2.skyhanni.utils.NumberUtil.shortFormat
import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher
import at.hannibal2.skyhanni.utils.RenderUtils.drawDynamicText
@@ -718,7 +718,7 @@ object DamageIndicatorManager {
if (existed > 40) {
val end = (20 * 26) - existed
val time = end.toDouble() / 20
- entityData.nameAbove = "Mania Circles: §b${time.round(1)}s"
+ entityData.nameAbove = "Mania Circles: §b${time.roundTo(1)}s"
return ""
}
}
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 3bc3c85d4b2a..b337d58b1487 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
@@ -48,14 +48,14 @@ import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators
import at.hannibal2.skyhanni.utils.NumberUtil.formatDouble
import at.hannibal2.skyhanni.utils.NumberUtil.formatLong
import at.hannibal2.skyhanni.utils.NumberUtil.romanToDecimal
-import at.hannibal2.skyhanni.utils.NumberUtil.roundToPrecision
+import at.hannibal2.skyhanni.utils.NumberUtil.roundTo
import at.hannibal2.skyhanni.utils.OSUtils
import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher
import at.hannibal2.skyhanni.utils.RenderUtils.renderStringsAndItems
import at.hannibal2.skyhanni.utils.StringUtils.removeColor
import at.hannibal2.skyhanni.utils.renderables.Renderable
import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern
-import io.github.moulberry.notenoughupdates.util.Utils
+import com.google.gson.JsonPrimitive
import io.github.moulberry.notenoughupdates.util.XPInformation
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import org.apache.commons.io.FilenameUtils
@@ -76,27 +76,27 @@ object GhostCounter {
private val patternGroup = RepoPattern.group("combat.ghostcounter")
private val skillXPPattern by patternGroup.pattern(
"skillxp",
- "[+](?[0-9,.]+) \\((?[0-9,.]+)(?:/(?[0-9,.]+))?\\)"
+ "[+](?[0-9,.]+) \\((?[0-9,.]+)(?:/(?[0-9,.]+))?\\)",
)
private val combatSectionPattern by patternGroup.pattern(
"combatsection",
- ".*[+](?[0-9,.]+) (?[A-Za-z]+) \\((?