diff options
10 files changed, 186 insertions, 62 deletions
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 611b57621..bd6cc8efe 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt +++ b/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt @@ -29,6 +29,7 @@ import at.hannibal2.skyhanni.features.event.diana.GriffinBurrowHelper import at.hannibal2.skyhanni.features.event.diana.InquisitorWaypointShare import at.hannibal2.skyhanni.features.event.diana.MythologicalCreatureTracker import at.hannibal2.skyhanni.features.event.hoppity.HoppityCollectionStats +import at.hannibal2.skyhanni.features.event.hoppity.HoppityEggLocations import at.hannibal2.skyhanni.features.event.jerry.frozentreasure.FrozenTreasureTracker import at.hannibal2.skyhanni.features.fishing.tracker.FishingProfitTracker import at.hannibal2.skyhanni.features.fishing.tracker.SeaCreatureTracker @@ -535,6 +536,10 @@ object Commands { "shaddfoundburrowlocationsfromclipboard", "Add all ever found burrow locations from clipboard" ) { AllBurrowsList.addFromClipboard() } + registerCommand( + "shtoggleegglocationdebug", + "Shows Hoppity egg locations with their internal API names and status." + ) { HoppityEggLocations.toggleDebug() } } private fun internalCommands() { diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/event/HoppityEggsConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/event/HoppityEggsConfig.java index 59f2d7516..6ec9f2439 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/event/HoppityEggsConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/event/HoppityEggsConfig.java @@ -51,6 +51,12 @@ public class HoppityEggsConfig { public boolean showNearbyDuplicateEggLocations = false; @Expose + @ConfigOption(name = "Load from NEU PV", desc = "Load Hoppity Egg Location data from API when opening the NEU Profile Viewer.") + @ConfigEditorBoolean + @FeatureToggle + public boolean loadFromNeuPv = true; + + @Expose @ConfigOption(name = "Show Unclaimed Eggs", desc = "Displays which eggs haven't been found in the last SkyBlock day.") @ConfigEditorBoolean @FeatureToggle diff --git a/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/other/HypixelPlayerApiJson.kt b/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/other/HypixelPlayerApiJson.kt index 0a18ca28e..47304433a 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/other/HypixelPlayerApiJson.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/other/HypixelPlayerApiJson.kt @@ -2,6 +2,7 @@ package at.hannibal2.skyhanni.data.jsonobjects.other import com.google.gson.annotations.Expose import com.google.gson.annotations.SerializedName +import javax.annotation.Nullable data class HypixelPlayerApiJson( @Expose val profiles: List<HypixelApiProfile> @@ -13,7 +14,21 @@ data class HypixelApiProfile( ) data class HypixelApiPlayer( - @Expose @SerializedName("trophy_fish") val trophyFish: HypixelApiTrophyFish + @Expose @SerializedName("trophy_fish") val trophyFish: HypixelApiTrophyFish, + @Expose val events: HypixelApiEvents +) + +data class HypixelApiEvents( + @Expose val easter: HypixelApiEasterEvent +) + +data class HypixelApiEasterEvent( + @Expose val rabbits: HypixelApiRabbits +) + +data class HypixelApiRabbits( + @Expose @SerializedName("collected_locations") + val collectedLocations: Map<String, List<String>> ) data class HypixelApiTrophyFish( 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 82eadbd18..d83d66249 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 @@ -21,5 +21,6 @@ data class HoppityEggLocationsJson( @Expose val coachRabbitIndex: Int, @Expose val maxRabbits: Int, @Expose val maxPrestige: Int, + @Expose val apiEggLocations: Map<IslandType, Map<String, LorenzVec>>, @Expose val specialRabbits: List<String>, ) diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggLocations.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggLocations.kt new file mode 100644 index 000000000..4fd39eb96 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggLocations.kt @@ -0,0 +1,146 @@ +package at.hannibal2.skyhanni.features.event.hoppity + +import at.hannibal2.skyhanni.data.IslandType +import at.hannibal2.skyhanni.data.jsonobjects.repo.HoppityEggLocationsJson +import at.hannibal2.skyhanni.events.LorenzRenderWorldEvent +import at.hannibal2.skyhanni.events.NeuProfileDataLoadedEvent +import at.hannibal2.skyhanni.events.ProfileJoinEvent +import at.hannibal2.skyhanni.events.RepositoryReloadEvent +import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactoryAPI +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.test.command.ErrorManager +import at.hannibal2.skyhanni.utils.ChatUtils +import at.hannibal2.skyhanni.utils.LocationUtils +import at.hannibal2.skyhanni.utils.LocationUtils.distanceSqToPlayer +import at.hannibal2.skyhanni.utils.LorenzColor +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.LorenzVec +import at.hannibal2.skyhanni.utils.RenderUtils.drawColor +import at.hannibal2.skyhanni.utils.RenderUtils.drawDynamicText +import at.hannibal2.skyhanni.utils.StringUtils +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +@SkyHanniModule +object HoppityEggLocations { + + private var collectedEggStorage: MutableMap<IslandType, MutableSet<LorenzVec>> + get() = ChocolateFactoryAPI.profileStorage?.collectedEggLocations ?: mutableMapOf() + set(value) { + ChocolateFactoryAPI.profileStorage?.collectedEggLocations = value + } + + private var apiEggLocations: Map<IslandType, Map<String, LorenzVec>> = mapOf() + + val islandLocations + get() = apiEggLocations[LorenzUtils.skyBlockIsland]?.values?.toSet() ?: emptySet() + + val islandCollectedLocations + get() = collectedEggStorage[LorenzUtils.skyBlockIsland]?.toSet() ?: emptySet() + + fun hasCollectedEgg(location: LorenzVec): Boolean = islandCollectedLocations.contains(location) + + @SubscribeEvent + fun onRepoReload(event: RepositoryReloadEvent) { + // TODO: split Chocolate Factory and Hoppity repo data + val data = event.getConstant<HoppityEggLocationsJson>("HoppityEggLocations") + apiEggLocations = data.apiEggLocations + legacyEggLocations = data.eggLocations.mapValues { it.value.toSet() } + } + + fun saveNearestEgg() { + val location = islandLocations.minByOrNull { it.distanceSqToPlayer() } ?: return + if (location.distanceSqToPlayer() > 100) { + ErrorManager.skyHanniError( + "Player far from any known egg location!", + "island" to LorenzUtils.skyBlockIsland, + "distanceSqToPlayer" to location.distanceSqToPlayer(), + "playerLocation" to LocationUtils.playerLocation(), + "closestKnownEgg" to location, + ) + } + + saveEggLocation(LorenzUtils.skyBlockIsland, location) + } + + private fun saveEggLocation(island: IslandType, location: LorenzVec) { + val locations = collectedEggStorage.getOrPut(island) { mutableSetOf() } + locations += location + } + + private var loadedNeuThisProfile = false + + @SubscribeEvent + fun onProfileJoin(event: ProfileJoinEvent) { + loadedNeuThisProfile = false + } + + @SubscribeEvent + fun onNeuProfileDataLoaded(event: NeuProfileDataLoadedEvent) { + if (loadedNeuThisProfile || !HoppityEggsManager.config.loadFromNeuPv) return + + val rawLocations = event.getCurrentPlayerData()?.events?.easter?.rabbits?.collectedLocations ?: return + loadedNeuThisProfile = true + + val apiCollectedLocations = rawLocations.values.flatten() + + val collectedEggsApiData = mutableMapOf<IslandType, MutableSet<LorenzVec>>() + + for ((island, locationNameToCoords) in apiEggLocations) { + val coords = apiCollectedLocations.mapNotNull { locationNameToCoords[it] } + collectedEggsApiData[island] = coords.toMutableSet() + } + + val storedEggLocationCount = collectedEggStorage.values.sumOf { it.size } + val diff = apiCollectedLocations.size - storedEggLocationCount + if (diff <= 0) return + + val locationStr = StringUtils.pluralize(diff, "location", "locations") + + ChatUtils.clickableChat( + message = "Click here to load $diff more collected egg $locationStr from NEU PV!", + onClick = { + loadApiCollectedEggs(collectedEggsApiData) + ChatUtils.chat("Updated Hoppity egg location data!") + }, + oneTimeClick = true + ) + } + + private fun loadApiCollectedEggs(locations: Map<IslandType, Set<LorenzVec>>) { + for ((island, coordinates) in locations.entries) { + coordinates.forEach { saveEggLocation(island, it) } + } + } + + /* Debug logic, enabled using /shtoggleegglocationdebug */ + private var showEggLocationsDebug = false + + // to be removed - in case there are any issues with missing locations + private var legacyEggLocations: Map<IslandType, Set<LorenzVec>> = mapOf() + + fun toggleDebug() { + showEggLocationsDebug = !showEggLocationsDebug + val enabledDisabled = if (showEggLocationsDebug) "§aEnabled" else "§cDisabled" + ChatUtils.chat("$enabledDisabled hoppity egg location debug viewer.") + } + + @SubscribeEvent + fun onRenderWorld(event: LorenzRenderWorldEvent) { + if (!LorenzUtils.inSkyBlock || !showEggLocationsDebug) return + val legacyLocations = legacyEggLocations[LorenzUtils.skyBlockIsland] ?: return + val apiLocations = apiEggLocations[LorenzUtils.skyBlockIsland] ?: return + val collectedLocations = islandCollectedLocations + for (location in legacyLocations) { + val name = apiLocations.entries.find { it.value == location }?.key + val isCollected = collectedLocations.contains(location) + val color = if (isCollected) LorenzColor.GREEN else LorenzColor.RED + val nameColorCode = (if (name != null) LorenzColor.GREEN else LorenzColor.RED).getChatColor() + + event.drawColor(location, color, false, 0.5f) + event.drawDynamicText(location.add(y = 0.5), "$nameColorCode$name", 1.2) + if (location.distanceSqToPlayer() < 100) { + event.drawDynamicText(location.add(y = 0.5), location.toCleanString(), 1.0, yOff = 12f) + } + } + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggLocator.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggLocator.kt index c358d3618..f4682dd51 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggLocator.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggLocator.kt @@ -1,7 +1,6 @@ package at.hannibal2.skyhanni.features.event.hoppity import at.hannibal2.skyhanni.data.ClickType -import at.hannibal2.skyhanni.data.IslandType import at.hannibal2.skyhanni.events.DebugDataCollectEvent import at.hannibal2.skyhanni.events.ItemClickEvent import at.hannibal2.skyhanni.events.LorenzRenderWorldEvent @@ -56,8 +55,6 @@ object HoppityEggLocator { var currentEggType: HoppityEggType? = null var currentEggNote: String? = null - var eggLocations: Map<IslandType, List<LorenzVec>> = mapOf() - @SubscribeEvent fun onWorldChange(event: LorenzWorldChangeEvent) { resetData() @@ -94,7 +91,7 @@ object HoppityEggLocator { } } - val islandEggsLocations = getCurrentIslandEggLocations() ?: return + val islandEggsLocations = HoppityEggLocations.islandLocations ?: return if (shouldShowAllEggs()) { for (eggLocation in islandEggsLocations) { @@ -116,11 +113,11 @@ object HoppityEggLocator { } } - private fun LorenzRenderWorldEvent.drawDuplicateEggs(islandEggsLocations: List<LorenzVec>, ) { + private fun LorenzRenderWorldEvent.drawDuplicateEggs(islandEggsLocations: Set<LorenzVec>, ) { if (!config.highlightDuplicateEggLocations || !config.showNearbyDuplicateEggLocations) return for (eggLocation in islandEggsLocations) { val dist = eggLocation.distanceToPlayer() - if (dist < 10 && HoppityUniqueEggLocations.hasCollectedEgg(eggLocation)) { + if (dist < 10 && HoppityEggLocations.hasCollectedEgg(eggLocation)) { val alpha = ((10 - dist) / 10).coerceAtMost(0.5).toFloat() drawColor(eggLocation, LorenzColor.RED, false, alpha) drawDynamicText(eggLocation.add(y = 1), "§cDuplicate Location!", 1.5) @@ -153,7 +150,7 @@ object HoppityEggLocator { private fun LorenzRenderWorldEvent.drawEggWaypoint(location: LorenzVec, label: String) { val shouldMarkDuplicate = config.highlightDuplicateEggLocations - && HoppityUniqueEggLocations.hasCollectedEgg(location) + && HoppityEggLocations.hasCollectedEgg(location) val possibleDuplicateLabel = if (shouldMarkDuplicate) "$label §c(Duplicate Location)" else label if (!shouldMarkDuplicate) { drawWaypointFilled(location, LorenzColor.GREEN.toColor(), seeThroughBlocks = true) @@ -219,7 +216,7 @@ object HoppityEggLocator { lastGuessMade = SimpleTimeMark.now() possibleEggLocations = emptyList() - val islandEggsLocations = getCurrentIslandEggLocations() ?: return + val islandEggsLocations = HoppityEggLocations.islandLocations ?: return val listSize = validParticleLocations.size if (listSize < 5) return @@ -264,11 +261,8 @@ object HoppityEggLocator { drawLocations = true } - fun getCurrentIslandEggLocations(): List<LorenzVec>? = - eggLocations[LorenzUtils.skyBlockIsland] - fun isValidEggLocation(location: LorenzVec): Boolean = - getCurrentIslandEggLocations()?.any { it.distance(location) < 5.0 } ?: false + HoppityEggLocations.islandLocations?.any { it.distance(location) < 5.0 } ?: false private fun ReceiveParticleEvent.isVillagerParticle() = type == EnumParticleTypes.VILLAGER_HAPPY && speed == 0.0f && count == 1 @@ -281,7 +275,7 @@ object HoppityEggLocator { private val ItemStack.isLocatorItem get() = getInternalName() == locatorItem - fun hasLocatorInHotbar() = RecalculatingValue(1.seconds) { + private fun hasLocatorInHotbar() = RecalculatingValue(1.seconds) { LorenzUtils.inSkyBlock && InventoryUtils.getItemsInHotbar().any { it.isLocatorItem } }.getValue() diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggsManager.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggsManager.kt index 771e55c59..7febbab91 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggsManager.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggsManager.kt @@ -110,7 +110,7 @@ object HoppityEggsManager { HoppityEggsCompactChat.handleChat(event) eggFoundPattern.matchMatcher(event.message) { - HoppityUniqueEggLocations.saveNearestEgg() + HoppityEggLocations.saveNearestEgg() HoppityEggLocator.eggFound() val meal = getEggType(event) val note = group("note").removeColor() @@ -193,9 +193,9 @@ object HoppityEggsManager { displayList.add(0, "§bUnclaimed Eggs:") if (config.showCollectedLocationCount && LorenzUtils.inSkyBlock) { - val totalEggs = HoppityEggLocator.getCurrentIslandEggLocations()?.size - if (totalEggs != null) { - val collectedEggs = HoppityUniqueEggLocations.collectedEggsThisIsland() + val totalEggs = HoppityEggLocations.islandLocations.size + if (totalEggs > 0) { + val collectedEggs = HoppityEggLocations.islandCollectedLocations.size val collectedFormat = formatEggsCollected(collectedEggs) displayList.add("§7Locations: $collectedFormat$collectedEggs§7/§a$totalEggs") } diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggsShared.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggsShared.kt index 0927036ae..d617241b0 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggsShared.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggsShared.kt @@ -47,7 +47,7 @@ object HoppityEggsShared { fun shareNearbyEggLocation(playerLocation: LorenzVec, meal: HoppityEggType, note: String) { if (!isEnabled()) return - val islandEggsLocations = HoppityEggLocator.getCurrentIslandEggLocations() ?: return + val islandEggsLocations = HoppityEggLocations.islandLocations ?: return val closestEgg = islandEggsLocations.minByOrNull { it.distance(playerLocation) } ?: return val x = closestEgg.x.toInt() diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityUniqueEggLocations.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityUniqueEggLocations.kt deleted file mode 100644 index 161cff80e..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityUniqueEggLocations.kt +++ /dev/null @@ -1,40 +0,0 @@ -package at.hannibal2.skyhanni.features.event.hoppity - -import at.hannibal2.skyhanni.data.IslandType -import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactoryAPI -import at.hannibal2.skyhanni.test.command.ErrorManager -import at.hannibal2.skyhanni.utils.LocationUtils -import at.hannibal2.skyhanni.utils.LocationUtils.distanceSqToPlayer -import at.hannibal2.skyhanni.utils.LorenzUtils -import at.hannibal2.skyhanni.utils.LorenzVec - -object HoppityUniqueEggLocations { - - private val collectedEggLocations: MutableMap<IslandType, MutableSet<LorenzVec>>? - get() = ChocolateFactoryAPI.profileStorage?.collectedEggLocations - - private fun getCurrentIslandCollectedEggs(): MutableSet<LorenzVec>? = - collectedEggLocations?.getOrPut(LorenzUtils.skyBlockIsland) { mutableSetOf<LorenzVec>() } - - fun saveNearestEgg() { - val location = HoppityEggLocator.getCurrentIslandEggLocations() - ?.minByOrNull { it.distanceSqToPlayer() } ?: return - if (location.distanceSqToPlayer() > 100) { - ErrorManager.skyHanniError( - "Player far from any known egg location!", - "island" to LorenzUtils.skyBlockIsland, - "distanceSqToPlayer" to location.distanceSqToPlayer(), - "playerLocation" to LocationUtils.playerLocation(), - "closestKnownEgg" to location, - ) - } - - getCurrentIslandCollectedEggs()?.add(location) - } - - fun collectedEggsThisIsland() = getCurrentIslandCollectedEggs()?.size ?: 0 - - fun hasCollectedEgg(location: LorenzVec) = - getCurrentIslandCollectedEggs()?.contains(location) ?: false - -} diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryAPI.kt index 568f8f4fe..5974b0485 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryAPI.kt @@ -9,7 +9,6 @@ import at.hannibal2.skyhanni.data.jsonobjects.repo.HoppityEggLocationsJson import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent import at.hannibal2.skyhanni.events.RepositoryReloadEvent import at.hannibal2.skyhanni.features.event.hoppity.HoppityCollectionStats -import at.hannibal2.skyhanni.features.event.hoppity.HoppityEggLocator import at.hannibal2.skyhanni.utils.CollectionUtils.nextAfter import at.hannibal2.skyhanni.utils.DelayedRun import at.hannibal2.skyhanni.utils.LorenzUtils @@ -97,8 +96,6 @@ object ChocolateFactoryAPI { fun onRepoReload(event: RepositoryReloadEvent) { val data = event.getConstant<HoppityEggLocationsJson>("HoppityEggLocations") - HoppityEggLocator.eggLocations = data.eggLocations - rabbitSlots = data.rabbitSlots otherUpgradeSlots = data.otherUpgradeSlots noPickblockSlots = data.noPickblockSlots |