diff options
16 files changed, 1122 insertions, 1145 deletions
diff --git a/.idea/dictionaries/default_user.xml b/.idea/dictionaries/default_user.xml index a1b1f01c3..846fd6b43 100644 --- a/.idea/dictionaries/default_user.xml +++ b/.idea/dictionaries/default_user.xml @@ -172,6 +172,7 @@ <w>skytils's</w> <w>soopy</w> <w>soopy's</w> + <w>soulsand</w> <w>soulweaver</w> <w>sprayonator</w> <w>stillgore</w> diff --git a/.live-plugins/module/plugin.kts b/.live-plugins/module/plugin.kts index 286160a9b..c0a65d3f4 100644 --- a/.live-plugins/module/plugin.kts +++ b/.live-plugins/module/plugin.kts @@ -5,7 +5,6 @@ import com.intellij.codeInspection.ProblemsHolder import com.intellij.openapi.project.Project import com.intellij.psi.PsiElementVisitor import liveplugin.registerInspection -import liveplugin.show import org.jetbrains.kotlin.idea.base.utils.fqname.fqName import org.jetbrains.kotlin.idea.codeinsight.api.classic.inspections.AbstractKotlinInspection import org.jetbrains.kotlin.idea.util.AnnotationModificationHelper @@ -55,7 +54,6 @@ class ModuleInspectionKotlin : AbstractKotlinInspection() { } override fun visitObjectDeclaration(declaration: KtObjectDeclaration) { - if (declaration.isCompanion()) return val hasAnnotation = declaration.annotationEntries.any { it.shortName?.asString() == skyHanniModule } if (hasAnnotation) return @@ -92,7 +90,6 @@ class ModuleQuickFix : LocalQuickFix { " ", null ) - show("Annotation applied, make sure SkyHanniMod isn't still loading this module") } override fun getName() = "Annotate with @SkyHanniModule" diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt index bb3faa278..28a8aa318 100644 --- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt +++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt @@ -6,9 +6,7 @@ import at.hannibal2.skyhanni.config.ConfigManager import at.hannibal2.skyhanni.config.Features import at.hannibal2.skyhanni.config.SackData import at.hannibal2.skyhanni.config.commands.Commands -import at.hannibal2.skyhanni.data.HypixelData import at.hannibal2.skyhanni.data.OtherInventoryData -import at.hannibal2.skyhanni.data.SkillExperience import at.hannibal2.skyhanni.data.jsonobjects.local.FriendsJson import at.hannibal2.skyhanni.data.jsonobjects.local.JacobContestsJson import at.hannibal2.skyhanni.data.jsonobjects.local.KnownFeaturesJson @@ -16,12 +14,8 @@ import at.hannibal2.skyhanni.data.jsonobjects.local.VisualWordsJson import at.hannibal2.skyhanni.data.repo.RepoManager import at.hannibal2.skyhanni.events.LorenzTickEvent import at.hannibal2.skyhanni.events.utils.PreInitFinishedEvent -import at.hannibal2.skyhanni.features.chat.Translator -import at.hannibal2.skyhanni.features.garden.farming.FarmingWeightDisplay -import at.hannibal2.skyhanni.features.misc.CollectionTracker import at.hannibal2.skyhanni.features.nether.reputationhelper.CrimsonIsleReputationHelper import at.hannibal2.skyhanni.skyhannimodule.LoadedModules -import at.hannibal2.skyhanni.test.SkyHanniDebugsAndTests import at.hannibal2.skyhanni.test.command.ErrorManager import at.hannibal2.skyhanni.test.hotswap.HotswapSupport import at.hannibal2.skyhanni.utils.MinecraftConsoleFilter.Companion.initLogging @@ -48,7 +42,7 @@ import org.apache.logging.log4j.Logger clientSideOnly = true, useMetadata = true, guiFactory = "at.hannibal2.skyhanni.config.ConfigGuiForgeInterop", - version = "0.26.Beta.9", + version = "0.26.Beta.7", ) class SkyHanniMod { @@ -61,18 +55,7 @@ class SkyHanniMod { loadModule(this) LoadedModules.modules.forEach { loadModule(it) } - // data - loadModule(HypixelData()) - loadModule(SkillExperience()) - - // features - loadModule(CollectionTracker()) loadModule(CrimsonIsleReputationHelper(this)) - loadModule(FarmingWeightDisplay()) - loadModule(Translator()) - - // test stuff - loadModule(SkyHanniDebugsAndTests()) SkyHanniEvents.init(modules) diff --git a/src/main/java/at/hannibal2/skyhanni/data/GuiEditManager.kt b/src/main/java/at/hannibal2/skyhanni/data/GuiEditManager.kt index 9f249ee7a..a7e09b3f0 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/GuiEditManager.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/GuiEditManager.kt @@ -144,4 +144,5 @@ object GuiEditManager { } } +// TODO remove class Vector2i(val x: Int, val y: Int) diff --git a/src/main/java/at/hannibal2/skyhanni/data/HypixelData.kt b/src/main/java/at/hannibal2/skyhanni/data/HypixelData.kt index d4a14679a..8ade8f55e 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/HypixelData.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/HypixelData.kt @@ -16,6 +16,7 @@ import at.hannibal2.skyhanni.events.minecraft.ClientDisconnectEvent import at.hannibal2.skyhanni.features.bingo.BingoAPI import at.hannibal2.skyhanni.features.dungeon.DungeonAPI import at.hannibal2.skyhanni.features.rift.RiftAPI +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.test.command.ErrorManager import at.hannibal2.skyhanni.utils.ChatUtils import at.hannibal2.skyhanni.utils.LorenzLogger @@ -35,7 +36,8 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import kotlin.concurrent.thread import kotlin.time.Duration.Companion.seconds -class HypixelData { +@SkyHanniModule +object HypixelData { private val patternGroup = RepoPattern.group("data.hypixeldata") // TODO add regex tests @@ -51,124 +53,121 @@ class HypixelData { "islandname", "(?:§.)*(Area|Dungeon): (?:§.)*(?<island>.*)", ) + private val serverIdScoreboardPattern by patternGroup.pattern( + "serverid.scoreboard", + "§7\\d+/\\d+/\\d+ §8(?<servertype>[mM])(?<serverid>\\S+).*", + ) + private val serverIdTablistPattern by patternGroup.pattern( + "serverid.tablist", + " Server: §r§8(?<serverid>\\S+)", + ) + private val lobbyTypePattern by patternGroup.pattern( + "lobbytype", + "(?<lobbyType>.*lobby)\\d+", + ) + private val playerAmountPattern by patternGroup.pattern( + "playeramount", + "^\\s*(?:§.)+Players (?:§.)+\\((?<amount>\\d+)\\)\\s*$", + ) + private val playerAmountCoopPattern by patternGroup.pattern( + "playeramount.coop", + "^\\s*(?:§.)*Coop (?:§.)*\\((?<amount>\\d+)\\)\\s*$", + ) + private val playerAmountGuestingPattern by patternGroup.pattern( + "playeramount.guesting", + "^\\s*(?:§.)*Guests (?:§.)*\\((?<amount>\\d+)\\)\\s*$", + ) - private var lastLocRaw = SimpleTimeMark.farPast() - - companion object { - private val patternGroup = RepoPattern.group("data.hypixeldata") - private val serverIdScoreboardPattern by patternGroup.pattern( - "serverid.scoreboard", - "§7\\d+/\\d+/\\d+ §8(?<servertype>[mM])(?<serverid>\\S+).*", - ) - private val serverIdTablistPattern by patternGroup.pattern( - "serverid.tablist", - " Server: §r§8(?<serverid>\\S+)", - ) - private val lobbyTypePattern by patternGroup.pattern( - "lobbytype", - "(?<lobbyType>.*lobby)\\d+", - ) - private val playerAmountPattern by patternGroup.pattern( - "playeramount", - "^\\s*(?:§.)+Players (?:§.)+\\((?<amount>\\d+)\\)\\s*$", - ) - private val playerAmountCoopPattern by patternGroup.pattern( - "playeramount.coop", - "^\\s*(?:§.)*Coop (?:§.)*\\((?<amount>\\d+)\\)\\s*$", - ) - private val playerAmountGuestingPattern by patternGroup.pattern( - "playeramount.guesting", - "^\\s*(?:§.)*Guests (?:§.)*\\((?<amount>\\d+)\\)\\s*$", - ) + /** + * REGEX-TEST: §r§b§lParty §r§f(4) + */ + private val dungeonPartyAmountPattern by patternGroup.pattern( + "playeramount.dungeonparty", + "^\\s*(?:§.)+Party (?:§.)+\\((?<amount>\\d+)\\)\\s*$", + ) + private val soloProfileAmountPattern by patternGroup.pattern( + "solo.profile.amount", + "^\\s*(?:§.)*Island\\s*$", + ) + private val scoreboardVisitingAmoutPattern by patternGroup.pattern( + "scoreboard.visiting.amount", + "\\s+§.✌ §.\\(§.(?<currentamount>\\d+)§./(?<maxamount>\\d+)\\)", + ) + private val guestPattern by patternGroup.pattern( + "guesting.scoreboard", + "SKYBLOCK GUEST", + ) + private val scoreboardTitlePattern by patternGroup.pattern( + "scoreboard.title", + "SK[YI]BLOCK(?: CO-OP| GUEST)?", + ) - /** - * REGEX-TEST: §r§b§lParty §r§f(4) - */ - private val dungeonPartyAmountPattern by patternGroup.pattern( - "playeramount.dungeonparty", - "^\\s*(?:§.)+Party (?:§.)+\\((?<amount>\\d+)\\)\\s*$", - ) - private val soloProfileAmountPattern by patternGroup.pattern( - "solo.profile.amount", - "^\\s*(?:§.)*Island\\s*$", - ) - private val scoreboardVisitingAmoutPattern by patternGroup.pattern( - "scoreboard.visiting.amount", - "\\s+§.✌ §.\\(§.(?<currentamount>\\d+)§./(?<maxamount>\\d+)\\)", - ) - private val guestPattern by patternGroup.pattern( - "guesting.scoreboard", - "SKYBLOCK GUEST", - ) - private val scoreboardTitlePattern by patternGroup.pattern( - "scoreboard.title", - "SK[YI]BLOCK(?: CO-OP| GUEST)?", - ) + /** + * REGEX-TEST: §7⏣ §bVillage + * REGEX-TEST: §5ф §dWizard Tower + */ + private val skyblockAreaPattern by patternGroup.pattern( + "skyblock.area", + "\\s*§(?<symbol>7⏣|5ф) §(?<color>.)(?<area>.*)", + ) - /** - * REGEX-TEST: §7⏣ §bVillage - * REGEX-TEST: §5ф §dWizard Tower - */ - private val skyblockAreaPattern by patternGroup.pattern( - "skyblock.area", - "\\s*§(?<symbol>7⏣|5ф) §(?<color>.)(?<area>.*)", - ) + private var lastLocRaw = SimpleTimeMark.farPast() - var hypixelLive = false - var hypixelAlpha = false - var inLobby = false - var inLimbo = false - var skyBlock = false - var skyBlockIsland = IslandType.UNKNOWN - var serverId: String? = null + var hypixelLive = false + var hypixelAlpha = false + var inLobby = false + var inLimbo = false + var skyBlock = false + var skyBlockIsland = IslandType.UNKNOWN + var serverId: String? = null - // Ironman, Stranded and Bingo - var noTrade = false + // Ironman, Stranded and Bingo + var noTrade = false - var ironman = false - var stranded = false - var bingo = false + var ironman = false + var stranded = false + var bingo = false - var profileName = "" - var joinedWorld = SimpleTimeMark.farPast() + var profileName = "" + var joinedWorld = SimpleTimeMark.farPast() - var skyBlockArea: String? = null - var skyBlockAreaWithSymbol: String? = null + var skyBlockArea: String? = null + var skyBlockAreaWithSymbol: String? = null // Data from locraw var locrawData: JsonObject? = null - private var locraw: MutableMap<String, String> = listOf( - "server", + private var locraw: MutableMap<String, String> = listOf( + "server", "gametype", "lobbyname", "lobbytype", "mode", "map", - ).associateWith { "" }.toMutableMap() - - val server get() = locraw["server"] ?: "" - val gameType get() = locraw["gametype"] ?: "" - val lobbyName get() = locraw["lobbyname"] ?: "" - val lobbyType get() = locraw["lobbytype"] ?: "" - val mode get() = locraw["mode"] ?: "" - val map get() = locraw["map"] ?: "" - - fun checkCurrentServerId() { - if (!LorenzUtils.inSkyBlock) return - if (serverId != null) return - if (LorenzUtils.lastWorldSwitch.passedSince() < 1.seconds) return - if (!TabListData.fullyLoaded) return - - ScoreboardData.sidebarLinesFormatted.matchFirst(serverIdScoreboardPattern) { - val serverType = if (group("servertype") == "M") "mega" else "mini" - serverId = "$serverType${group("serverid")}" - return - } + ).associateWith { "" }.toMutableMap() + + val server get() = locraw["server"] ?: "" + val gameType get() = locraw["gametype"] ?: "" + val lobbyName get() = locraw["lobbyname"] ?: "" + val lobbyType get() = locraw["lobbytype"] ?: "" + val mode get() = locraw["mode"] ?: "" + val map get() = locraw["map"] ?: "" + + fun checkCurrentServerId() { + if (!LorenzUtils.inSkyBlock) return + if (serverId != null) return + if (LorenzUtils.lastWorldSwitch.passedSince() < 1.seconds) return + if (!TabListData.fullyLoaded) return + + ScoreboardData.sidebarLinesFormatted.matchFirst(serverIdScoreboardPattern) { + val serverType = if (group("servertype") == "M") "mega" else "mini" + serverId = "$serverType${group("serverid")}" + return + } - TabListData.getTabList().matchFirst(serverIdTablistPattern) { - serverId = group("serverid") - return - } + TabListData.getTabList().matchFirst(serverIdTablistPattern) { + serverId = group("serverid") + return + } ErrorManager.logErrorWithData( Exception("NoServerId"), @@ -179,71 +178,70 @@ class HypixelData { ) } - fun getPlayersOnCurrentServer(): Int { - var amount = 0 - val playerPatternList = mutableListOf( - playerAmountPattern, - playerAmountCoopPattern, - playerAmountGuestingPattern, - ) - if (DungeonAPI.inDungeon()) { - playerPatternList.add(dungeonPartyAmountPattern) - } + fun getPlayersOnCurrentServer(): Int { + var amount = 0 + val playerPatternList = mutableListOf( + playerAmountPattern, + playerAmountCoopPattern, + playerAmountGuestingPattern, + ) + if (DungeonAPI.inDungeon()) { + playerPatternList.add(dungeonPartyAmountPattern) + } - out@ for (pattern in playerPatternList) { - for (line in TabListData.getTabList()) { - pattern.matchMatcher(line) { - amount += group("amount").toInt() - continue@out - } + out@ for (pattern in playerPatternList) { + for (line in TabListData.getTabList()) { + pattern.matchMatcher(line) { + amount += group("amount").toInt() + continue@out } } - amount += TabListData.getTabList().count { soloProfileAmountPattern.matches(it) } - - return amount } + amount += TabListData.getTabList().count { soloProfileAmountPattern.matches(it) } - fun getMaxPlayersForCurrentServer(): Int { - ScoreboardData.sidebarLinesFormatted.matchFirst(scoreboardVisitingAmoutPattern) { - return group("maxamount").toInt() - } + return amount + } - return when (skyBlockIsland) { - IslandType.MINESHAFT -> 4 - IslandType.CATACOMBS -> 5 - IslandType.CRYSTAL_HOLLOWS -> 24 - IslandType.CRIMSON_ISLE -> 24 - else -> if (serverId?.startsWith("mega") == true) 80 else 26 - } + fun getMaxPlayersForCurrentServer(): Int { + ScoreboardData.sidebarLinesFormatted.matchFirst(scoreboardVisitingAmoutPattern) { + return group("maxamount").toInt() } - // This code is modified from NEU, and depends on NEU (or another mod) sending /locraw. - private val jsonBracketPattern = "^\\{.+}".toPattern() - - //todo convert to proper json object - fun checkForLocraw(message: String) { - jsonBracketPattern.matchMatcher(message.removeColor()) { - try { - val obj: JsonObject = gson.fromJson(group(), JsonObject::class.java) - if (obj.has("server")) { - locrawData = obj - locraw.keys.forEach { key -> - locraw[key] = obj[key]?.asString ?: "" - } - inLimbo = locraw["server"] == "limbo" - inLobby = locraw["lobbyname"] != "" - - if (inLobby) { - locraw["lobbyname"]?.let { - lobbyTypePattern.matchMatcher(it) { - locraw["lobbytype"] = group("lobbyType") - } + return when (skyBlockIsland) { + IslandType.MINESHAFT -> 4 + IslandType.CATACOMBS -> 5 + IslandType.CRYSTAL_HOLLOWS -> 24 + IslandType.CRIMSON_ISLE -> 24 + else -> if (serverId?.startsWith("mega") == true) 80 else 26 + } + } + + // This code is modified from NEU, and depends on NEU (or another mod) sending /locraw. + private val jsonBracketPattern = "^\\{.+}".toPattern() + + //todo convert to proper json object + fun checkForLocraw(message: String) { + jsonBracketPattern.matchMatcher(message.removeColor()) { + try { + val obj: JsonObject = gson.fromJson(group(), JsonObject::class.java) + if (obj.has("server")) { + locrawData = obj + locraw.keys.forEach { key -> + locraw[key] = obj[key]?.asString ?: "" + } + inLimbo = locraw["server"] == "limbo" + inLobby = locraw["lobbyname"] != "" + + if (inLobby) { + locraw["lobbyname"]?.let { + lobbyTypePattern.matchMatcher(it) { + locraw["lobbytype"] = group("lobbyType") } } } - } catch (e: Exception) { - ErrorManager.logErrorWithData(e, "Failed to parse locraw data") } + } catch (e: Exception) { + ErrorManager.logErrorWithData(e, "Failed to parse locraw data") } } } diff --git a/src/main/java/at/hannibal2/skyhanni/data/ScoreboardData.kt b/src/main/java/at/hannibal2/skyhanni/data/ScoreboardData.kt index 72abf6bab..31499adb1 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/ScoreboardData.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/ScoreboardData.kt @@ -28,6 +28,8 @@ object ScoreboardData { private val minecraftColorCodesPattern = "(?i)[0-9a-fkmolnr]".toPattern() + + fun formatLines(rawList: List<String>): List<String> { val list = mutableListOf<String>() for (line in rawList) { diff --git a/src/main/java/at/hannibal2/skyhanni/data/SkillExperience.kt b/src/main/java/at/hannibal2/skyhanni/data/SkillExperience.kt index 25d48a525..367c3794e 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/SkillExperience.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/SkillExperience.kt @@ -3,6 +3,7 @@ package at.hannibal2.skyhanni.data import at.hannibal2.skyhanni.events.ActionBarUpdateEvent import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent import at.hannibal2.skyhanni.events.ProfileJoinEvent +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.ItemUtils.getLore import at.hannibal2.skyhanni.utils.ItemUtils.name import at.hannibal2.skyhanni.utils.LorenzUtils @@ -13,7 +14,8 @@ import at.hannibal2.skyhanni.utils.StringUtils.removeColor import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern import net.minecraftforge.fml.common.eventhandler.SubscribeEvent -class SkillExperience { +@SkyHanniModule +object SkillExperience { private val patternGroup = RepoPattern.group("data.skill") private val actionBarPattern by patternGroup.pattern( "actionbar", @@ -77,102 +79,100 @@ class SkillExperience { if (skillExp.isNotEmpty()) return } - companion object { - private val skillExp = mutableMapOf<String, Long>() + private val skillExp = mutableMapOf<String, Long>() - private fun getLevelForExpExactly(experience: Long): Int { - var level = 1 - for (levelXp in levelingExp) { - if (levelXp.toLong() == experience) { - return level - } - level++ + private fun getLevelForExpExactly(experience: Long): Int { + var level = 1 + for (levelXp in levelingExp) { + if (levelXp.toLong() == experience) { + return level } - - return 0 + level++ } - fun getExpForNextLevel(requestedLevel: Int) = levelingExp[requestedLevel] + return 0 + } - fun getExpForLevel(requestedLevel: Int): Long { - var total = 0L - var level = 0 - for (levelXp in levelingExp) { - total += levelXp - level++ - if (level == requestedLevel) { - return total - } - } + fun getExpForNextLevel(requestedLevel: Int) = levelingExp[requestedLevel] - return 0 + fun getExpForLevel(requestedLevel: Int): Long { + var total = 0L + var level = 0 + for (levelXp in levelingExp) { + total += levelXp + level++ + if (level == requestedLevel) { + return total + } } - // TODO create additional event - fun getExpForSkill(skillName: String) = skillExp[skillName.lowercase()] ?: 0 - - private val levelingExp = listOf( - 50, - 125, - 200, - 300, - 500, - 750, - 1000, - 1500, - 2000, - 3500, - 5000, - 7500, - 10000, - 15000, - 20000, - 30000, - 50000, - 75000, - 100000, - 200000, - 300000, - 400000, - 500000, - 600000, - 700000, - 800000, - 900000, - 1000000, - 1100000, - 1200000, - 1300000, - 1400000, - 1500000, - 1600000, - 1700000, - 1800000, - 1900000, - 2000000, - 2100000, - 2200000, - 2300000, - 2400000, - 2500000, - 2600000, - 2750000, - 2900000, - 3100000, - 3400000, - 3700000, - 4000000, - 4300000, - 4600000, - 4900000, - 5200000, - 5500000, - 5800000, - 6100000, - 6400000, - 6700000, - 7000000 - ) + return 0 } + + // TODO create additional event + fun getExpForSkill(skillName: String) = skillExp[skillName.lowercase()] ?: 0 + + private val levelingExp = listOf( + 50, + 125, + 200, + 300, + 500, + 750, + 1000, + 1500, + 2000, + 3500, + 5000, + 7500, + 10000, + 15000, + 20000, + 30000, + 50000, + 75000, + 100000, + 200000, + 300000, + 400000, + 500000, + 600000, + 700000, + 800000, + 900000, + 1000000, + 1100000, + 1200000, + 1300000, + 1400000, + 1500000, + 1600000, + 1700000, + 1800000, + 1900000, + 2000000, + 2100000, + 2200000, + 2300000, + 2400000, + 2500000, + 2600000, + 2750000, + 2900000, + 3100000, + 3400000, + 3700000, + 4000000, + 4300000, + 4600000, + 4900000, + 5200000, + 5500000, + 5800000, + 6100000, + 6400000, + 6700000, + 7000000 + ) } diff --git a/src/main/java/at/hannibal2/skyhanni/data/mob/MobData.kt b/src/main/java/at/hannibal2/skyhanni/data/mob/MobData.kt index 59cacde87..4eb79d6de 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/mob/MobData.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/mob/MobData.kt @@ -19,7 +19,6 @@ object MobData { val entityList get() = this.flatMap { listOf(it.baseEntity) + (it.extraEntities) } } - val players = MobSet() val displayNPCs = MobSet() val skyblockMobs = MobSet() diff --git a/src/main/java/at/hannibal2/skyhanni/data/mob/MobDetection.kt b/src/main/java/at/hannibal2/skyhanni/data/mob/MobDetection.kt index 0c59a72ac..c1e17f06b 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/mob/MobDetection.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/mob/MobDetection.kt @@ -3,7 +3,6 @@ package at.hannibal2.skyhanni.data.mob import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.api.event.HandleEvent import at.hannibal2.skyhanni.data.IslandType -import at.hannibal2.skyhanni.data.mob.MobData.logger import at.hannibal2.skyhanni.data.mob.MobFilter.isDisplayNPC import at.hannibal2.skyhanni.data.mob.MobFilter.isRealPlayer import at.hannibal2.skyhanni.data.mob.MobFilter.isSkyBlockMob @@ -133,7 +132,7 @@ object MobDetection { private fun getRetry(entity: EntityLivingBase) = MobData.retries[entity.entityId] /** @return always true */ - private fun mobDetectionError(string: String) = logger.log(string).let { true } + private fun mobDetectionError(string: String) = MobData.logger.log(string).let { true } /**@return a false means that it should try again (later)*/ private fun entitySpawn(entity: EntityLivingBase, roughType: Mob.Type): Boolean { @@ -267,7 +266,7 @@ object MobDetection { val entity = retry.entity if (retry.times == MAX_RETRIES) { - logger.log( + MobData.logger.log( "`${retry.entity.name}`${retry.entity.entityId} missed {\n " + "is already Found: ${MobData.entityToMob[retry.entity] != null})." + "\n Position: ${retry.entity.getLorenzVec()}\n " diff --git a/src/main/java/at/hannibal2/skyhanni/features/chat/Translator.kt b/src/main/java/at/hannibal2/skyhanni/features/chat/Translator.kt index 683fe1857..2d3f3aa85 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/chat/Translator.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/chat/Translator.kt @@ -3,6 +3,7 @@ package at.hannibal2.skyhanni.features.chat import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.SkyHanniMod.Companion.coroutineScope import at.hannibal2.skyhanni.events.LorenzChatEvent +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.APIUtil import at.hannibal2.skyhanni.utils.ChatUtils import at.hannibal2.skyhanni.utils.ConditionalUtils.transformIf @@ -21,7 +22,8 @@ import java.net.URLDecoder import java.net.URLEncoder // TODO split into two classes: TranslatorCommand and GoogleTranslator. only communicates via getTranslationFromEnglish and getTranslationToEnglish -class Translator { +@SkyHanniModule +object Translator { private val messageContentRegex = Regex(".*: (.*)") @@ -49,108 +51,105 @@ class Translator { return style } - companion object { - - private val config get() = SkyHanniMod.feature.chat - - /* - * Simplified version of the JSON response: - * [ - * [ - * [ - * 'translated sentence one with a space after the punctuation. ' - * 'original sentence one without a space after the punctuation.' - * ], - * [ - * 'translated sentence two without punctuation bc it's last' - * 'original sentence two without punctuation' - * ] - * ], - * null, - * '"target language as a two-letter code following ISO 639-1"', - * ] - */ - - private fun getJSONResponse(urlString: String) = - APIUtil.getJSONResponseAsElement(urlString, false, "Google Translate API") - - private fun getTranslationToEnglish(message: String): String { - val url = - "https://translate.googleapis.com/translate_a/single?client=gtx&sl=auto&tl=en&dt=t&q=" + - URLEncoder.encode(message, "UTF-8") - - var messageToSend = "" - val layer1 = getJSONResponse(url).asJsonArray - if (layer1.size() <= 2) return "Error!" - - val language = layer1[2].toString() - if (language == "\"en\"") return "Unable to translate!" - if (language.length != 4) return "Error!" - - val layer2 = try { - layer1[0] as JsonArray - } catch (_: Exception) { - return "Error!" - } + private val config get() = SkyHanniMod.feature.chat + + /* + * Simplified version of the JSON response: + * [ + * [ + * [ + * 'translated sentence one with a space after the punctuation. ' + * 'original sentence one without a space after the punctuation.' + * ], + * [ + * 'translated sentence two without punctuation bc it's last' + * 'original sentence two without punctuation' + * ] + * ], + * null, + * '"target language as a two-letter code following ISO 639-1"', + * ] + */ + + private fun getJSONResponse(urlString: String) = + APIUtil.getJSONResponseAsElement(urlString, false, "Google Translate API") + + private fun getTranslationToEnglish(message: String): String { + val url = + "https://translate.googleapis.com/translate_a/single?client=gtx&sl=auto&tl=en&dt=t&q=" + + URLEncoder.encode(message, "UTF-8") + + var messageToSend = "" + val layer1 = getJSONResponse(url).asJsonArray + if (layer1.size() <= 2) return "Error!" + + val language = layer1[2].toString() + if (language == "\"en\"") return "Unable to translate!" + if (language.length != 4) return "Error!" + + val layer2 = try { + layer1[0] as JsonArray + } catch (_: Exception) { + return "Error!" + } - for (layer3 in layer2) { - val arrayLayer3 = layer3 as? JsonArray ?: continue - val sentence = arrayLayer3[0].toString() + for (layer3 in layer2) { + val arrayLayer3 = layer3 as? JsonArray ?: continue + val sentence = arrayLayer3[0].toString() + val sentenceWithoutQuotes = sentence.substring(1, sentence.length - 1) + messageToSend = "$messageToSend$sentenceWithoutQuotes" + } + messageToSend = "$messageToSend §7(Language: $language)" + + return URLDecoder.decode(messageToSend, "UTF-8").replace("\\", "") + } + + private fun getTranslationFromEnglish(message: String, lang: String): String { + val url = + "https://translate.googleapis.com/translate_a/single?client=gtx&sl=en&tl=$lang&dt=t&q=" + + URLEncoder.encode(message, "UTF-8") + + val layer1 = getJSONResponse(url).asJsonArray + if (layer1.size() < 1) return "Error!" + val layer2 = layer1[0] as? JsonArray + + val firstSentence = (layer2?.get(0) as? JsonArray)?.get(0).toString() + var messageToSend = firstSentence.substring(0, firstSentence.length - 1) + if (layer2 != null) { + for (sentenceIndex in 1..<layer2.size()) { + val sentence = (layer2.get(sentenceIndex) as JsonArray).get(0).toString() val sentenceWithoutQuotes = sentence.substring(1, sentence.length - 1) messageToSend = "$messageToSend$sentenceWithoutQuotes" } - messageToSend = "$messageToSend §7(Language: $language)" + } // The first translated sentence only has 1 extra char at the end, but sentences after it need 1 at the front and 1 at the end removed in the substring + messageToSend = messageToSend.substring(1, messageToSend.length) + return URLDecoder.decode(messageToSend, "UTF-8").replace("\\", "") + } - return URLDecoder.decode(messageToSend, "UTF-8").replace("\\", "") - } + fun toEnglish(args: Array<String>) { + val message = args.joinToString(" ").removeColor() - private fun getTranslationFromEnglish(message: String, lang: String): String { - val url = - "https://translate.googleapis.com/translate_a/single?client=gtx&sl=en&tl=$lang&dt=t&q=" + - URLEncoder.encode(message, "UTF-8") - - val layer1 = getJSONResponse(url).asJsonArray - if (layer1.size() < 1) return "Error!" - val layer2 = layer1[0] as? JsonArray - - val firstSentence = (layer2?.get(0) as? JsonArray)?.get(0).toString() - var messageToSend = firstSentence.substring(0, firstSentence.length - 1) - if (layer2 != null) { - for (sentenceIndex in 1..<layer2.size()) { - val sentence = (layer2.get(sentenceIndex) as JsonArray).get(0).toString() - val sentenceWithoutQuotes = sentence.substring(1, sentence.length - 1) - messageToSend = "$messageToSend$sentenceWithoutQuotes" - } - } // The first translated sentence only has 1 extra char at the end, but sentences after it need 1 at the front and 1 at the end removed in the substring - messageToSend = messageToSend.substring(1, messageToSend.length) - return URLDecoder.decode(messageToSend, "UTF-8").replace("\\", "") + coroutineScope.launch { + val translation = getTranslationToEnglish(message) + if (translation == "Unable to translate!") ChatUtils.userError("Unable to translate message :( (is it in English?)") + else ChatUtils.chat("Found translation: §f$translation") } + } - fun toEnglish(args: Array<String>) { - val message = args.joinToString(" ").removeColor() - - coroutineScope.launch { - val translation = getTranslationToEnglish(message) - if (translation == "Unable to translate!") ChatUtils.userError("Unable to translate message :( (is it in English?)") - else ChatUtils.chat("Found translation: §f$translation") - } + fun fromEnglish(args: Array<String>) { + if (args.size < 2 || args[0].length != 2) { // args[0] is the language code + ChatUtils.userError("Usage: /shcopytranslation <two letter language code (at the end of a translation)> <message>") + return } + val language = args[0] + val message = args.drop(1).joinToString(" ") - fun fromEnglish(args: Array<String>) { - if (args.size < 2 || args[0].length != 2) { // args[0] is the language code - ChatUtils.userError("Usage: /shcopytranslation <two letter language code (at the end of a translation)> <message>") - return - } - val language = args[0] - val message = args.drop(1).joinToString(" ") - - coroutineScope.launch { - val translation = getTranslationFromEnglish(message, language) - ChatUtils.chat("Copied translation to clipboard: §f$translation") - OSUtils.copyToClipboard(translation) - } + coroutineScope.launch { + val translation = getTranslationFromEnglish(message, language) + ChatUtils.chat("Copied translation to clipboard: §f$translation") + OSUtils.copyToClipboard(translation) } - - fun isEnabled() = config.translator } + + fun isEnabled() = config.translator } 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 33bb20a52..d41431726 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 @@ -74,6 +74,7 @@ object DamageIndicatorManager { private val enderSlayerHitsNumberPattern = ".* §[5fd]§l(?<hits>\\d+) Hits?".toPattern() + private var data = mapOf<UUID, EntityData>() private val damagePattern = "[✧✯]?(\\d+[⚔+✧❤♞☄✷ﬗ✯]*)".toPattern() diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/diana/BurrowWarpHelper.kt b/src/main/java/at/hannibal2/skyhanni/features/event/diana/BurrowWarpHelper.kt index be8d77a6a..bf362d918 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/diana/BurrowWarpHelper.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/diana/BurrowWarpHelper.kt @@ -23,6 +23,7 @@ import kotlin.time.Duration.Companion.seconds object BurrowWarpHelper { private val config get() = SkyHanniMod.feature.event.diana + var currentWarp: WarpPoint? = null private var lastWarpTime = SimpleTimeMark.farPast() diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/FarmingWeightDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/FarmingWeightDisplay.kt index 0aac3e747..03c35ce27 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/FarmingWeightDisplay.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/FarmingWeightDisplay.kt @@ -18,6 +18,7 @@ import at.hannibal2.skyhanni.features.garden.CropType import at.hannibal2.skyhanni.features.garden.GardenAPI import at.hannibal2.skyhanni.features.garden.farming.GardenCropSpeed.getSpeed import at.hannibal2.skyhanni.features.garden.pests.PestType +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.test.command.ErrorManager import at.hannibal2.skyhanni.utils.APIUtil import at.hannibal2.skyhanni.utils.ChatUtils @@ -39,7 +40,8 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import kotlin.time.Duration.Companion.minutes import kotlin.time.Duration.Companion.seconds -class FarmingWeightDisplay { +@SkyHanniModule +object FarmingWeightDisplay { @SubscribeEvent fun onRenderOverlay(event: GuiRenderEvent) { @@ -102,491 +104,487 @@ class FarmingWeightDisplay { event.move(34, "garden.eliteFarmingWeights.ETAGoalRank", "garden.eliteFarmingWeights.etaGoalRank") } - companion object { - - private val config get() = GardenAPI.config.eliteFarmingWeights - private val localCounter = mutableMapOf<CropType, Long>() - - private var display = emptyList<Renderable>() - private var profileId = "" - private var lastLeaderboardUpdate = SimpleTimeMark.farPast() - private var apiError = false - private var leaderboardPosition = -1 - private var weight = -1.0 - private var localWeight = 0.0 - private var weightPerSecond = -1.0 - private var weightNeedsRecalculating = false - private var isLoadingWeight = false - private var isLoadingLeaderboard = false - private var rankGoal = -1 + private val config get() = GardenAPI.config.eliteFarmingWeights + private val localCounter = mutableMapOf<CropType, Long>() + + private var display = emptyList<Renderable>() + private var profileId = "" + private var lastLeaderboardUpdate = SimpleTimeMark.farPast() + private var apiError = false + private var leaderboardPosition = -1 + private var weight = -1.0 + private var localWeight = 0.0 + private var weightPerSecond = -1.0 + private var weightNeedsRecalculating = false + private var isLoadingWeight = false + private var isLoadingLeaderboard = false + private var rankGoal = -1 + + private var nextPlayers = mutableListOf<UpcomingLeaderboardPlayer>() + private val nextPlayer get() = nextPlayers.firstOrNull() + + private val recalculate by lazy { + ({ + resetData() + }) + } - private var nextPlayers = mutableListOf<UpcomingLeaderboardPlayer>() - private val nextPlayer get() = nextPlayers.firstOrNull() + private val eliteWeightApiGson by lazy { + BaseGsonBuilder.gson() + .registerTypeAdapter(CropType::class.java, SkyHanniTypeAdapters.CROP_TYPE.nullSafe()) + .registerTypeAdapter(PestType::class.java, SkyHanniTypeAdapters.PEST_TYPE.nullSafe()) + .create() + } - private val recalculate by lazy { - ({ - resetData() - }) - } + private val errorMessage by lazy { + listOf( + Renderable.clickAndHover( + "§cFarming Weight error: Cannot load", + listOf("§eClick here to reload the data right now!"), + onClick = recalculate + ), Renderable.clickAndHover( + "§cdata from Elite Farmers!", + listOf("§eClick here to reload the data right now!"), + onClick = recalculate + ), Renderable.clickAndHover( + "§eRejoin the garden or", + listOf("§eClick here to reload the data right now!"), + onClick = recalculate + ), Renderable.clickAndHover( + "§eclick here to fix it.", + listOf("§eClick here to reload the data right now!"), + onClick = recalculate + ) + ) + } - private val eliteWeightApiGson by lazy { - BaseGsonBuilder.gson() - .registerTypeAdapter(CropType::class.java, SkyHanniTypeAdapters.CROP_TYPE.nullSafe()) - .registerTypeAdapter(PestType::class.java, SkyHanniTypeAdapters.PEST_TYPE.nullSafe()) - .create() - } + private var lastOpenWebsite = SimpleTimeMark.farPast() - private val errorMessage by lazy { - listOf( - Renderable.clickAndHover( - "§cFarming Weight error: Cannot load", - listOf("§eClick here to reload the data right now!"), - onClick = recalculate - ), Renderable.clickAndHover( - "§cdata from Elite Farmers!", - listOf("§eClick here to reload the data right now!"), - onClick = recalculate - ), Renderable.clickAndHover( - "§eRejoin the garden or", - listOf("§eClick here to reload the data right now!"), - onClick = recalculate - ), Renderable.clickAndHover( - "§eclick here to fix it.", - listOf("§eClick here to reload the data right now!"), - onClick = recalculate - ) - ) + private fun update() { + if (!isEnabled()) return + if (apiError) { + display = errorMessage + return } - private var lastOpenWebsite = SimpleTimeMark.farPast() - - private fun update() { - if (!isEnabled()) return - if (apiError) { - display = errorMessage - return - } + if (weight == -1.0) { + if (!isLoadingWeight) { + val localProfile = HypixelData.profileName - if (weight == -1.0) { - if (!isLoadingWeight) { - val localProfile = HypixelData.profileName - - isLoadingWeight = true - if (display.isEmpty()) { - display = Renderable.singeltonString("§6Farming Weight§7: §eLoading..") - } - SkyHanniMod.coroutineScope.launch { - loadWeight(localProfile) - isLoadingWeight = false - } + isLoadingWeight = true + if (display.isEmpty()) { + display = Renderable.singeltonString("§6Farming Weight§7: §eLoading..") + } + SkyHanniMod.coroutineScope.launch { + loadWeight(localProfile) + isLoadingWeight = false } - return } + return + } - val weight = getWeight() + val weight = getWeight() - if (rankGoal == -1) rankGoal = getRankGoal() - val leaderboard = getLeaderboard() + if (rankGoal == -1) rankGoal = getRankGoal() + val leaderboard = getLeaderboard() - val list = mutableListOf<Renderable>() - list.add( - Renderable.clickAndHover( - "§6Farming Weight§7: $weight$leaderboard", - listOf("§eClick to open your Farming Profile."), onClick = { - openWebsite(LorenzUtils.getPlayerName()) - } - ) + val list = mutableListOf<Renderable>() + list.add( + Renderable.clickAndHover( + "§6Farming Weight§7: $weight$leaderboard", + listOf("§eClick to open your Farming Profile."), + onClick = { openWebsite(LorenzUtils.getPlayerName()) } ) + ) - if (isEtaEnabled() && (weightPerSecond != -1.0 || config.overtakeETAAlways)) { - getETA()?.let { - list.add(it) - } + if (isEtaEnabled() && (weightPerSecond != -1.0 || config.overtakeETAAlways)) { + getETA()?.let { + list.add(it) } - display = list } + display = list + } - private fun getLeaderboard(): String { - if (!config.leaderboard) return "" - - // Fetching new leaderboard position every 10.5 minutes - if (lastLeaderboardUpdate.passedSince() > 10.5.minutes) { - loadLeaderboardIfAble() - } + private fun getLeaderboard(): String { + if (!config.leaderboard) return "" - return if (leaderboardPosition != -1) { - val format = leaderboardPosition.addSeparators() - " §7[§b#$format§7]" - } else { - if (isLoadingLeaderboard) " §7[§b#?§7]" else "" - } + // Fetching new leaderboard position every 10.5 minutes + if (lastLeaderboardUpdate.passedSince() > 10.5.minutes) { + loadLeaderboardIfAble() } - private fun getWeight(): String { - if (weightNeedsRecalculating) { - val values = calculateCollectionWeight().values - if (values.isNotEmpty()) { - localWeight = values.sum() - weightNeedsRecalculating = false - } - } - - val totalWeight = (localWeight + weight) - return "§e" + totalWeight.round(2).addSeparators() + return if (leaderboardPosition != -1) { + val format = leaderboardPosition.addSeparators() + " §7[§b#$format§7]" + } else { + if (isLoadingLeaderboard) " §7[§b#?§7]" else "" } + } - private fun getRankGoal(): Int { - val value = config.etaGoalRank - var goal = 10000 - - // Check that the provided string is valid - val parsed = value.toIntOrNull() ?: 0 - if (parsed < 1 || parsed > goal) { - ChatUtils.chatAndOpenConfig( - "Invalid Farming Weight Overtake Goal! Click here to edit the Overtake Goal config value " + - "to a valid number [1-10000] to use this feature!", - GardenAPI.config.eliteFarmingWeights::etaGoalRank - ) - config.etaGoalRank = goal.toString() - } else { - goal = parsed - } - - // Fetch the positions again if the goal was changed - if (rankGoal != goal) { - loadLeaderboardIfAble() + private fun getWeight(): String { + if (weightNeedsRecalculating) { + val values = calculateCollectionWeight().values + if (values.isNotEmpty()) { + localWeight = values.sum() + weightNeedsRecalculating = false } - - return goal } - private fun getETA(): Renderable? { - if (weight < 0) return null + val totalWeight = (localWeight + weight) + return "§e" + totalWeight.round(2).addSeparators() + } - val nextPlayer = nextPlayer ?: return Renderable.clickAndHover( - "§cWaiting for leaderboard update...", - listOf("§eClick here to load new data right now!"), - onClick = recalculate + private fun getRankGoal(): Int { + val value = config.etaGoalRank + var goal = 10000 + + // Check that the provided string is valid + val parsed = value.toIntOrNull() ?: 0 + if (parsed < 1 || parsed > goal) { + ChatUtils.chatAndOpenConfig( + "Invalid Farming Weight Overtake Goal! Click here to edit the Overtake Goal config value " + + "to a valid number [1-10000] to use this feature!", + GardenAPI.config.eliteFarmingWeights::etaGoalRank ) - val showRankGoal = leaderboardPosition == -1 || leaderboardPosition > rankGoal - var nextName = - if (showRankGoal) "#$rankGoal" else nextPlayer.name + config.etaGoalRank = goal.toString() + } else { + goal = parsed + } - val totalWeight = (localWeight + weight) - var weightUntilOvertake = nextPlayer.weight - totalWeight + // Fetch the positions again if the goal was changed + if (rankGoal != goal) { + loadLeaderboardIfAble() + } - if (weightUntilOvertake < 0) { - if (weightPerSecond > 0) { - farmingChatMessage("You passed §b$nextName §ein the Farming Weight Leaderboard!") - } + return goal + } - // Lower leaderboard position - if (leaderboardPosition == -1) { - leaderboardPosition = 10000 - } else { - leaderboardPosition-- - } - GardenAPI.storage?.farmingWeight?.lastFarmingWeightLeaderboard = - leaderboardPosition + private fun getETA(): Renderable? { + if (weight < 0) return null - // Remove passed player to present the next one - nextPlayers.removeFirst() + val nextPlayer = nextPlayer ?: return Renderable.clickAndHover( + "§cWaiting for leaderboard update...", + listOf("§eClick here to load new data right now!"), + onClick = recalculate + ) + val showRankGoal = leaderboardPosition == -1 || leaderboardPosition > rankGoal + var nextName = + if (showRankGoal) "#$rankGoal" else nextPlayer.name - // Display waiting message if nextPlayers list is empty - // Update values to next player - nextName = nextPlayer.name - weightUntilOvertake = nextPlayer.weight - totalWeight - } + val totalWeight = (localWeight + weight) + var weightUntilOvertake = nextPlayer.weight - totalWeight - if (nextPlayer.weight == 0.0) { - return Renderable.clickAndHover( - "§cRejoin the garden to show ETA!", - listOf("Click here to calculate the data right now!"), - onClick = recalculate - ) + if (weightUntilOvertake < 0) { + if (weightPerSecond > 0) { + farmingChatMessage("You passed §b$nextName §ein the Farming Weight Leaderboard!") } - val timeFormat = if (weightPerSecond != -1.0) { - val timeTillOvertake = (weightUntilOvertake / weightPerSecond) * 1000 - val format = TimeUtils.formatDuration(timeTillOvertake.toLong()) - " §7(§b$format§7)" - } else "" - - val weightFormat = weightUntilOvertake.round(2).addSeparators() - val text = "§e$weightFormat$timeFormat §7behind §b$nextName" - return if (showRankGoal) { - Renderable.string(text) + // Lower leaderboard position + if (leaderboardPosition == -1) { + leaderboardPosition = 10000 } else { - Renderable.clickAndHover( - text, - listOf("§eClick to open the Farming Profile of §b$nextName."), - onClick = { openWebsite(nextName) } - ) + leaderboardPosition-- } - } + GardenAPI.storage?.farmingWeight?.lastFarmingWeightLeaderboard = + leaderboardPosition - private fun resetData() { - apiError = false - // We ask both api endpoints after every world switch - weight = -1.0 - weightPerSecond = -1.0 + // Remove passed player to present the next one + nextPlayers.removeFirst() - leaderboardPosition = -1 - weightNeedsRecalculating = true - lastLeaderboardUpdate = SimpleTimeMark.farPast() - - nextPlayers.clear() - rankGoal = -1 + // Display waiting message if nextPlayers list is empty + // Update values to next player + nextName = nextPlayer.name + weightUntilOvertake = nextPlayer.weight - totalWeight + } - localCounter.clear() + if (nextPlayer.weight == 0.0) { + return Renderable.clickAndHover( + "§cRejoin the garden to show ETA!", + listOf("Click here to calculate the data right now!"), + onClick = recalculate + ) } - private fun farmingChatMessage(message: String) { - ChatUtils.hoverableChat( - message, - listOf( - "§eClick to open your Farming Weight", - "§eprofile on §celitebot.dev", - ), - "shfarmingprofile ${LorenzUtils.getPlayerName()}" + val timeFormat = if (weightPerSecond != -1.0) { + val timeTillOvertake = (weightUntilOvertake / weightPerSecond) * 1000 + val format = TimeUtils.formatDuration(timeTillOvertake.toLong()) + " §7(§b$format§7)" + } else "" + + val weightFormat = weightUntilOvertake.round(2).addSeparators() + val text = "§e$weightFormat$timeFormat §7behind §b$nextName" + return if (showRankGoal) { + Renderable.string(text) + } else { + Renderable.clickAndHover( + text, + listOf("§eClick to open the Farming Profile of §b$nextName."), + onClick = { openWebsite(nextName) } ) } + } - private fun isEnabled() = ((OutsideSbFeature.FARMING_WEIGHT.isSelected() && !LorenzUtils.inSkyBlock) || - (LorenzUtils.inSkyBlock && (GardenAPI.inGarden() || config.showOutsideGarden))) && config.display + private fun resetData() { + apiError = false + // We ask both api endpoints after every world switch + weight = -1.0 + weightPerSecond = -1.0 - private fun isEtaEnabled() = config.overtakeETA + leaderboardPosition = -1 + weightNeedsRecalculating = true + lastLeaderboardUpdate = SimpleTimeMark.farPast() + + nextPlayers.clear() + rankGoal = -1 - fun addCrop(crop: CropType, addedCounter: Int) { - val before = getExactWeight() - localCounter[crop] = crop.getLocalCounter() + addedCounter - val after = getExactWeight() + localCounter.clear() + } - updateWeightPerSecond(crop, before, after, addedCounter) + private fun farmingChatMessage(message: String) { + ChatUtils.hoverableChat( + message, + listOf( + "§eClick to open your Farming Weight", + "§eprofile on §celitebot.dev", + ), + "shfarmingprofile ${LorenzUtils.getPlayerName()}" + ) + } - weightNeedsRecalculating = true - } + private fun isEnabled() = ((OutsideSbFeature.FARMING_WEIGHT.isSelected() && !LorenzUtils.inSkyBlock) || + (LorenzUtils.inSkyBlock && (GardenAPI.inGarden() || config.showOutsideGarden))) && config.display - private fun updateWeightPerSecond(crop: CropType, before: Double, after: Double, diff: Int) { - val speed = crop.getSpeed() ?: return - val weightDiff = (after - before) * 1000 - weightPerSecond = weightDiff / diff * speed / 1000 - } + private fun isEtaEnabled() = config.overtakeETA - private fun getExactWeight(): Double { - val values = calculateCollectionWeight().values - return if (values.isNotEmpty()) { - values.sum() - } else 0.0 - } + fun addCrop(crop: CropType, addedCounter: Int) { + val before = getExactWeight() + localCounter[crop] = crop.getLocalCounter() + addedCounter + val after = getExactWeight() - private fun loadLeaderboardIfAble() { - if (isLoadingLeaderboard) return - isLoadingLeaderboard = true + updateWeightPerSecond(crop, before, after, addedCounter) - SkyHanniMod.coroutineScope.launch { - val wasNotLoaded = leaderboardPosition == -1 - leaderboardPosition = loadLeaderboardPosition() - if (wasNotLoaded && config.showLbChange) { - checkOffScreenLeaderboardChanges() - } - GardenAPI.storage?.farmingWeight?.lastFarmingWeightLeaderboard = - leaderboardPosition - lastLeaderboardUpdate = SimpleTimeMark.now() - isLoadingLeaderboard = false - } - } + weightNeedsRecalculating = true + } - private fun checkOffScreenLeaderboardChanges() { - val profileSpecific = ProfileStorageData.profileSpecific ?: return - val oldPosition = profileSpecific.garden.farmingWeight.lastFarmingWeightLeaderboard + private fun updateWeightPerSecond(crop: CropType, before: Double, after: Double, diff: Int) { + val speed = crop.getSpeed() ?: return + val weightDiff = (after - before) * 1000 + weightPerSecond = weightDiff / diff * speed / 1000 + } - if (oldPosition <= 0) return - if (leaderboardPosition <= 0) return + private fun getExactWeight(): Double { + val values = calculateCollectionWeight().values + return if (values.isNotEmpty()) { + values.sum() + } else 0.0 + } - val diff = leaderboardPosition - oldPosition - if (diff == 0) return + private fun loadLeaderboardIfAble() { + if (isLoadingLeaderboard) return + isLoadingLeaderboard = true - if (diff > 0) { - showLbChange("§cdropped ${StringUtils.pluralize(diff, "place", withNumber = true)}", oldPosition) - } else { - showLbChange("§arisen ${StringUtils.pluralize(-diff, "place", withNumber = true)}", oldPosition) + SkyHanniMod.coroutineScope.launch { + val wasNotLoaded = leaderboardPosition == -1 + leaderboardPosition = loadLeaderboardPosition() + if (wasNotLoaded && config.showLbChange) { + checkOffScreenLeaderboardChanges() } + GardenAPI.storage?.farmingWeight?.lastFarmingWeightLeaderboard = + leaderboardPosition + lastLeaderboardUpdate = SimpleTimeMark.now() + isLoadingLeaderboard = false } + } - private fun showLbChange(direction: String, oldPosition: Int) { - farmingChatMessage( - "§7Since your last visit to the §aGarden§7, " + - "you have $direction §7on the §dFarming Leaderboard§7. " + - "§7(§e#${oldPosition.addSeparators()} §7-> §e#${leaderboardPosition.addSeparators()}§7)" - ) + private fun checkOffScreenLeaderboardChanges() { + val profileSpecific = ProfileStorageData.profileSpecific ?: return + val oldPosition = profileSpecific.garden.farmingWeight.lastFarmingWeightLeaderboard + + if (oldPosition <= 0) return + if (leaderboardPosition <= 0) return + + val diff = leaderboardPosition - oldPosition + if (diff == 0) return + + if (diff > 0) { + showLbChange("§cdropped ${StringUtils.pluralize(diff, "place", withNumber = true)}", oldPosition) + } else { + showLbChange("§arisen ${StringUtils.pluralize(-diff, "place", withNumber = true)}", oldPosition) } + } - private fun loadLeaderboardPosition(): Int { - val uuid = LorenzUtils.getPlayerUuid() + private fun showLbChange(direction: String, oldPosition: Int) { + farmingChatMessage( + "§7Since your last visit to the §aGarden§7, " + + "you have $direction §7on the §dFarming Leaderboard§7. " + + "§7(§e#${oldPosition.addSeparators()} §7-> §e#${leaderboardPosition.addSeparators()}§7)" + ) + } - val includeUpcoming = if (isEtaEnabled()) "?includeUpcoming=true" else "" - val goalRank = getRankGoal() + 1 // API returns upcoming players as if you were at this rank already - val atRank = if (isEtaEnabled() && goalRank != 10001) "&atRank=$goalRank" else "" + private fun loadLeaderboardPosition(): Int { + val uuid = LorenzUtils.getPlayerUuid() - val url = "https://api.elitebot.dev/leaderboard/rank/farmingweight/$uuid/$profileId$includeUpcoming$atRank" - val apiResponse = APIUtil.getJSONResponse(url) + val includeUpcoming = if (isEtaEnabled()) "?includeUpcoming=true" else "" + val goalRank = getRankGoal() + 1 // API returns upcoming players as if you were at this rank already + val atRank = if (isEtaEnabled() && goalRank != 10001) "&atRank=$goalRank" else "" - try { - val apiData = toEliteLeaderboardJson(apiResponse).data + val url = "https://api.elitebot.dev/leaderboard/rank/farmingweight/$uuid/$profileId$includeUpcoming$atRank" + val apiResponse = APIUtil.getJSONResponse(url) - if (isEtaEnabled()) { - nextPlayers.clear() - apiData.upcomingPlayers.forEach { nextPlayers.add(it) } - } + try { + val apiData = toEliteLeaderboardJson(apiResponse).data - return apiData.rank - } catch (e: Exception) { - ErrorManager.logErrorWithData( - e, "Error getting weight leaderboard position", - "url" to url, - "apiResponse" to apiResponse - ) + if (isEtaEnabled()) { + nextPlayers.clear() + apiData.upcomingPlayers.forEach { nextPlayers.add(it) } } - return -1 - } - private fun toEliteLeaderboardJson(obj: JsonObject): EliteLeaderboardJson { - val jsonObject = JsonObject() - jsonObject.add("data", obj) - return eliteWeightApiGson.fromJson<EliteLeaderboardJson>(jsonObject) + return apiData.rank + } catch (e: Exception) { + ErrorManager.logErrorWithData( + e, "Error getting weight leaderboard position", + "url" to url, + "apiResponse" to apiResponse + ) } + return -1 + } - private fun loadWeight(localProfile: String) { - val uuid = LorenzUtils.getPlayerUuid() - val url = "https://api.elitebot.dev/weight/$uuid" - val apiResponse = APIUtil.getJSONResponse(url) + private fun toEliteLeaderboardJson(obj: JsonObject): EliteLeaderboardJson { + val jsonObject = JsonObject() + jsonObject.add("data", obj) + return eliteWeightApiGson.fromJson<EliteLeaderboardJson>(jsonObject) + } - var error: Throwable? = null + private fun loadWeight(localProfile: String) { + val uuid = LorenzUtils.getPlayerUuid() + val url = "https://api.elitebot.dev/weight/$uuid" + val apiResponse = APIUtil.getJSONResponse(url) - try { + var error: Throwable? = null - val apiData = eliteWeightApiGson.fromJson<ElitePlayerWeightJson>(apiResponse) + try { - val selectedProfileId = apiData.selectedProfileId - var selectedProfileEntry = apiData.profiles.find { it.profileId == selectedProfileId } + val apiData = eliteWeightApiGson.fromJson<ElitePlayerWeightJson>(apiResponse) - if (selectedProfileEntry == null || (selectedProfileEntry.profileName.lowercase() != localProfile && localProfile != "")) { - selectedProfileEntry = apiData.profiles.find { it.profileName.lowercase() == localProfile } - } + val selectedProfileId = apiData.selectedProfileId + var selectedProfileEntry = apiData.profiles.find { it.profileId == selectedProfileId } - if (selectedProfileEntry != null) { - profileId = selectedProfileEntry.profileId - weight = selectedProfileEntry.totalWeight + if (selectedProfileEntry == null || (selectedProfileEntry.profileName.lowercase() != localProfile && localProfile != "")) { + selectedProfileEntry = apiData.profiles.find { it.profileName.lowercase() == localProfile } + } - localCounter.clear() - weightNeedsRecalculating = true - return - } + if (selectedProfileEntry != null) { + profileId = selectedProfileEntry.profileId + weight = selectedProfileEntry.totalWeight - } catch (e: Exception) { - error = e + localCounter.clear() + weightNeedsRecalculating = true + return } - apiError = true - ErrorManager.logErrorWithData( - error ?: IllegalStateException("Error loading user farming weight"), - "Error loading user farming weight\n" + - "§eLoading the farming weight data from elitebot.dev failed!\n" + - "§eYou can re-enter the garden to try to fix the problem.\n" + - "§cIf this message repeats, please report it on Discord!\n", - "url" to url, - "apiResponse" to apiResponse, - "localProfile" to localProfile - ) + } catch (e: Exception) { + error = e } + apiError = true + + ErrorManager.logErrorWithData( + error ?: IllegalStateException("Error loading user farming weight"), + "Error loading user farming weight\n" + + "§eLoading the farming weight data from elitebot.dev failed!\n" + + "§eYou can re-enter the garden to try to fix the problem.\n" + + "§cIf this message repeats, please report it on Discord!\n", + "url" to url, + "apiResponse" to apiResponse, + "localProfile" to localProfile + ) + } - private fun calculateCollectionWeight(): MutableMap<CropType, Double> { - val weightPerCrop = mutableMapOf<CropType, Double>() - var totalWeight = 0.0 - for (crop in CropType.entries) { - val weight = crop.getLocalCounter() / crop.getFactor() - weightPerCrop[crop] = weight - totalWeight += weight - } - if (totalWeight > 0) { - weightPerCrop[CropType.MUSHROOM] = specialMushroomWeight(weightPerCrop, totalWeight) - } - return weightPerCrop + private fun calculateCollectionWeight(): MutableMap<CropType, Double> { + val weightPerCrop = mutableMapOf<CropType, Double>() + var totalWeight = 0.0 + for (crop in CropType.entries) { + val weight = crop.getLocalCounter() / crop.getFactor() + weightPerCrop[crop] = weight + totalWeight += weight } + if (totalWeight > 0) { + weightPerCrop[CropType.MUSHROOM] = specialMushroomWeight(weightPerCrop, totalWeight) + } + return weightPerCrop + } - private fun specialMushroomWeight(weightPerCrop: MutableMap<CropType, Double>, totalWeight: Double): Double { - val cactusWeight = weightPerCrop[CropType.CACTUS]!! - val sugarCaneWeight = weightPerCrop[CropType.SUGAR_CANE]!! - val doubleBreakRatio = (cactusWeight + sugarCaneWeight) / totalWeight - val normalRatio = (totalWeight - cactusWeight - sugarCaneWeight) / totalWeight + private fun specialMushroomWeight(weightPerCrop: MutableMap<CropType, Double>, totalWeight: Double): Double { + val cactusWeight = weightPerCrop[CropType.CACTUS]!! + val sugarCaneWeight = weightPerCrop[CropType.SUGAR_CANE]!! + val doubleBreakRatio = (cactusWeight + sugarCaneWeight) / totalWeight + val normalRatio = (totalWeight - cactusWeight - sugarCaneWeight) / totalWeight - val mushroomFactor = CropType.MUSHROOM.getFactor() - val mushroomCollection = CropType.MUSHROOM.getLocalCounter() - return doubleBreakRatio * (mushroomCollection / (2 * mushroomFactor)) + normalRatio * (mushroomCollection / mushroomFactor) - } + val mushroomFactor = CropType.MUSHROOM.getFactor() + val mushroomCollection = CropType.MUSHROOM.getLocalCounter() + return doubleBreakRatio * (mushroomCollection / (2 * mushroomFactor)) + normalRatio * (mushroomCollection / mushroomFactor) + } - private fun CropType.getLocalCounter() = localCounter[this] ?: 0L + private fun CropType.getLocalCounter() = localCounter[this] ?: 0L - private fun CropType.getFactor(): Double { - return cropWeight[this] ?: backupCropWeights[this] ?: error("Crop $this not in backupFactors!") - } + private fun CropType.getFactor(): Double { + return cropWeight[this] ?: backupCropWeights[this] ?: error("Crop $this not in backupFactors!") + } - fun lookUpCommand(it: Array<String>) { - val name = if (it.size == 1) it[0] else LorenzUtils.getPlayerName() - openWebsite(name, ignoreCooldown = true) - } + fun lookUpCommand(it: Array<String>) { + val name = if (it.size == 1) it[0] else LorenzUtils.getPlayerName() + openWebsite(name, ignoreCooldown = true) + } - private var lastName = "" + private var lastName = "" - private fun openWebsite(name: String, ignoreCooldown: Boolean = false) { - if (!ignoreCooldown && lastOpenWebsite.passedSince() < 5.seconds && name == lastName) return - lastOpenWebsite = SimpleTimeMark.now() - lastName = name + private fun openWebsite(name: String, ignoreCooldown: Boolean = false) { + if (!ignoreCooldown && lastOpenWebsite.passedSince() < 5.seconds && name == lastName) return + lastOpenWebsite = SimpleTimeMark.now() + lastName = name - OSUtils.openBrowser("https://elitebot.dev/@$name/") - ChatUtils.chat("Opening Farming Profile of player §b$name") - } + OSUtils.openBrowser("https://elitebot.dev/@$name/") + ChatUtils.chat("Opening Farming Profile of player §b$name") + } - private val cropWeight = mutableMapOf<CropType, Double>() - private var attemptingCropWeightFetch = false - private var hasFetchedCropWeights = false - - private fun getCropWeights() { - if (attemptingCropWeightFetch || hasFetchedCropWeights) return - attemptingCropWeightFetch = true - val url = "https://api.elitebot.dev/weights/all" - val apiResponse = APIUtil.getJSONResponse(url) - - try { - val apiData = eliteWeightApiGson.fromJson<EliteWeightsJson>(apiResponse) - apiData.crops - for (crop in apiData.crops) { - cropWeight[crop.key] = crop.value - } - hasFetchedCropWeights = true - } catch (e: Exception) { - ErrorManager.logErrorWithData( - e, "Error getting crop weights from elitebot.dev", - "apiResponse" to apiResponse - ) + private val cropWeight = mutableMapOf<CropType, Double>() + private var attemptingCropWeightFetch = false + private var hasFetchedCropWeights = false + + private fun getCropWeights() { + if (attemptingCropWeightFetch || hasFetchedCropWeights) return + attemptingCropWeightFetch = true + val url = "https://api.elitebot.dev/weights/all" + val apiResponse = APIUtil.getJSONResponse(url) + + try { + val apiData = eliteWeightApiGson.fromJson<EliteWeightsJson>(apiResponse) + apiData.crops + for (crop in apiData.crops) { + cropWeight[crop.key] = crop.value } - } - - // still needed when first joining garden and if they cant make https requests - private val backupCropWeights by lazy { - mapOf( - CropType.WHEAT to 100_000.0, - CropType.CARROT to 302_061.86, - CropType.POTATO to 300_000.0, - CropType.SUGAR_CANE to 200_000.0, - CropType.NETHER_WART to 250_000.0, - CropType.PUMPKIN to 98_284.71, - CropType.MELON to 485_308.47, - CropType.MUSHROOM to 90_178.06, - CropType.COCOA_BEANS to 267_174.04, - CropType.CACTUS to 177_254.45, + hasFetchedCropWeights = true + } catch (e: Exception) { + ErrorManager.logErrorWithData( + e, "Error getting crop weights from elitebot.dev", + "apiResponse" to apiResponse ) } } + + // still needed when first joining garden and if they cant make https requests + private val backupCropWeights by lazy { + mapOf( + CropType.WHEAT to 100_000.0, + CropType.CARROT to 302_061.86, + CropType.POTATO to 300_000.0, + CropType.SUGAR_CANE to 200_000.0, + CropType.NETHER_WART to 250_000.0, + CropType.PUMPKIN to 98_284.71, + CropType.MELON to 485_308.47, + CropType.MUSHROOM to 90_178.06, + CropType.COCOA_BEANS to 267_174.04, + CropType.CACTUS to 177_254.45, + ) + } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardElements.kt b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardElements.kt index 28e5151d4..aae1e7086 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardElements.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardElements.kt @@ -5,8 +5,8 @@ import at.hannibal2.skyhanni.config.features.gui.customscoreboard.ArrowConfig.Ar import at.hannibal2.skyhanni.config.features.gui.customscoreboard.DisplayConfig.PowderDisplay import at.hannibal2.skyhanni.data.BitsAPI import at.hannibal2.skyhanni.data.HypixelData -import at.hannibal2.skyhanni.data.HypixelData.Companion.getMaxPlayersForCurrentServer -import at.hannibal2.skyhanni.data.HypixelData.Companion.getPlayersOnCurrentServer +import at.hannibal2.skyhanni.data.HypixelData.getMaxPlayersForCurrentServer +import at.hannibal2.skyhanni.data.HypixelData.getPlayersOnCurrentServer import at.hannibal2.skyhanni.data.IslandType import at.hannibal2.skyhanni.data.MaxwellAPI import at.hannibal2.skyhanni.data.MayorAPI diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/CollectionTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/CollectionTracker.kt index 2b749c3a6..ffc260723 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/CollectionTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/CollectionTracker.kt @@ -4,6 +4,7 @@ import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.api.CollectionAPI import at.hannibal2.skyhanni.events.GuiRenderEvent import at.hannibal2.skyhanni.events.LorenzTickEvent +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.ChatUtils import at.hannibal2.skyhanni.utils.InventoryUtils import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName @@ -23,165 +24,163 @@ import net.minecraft.client.Minecraft import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import java.util.Collections -class CollectionTracker { +@SkyHanniModule +object CollectionTracker { - private val RECENT_GAIN_TIME = 1_500 + private const val RECENT_GAIN_TIME = 1_500 - companion object { + private var display = emptyList<List<Any>>() - private var display = emptyList<List<Any>>() + private var itemName = "" + private var internalName: NEUInternalName? = null + private var itemAmount = -1L + private var goalAmount = -1L - private var itemName = "" - private var internalName: NEUInternalName? = null - private var itemAmount = -1L - private var goalAmount = -1L + private var lastAmountInInventory = -1 - private var lastAmountInInventory = -1 + private var recentGain = 0 + private var lastGainTime = -1L - private var recentGain = 0 - private var lastGainTime = -1L - - fun command(args: Array<String>) { - if (args.isEmpty()) { - if (internalName == null) { - ChatUtils.userError("/shtrackcollection <item name> [goal amount]") - return - } - ChatUtils.chat("Stopped collection tracker.") - resetData() + fun command(args: Array<String>) { + if (args.isEmpty()) { + if (internalName == null) { + ChatUtils.userError("/shtrackcollection <item name> [goal amount]") return } + ChatUtils.chat("Stopped collection tracker.") + resetData() + return + } - val lastArg = args.last() - - val nameArgs = if (lastArg.isFormatNumber()) { - val goal = lastArg.formatLong() - if (goal <= 0) { - ChatUtils.chat("Invalid Amount for Goal.") - return - } - goalAmount = goal - args.dropLast(1).toTypedArray() - } else { - goalAmount = -1L - args - } + val lastArg = args.last() - val rawName = fixTypo(nameArgs.joinToString(" ").lowercase().replace("_", " ")) - if (rawName == "gemstone") { - ChatUtils.userError("Gemstone collection is not supported!") - return - } else if (rawName == "mushroom") { - ChatUtils.userError("Mushroom collection is not supported!") + val nameArgs = if (lastArg.isFormatNumber()) { + val goal = lastArg.formatLong() + if (goal <= 0) { + ChatUtils.chat("Invalid Amount for Goal.") return } + goalAmount = goal + args.dropLast(1).toTypedArray() + } else { + goalAmount = -1L + args + } - val foundInternalName = NEUInternalName.fromItemNameOrNull(rawName) - if (foundInternalName == null) { - ChatUtils.userError("Item '$rawName' does not exist!") - return - } + val rawName = fixTypo(nameArgs.joinToString(" ").lowercase().replace("_", " ")) + if (rawName == "gemstone") { + ChatUtils.userError("Gemstone collection is not supported!") + return + } else if (rawName == "mushroom") { + ChatUtils.userError("Mushroom collection is not supported!") + return + } - val stack = foundInternalName.getItemStackOrNull() - if (stack == null) { - ChatUtils.userError("Item '$rawName' does not exist!") - return - } - setNewCollection(foundInternalName, stack.name.removeColor()) + val foundInternalName = NEUInternalName.fromItemNameOrNull(rawName) + if (foundInternalName == null) { + ChatUtils.userError("Item '$rawName' does not exist!") + return } - private fun fixTypo(rawName: String) = when (rawName) { - "carrots" -> "carrot" - "melons" -> "melon" - "seed" -> "seeds" - "iron" -> "iron ingot" - "gold" -> "gold ingot" - "sugar" -> "sugar cane" - "cocoa bean", "cocoa" -> "cocoa beans" - "lapis" -> "lapis lazuli" - "cacti" -> "cactus" - "pumpkins" -> "pumpkin" - "potatoes" -> "potato" - "nether warts", "wart", "warts" -> "nether wart" - "stone" -> "cobblestone" - "red mushroom", "brown mushroom", "mushrooms" -> "mushroom" - "gemstones" -> "gemstone" - "caducous" -> "caducous stem" - "agaricus" -> "agaricus cap" - "quartz" -> "nether quartz" - "glowstone" -> "glowstone dust" - - else -> rawName + val stack = foundInternalName.getItemStackOrNull() + if (stack == null) { + ChatUtils.userError("Item '$rawName' does not exist!") + return } + setNewCollection(foundInternalName, stack.name.removeColor()) + } - private fun setNewCollection(internalName: NEUInternalName, name: String) { - val foundAmount = CollectionAPI.getCollectionCounter(internalName) - if (foundAmount == null) { - ChatUtils.userError("$name collection not found. Try to open the collection inventory!") - return - } - this.internalName = internalName - itemName = name - itemAmount = foundAmount + private fun fixTypo(rawName: String) = when (rawName) { + "carrots" -> "carrot" + "melons" -> "melon" + "seed" -> "seeds" + "iron" -> "iron ingot" + "gold" -> "gold ingot" + "sugar" -> "sugar cane" + "cocoa bean", "cocoa" -> "cocoa beans" + "lapis" -> "lapis lazuli" + "cacti" -> "cactus" + "pumpkins" -> "pumpkin" + "potatoes" -> "potato" + "nether warts", "wart", "warts" -> "nether wart" + "stone" -> "cobblestone" + "red mushroom", "brown mushroom", "mushrooms" -> "mushroom" + "gemstones" -> "gemstone" + "caducous" -> "caducous stem" + "agaricus" -> "agaricus cap" + "quartz" -> "nether quartz" + "glowstone" -> "glowstone dust" + + else -> rawName + } - lastAmountInInventory = countCurrentlyInInventory() - updateDisplay() - ChatUtils.chat("Started tracking $itemName §ecollection.") + private fun setNewCollection(internalName: NEUInternalName, name: String) { + val foundAmount = CollectionAPI.getCollectionCounter(internalName) + if (foundAmount == null) { + ChatUtils.userError("$name collection not found. Try to open the collection inventory!") + return } + this.internalName = internalName + itemName = name + itemAmount = foundAmount - private fun resetData() { - itemAmount = -1L - goalAmount = -1L - internalName = null - - lastAmountInInventory = -1 - display = emptyList() + lastAmountInInventory = countCurrentlyInInventory() + updateDisplay() + ChatUtils.chat("Started tracking $itemName §ecollection.") + } - recentGain = 0 - } + private fun resetData() { + itemAmount = -1L + goalAmount = -1L + internalName = null - private fun updateDisplay() { - val format = itemAmount.addSeparators() + lastAmountInInventory = -1 + display = emptyList() - var gainText = "" - if (recentGain != 0) { - gainText = "§a+" + recentGain.addSeparators() - } + recentGain = 0 + } - if (goalAmount != -1L && itemAmount >= goalAmount) { - ChatUtils.chat("Collection goal of §a${goalAmount.addSeparators()} reached!") - goalAmount = -1L - } + private fun updateDisplay() { + val format = itemAmount.addSeparators() - val goal = if (goalAmount == -1L) "" else " §f/ §b${goalAmount.addSeparators()} §f(§a${ - itemAmount.percentWithColorCode(goalAmount, 1) - }§f)" + var gainText = "" + if (recentGain != 0) { + gainText = "§a+" + recentGain.addSeparators() + } - display = Collections.singletonList(buildList { - internalName?.let { - add(it.getItemStack()) - } - add("$itemName collection: §e$format$goal $gainText") - }) + if (goalAmount != -1L && itemAmount >= goalAmount) { + ChatUtils.chat("Collection goal of §a${goalAmount.addSeparators()} reached!") + goalAmount = -1L } - private fun countCurrentlyInInventory(): Int { - val cactus = "CACTUS".asInternalName() - val cactusGreen = "INK_SACK-2".asInternalName() - return InventoryUtils.countItemsInLowerInventory { - if (internalName == cactus && it.getInternalName() == cactusGreen) { - return@countItemsInLowerInventory true - } - it.getInternalName() == internalName + val goal = if (goalAmount == -1L) "" else " §f/ §b${goalAmount.addSeparators()} §f(§a${ + itemAmount.percentWithColorCode(goalAmount, 1) + }§f)" + + display = Collections.singletonList(buildList { + internalName?.let { + add(it.getItemStack()) + } + add("$itemName collection: §e$format$goal $gainText") + }) + } + + private fun countCurrentlyInInventory(): Int { + val cactus = "CACTUS".asInternalName() + val cactusGreen = "INK_SACK-2".asInternalName() + return InventoryUtils.countItemsInLowerInventory { + if (internalName == cactus && it.getInternalName() == cactusGreen) { + return@countItemsInLowerInventory true } + it.getInternalName() == internalName } + } - fun handleTabComplete(command: String): List<String>? { - if (command != "shtrackcollection") return null + fun handleTabComplete(command: String): List<String>? { + if (command != "shtrackcollection") return null - return CollectionAPI.collectionValue.keys.mapNotNull { it.getItemStackOrNull() } - .map { it.displayName.removeColor().replace(" ", "_") } - } + return CollectionAPI.collectionValue.keys.mapNotNull { it.getItemStackOrNull() } + .map { it.displayName.removeColor().replace(" ", "_") } } @SubscribeEvent diff --git a/src/main/java/at/hannibal2/skyhanni/test/SkyHanniDebugsAndTests.kt b/src/main/java/at/hannibal2/skyhanni/test/SkyHanniDebugsAndTests.kt index ec6c10db4..b3dabadd5 100644 --- a/src/main/java/at/hannibal2/skyhanni/test/SkyHanniDebugsAndTests.kt +++ b/src/main/java/at/hannibal2/skyhanni/test/SkyHanniDebugsAndTests.kt @@ -16,6 +16,7 @@ import at.hannibal2.skyhanni.events.ReceiveParticleEvent import at.hannibal2.skyhanni.features.garden.GardenNextJacobContest import at.hannibal2.skyhanni.features.garden.visitor.GardenVisitorColorNames import at.hannibal2.skyhanni.features.inventory.bazaar.BazaarApi.getBazaarData +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.ChatUtils import at.hannibal2.skyhanni.utils.CollectionUtils.editCopy import at.hannibal2.skyhanni.utils.InventoryUtils @@ -62,62 +63,61 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import java.io.File import kotlin.time.Duration.Companion.seconds -class SkyHanniDebugsAndTests { +@SkyHanniModule +object SkyHanniDebugsAndTests { - companion object { + private val config get() = SkyHanniMod.feature.dev + private val debugConfig get() = config.debug + var displayLine = "" + var displayList = emptyList<List<Any>>() - private val config get() = SkyHanniMod.feature.dev - private val debugConfig get() = config.debug - var displayLine = "" - var displayList = emptyList<List<Any>>() + var globalRender = true - var globalRender = true + var a = 1.0 + var b = 60.0 + var c = 0.0 - var a = 1.0 - var b = 60.0 - var c = 0.0 + val debugLogger = LorenzLogger("debug/test") - val debugLogger = LorenzLogger("debug/test") - - private fun run(compound: NBTTagCompound, text: String) { - print("$text'$compound'") - for (s in compound.keySet) { - val element = compound.getCompoundTag(s) - run(element, "$text ") - } + private fun run(compound: NBTTagCompound, text: String) { + print("$text'$compound'") + for (s in compound.keySet) { + val element = compound.getCompoundTag(s) + run(element, "$text ") } + } - private fun print(text: String) { - LorenzDebug.log(text) - } + private fun print(text: String) { + LorenzDebug.log(text) + } - private var testLocation: LorenzVec? = null + private var testLocation: LorenzVec? = null - @SubscribeEvent - fun onRenderWorld(event: LorenzRenderWorldEvent) { - testLocation?.let { - event.drawWaypointFilled(it, LorenzColor.WHITE.toColor()) - event.drawDynamicText(it, "Test", 1.5) - } + @SubscribeEvent + fun onRenderWorld(event: LorenzRenderWorldEvent) { + testLocation?.let { + event.drawWaypointFilled(it, LorenzColor.WHITE.toColor()) + event.drawDynamicText(it, "Test", 1.5) } + } - fun waypoint(args: Array<String>) { - SoundUtils.playBeepSound() - - if (args.isEmpty()) { - testLocation = null - ChatUtils.chat("reset test waypoint") - } + fun waypoint(args: Array<String>) { + SoundUtils.playBeepSound() - val x = args[0].toDouble() - val y = args[1].toDouble() - val z = args[2].toDouble() - testLocation = LorenzVec(x, y, z) - ChatUtils.chat("set test waypoint") + if (args.isEmpty()) { + testLocation = null + ChatUtils.chat("reset test waypoint") } - fun testCommand(args: Array<String>) { - SoundUtils.playBeepSound() + val x = args[0].toDouble() + val y = args[1].toDouble() + val z = args[2].toDouble() + testLocation = LorenzVec(x, y, z) + ChatUtils.chat("set test waypoint") + } + + fun testCommand(args: Array<String>) { + SoundUtils.playBeepSound() // val a = Thread { OSUtils.copyToClipboard("123") } // val b = Thread { OSUtils.copyToClipboard("456") } // a.start() @@ -146,271 +146,270 @@ class SkyHanniDebugsAndTests { // for (line in TabListUtils.getTabList()) { // println("tablist: '$line'") // } - } + } - fun findNullConfig(args: Array<String>) { - println("start null finder") - findNull(SkyHanniMod.feature, "config") - println("stop null finder") - } + fun findNullConfig(args: Array<String>) { + println("start null finder") + findNull(SkyHanniMod.feature, "config") + println("stop null finder") + } - private fun findNull(obj: Any, path: String) { - - val blockedNames = listOf( - "TRUE", - "FALSE", - "SIZE", - "MIN_VALUE", - "MAX_VALUE", - "BYTES", - "POSITIVE_INFINITY", - "NEGATIVE_INFINITY", - "NaN", - "MIN_NORMAL", - ) + private fun findNull(obj: Any, path: String) { + + val blockedNames = listOf( + "TRUE", + "FALSE", + "SIZE", + "MIN_VALUE", + "MAX_VALUE", + "BYTES", + "POSITIVE_INFINITY", + "NEGATIVE_INFINITY", + "NaN", + "MIN_NORMAL", + ) - val javaClass = obj.javaClass - if (javaClass.isEnum) return - for (field in javaClass.fields) { - val name = field.name - if (name in blockedNames) continue + val javaClass = obj.javaClass + if (javaClass.isEnum) return + for (field in javaClass.fields) { + val name = field.name + if (name in blockedNames) continue - // funny thing - if (obj is Position) { - if (name == "internalName") continue - } + // funny thing + if (obj is Position) { + if (name == "internalName") continue + } - val other = field.makeAccessible().get(obj) - val newName = "$path.$name" - if (other == null) { - println("config null at $newName") - } else { - findNull(other, newName) - } + val other = field.makeAccessible().get(obj) + val newName = "$path.$name" + if (other == null) { + println("config null at $newName") + } else { + findNull(other, newName) } } + } - fun resetConfigCommand() { - ChatUtils.clickableChat( - "§cTHIS WILL RESET YOUR SkyHanni CONFIG! Click here to procceed.", - onClick = { - resetConfig() - }, - prefix = false, - oneTimeClick = true - ) - } + fun resetConfigCommand() { + ChatUtils.clickableChat( + "§cTHIS WILL RESET YOUR SkyHanni CONFIG! Click here to procceed.", + onClick = { + resetConfig() + }, + prefix = false, + oneTimeClick = true + ) + } - private fun resetConfig() { - // saving old config state - SkyHanniMod.configManager.saveConfig(ConfigFileType.FEATURES, "reload config manager") - SkyHanniMod.configManager.saveConfig(ConfigFileType.SACKS, "reload config manager") - Thread { - Thread.sleep(500) - SkyHanniMod.configManager.disableSaving() - - // initializing a new config manager, calling firstLoad, and setting it as the config manager in use. - val configManager = ConfigManager() - configManager.firstLoad() - SkyHanniMod.Companion::class.java.enclosingClass.getDeclaredField("configManager").makeAccessible() - .set(SkyHanniMod, configManager) - - // resetting the MoulConfigProcessor in use - ConfigGuiManager.editor = null - ChatUtils.chat("Reset the config manager!") - }.start() + private fun resetConfig() { + // saving old config state + SkyHanniMod.configManager.saveConfig(ConfigFileType.FEATURES, "reload config manager") + SkyHanniMod.configManager.saveConfig(ConfigFileType.SACKS, "reload config manager") + Thread { + Thread.sleep(500) + SkyHanniMod.configManager.disableSaving() + + // initializing a new config manager, calling firstLoad, and setting it as the config manager in use. + val configManager = ConfigManager() + configManager.firstLoad() + SkyHanniMod.Companion::class.java.enclosingClass.getDeclaredField("configManager").makeAccessible() + .set(SkyHanniMod, configManager) + + // resetting the MoulConfigProcessor in use + ConfigGuiManager.editor = null + ChatUtils.chat("Reset the config manager!") + }.start() + } + + fun testGardenVisitors() { + if (displayList.isNotEmpty()) { + displayList = mutableListOf() + return } - fun testGardenVisitors() { - if (displayList.isNotEmpty()) { - displayList = mutableListOf() - return + val bigList = mutableListOf<List<Any>>() + var list = mutableListOf<Any>() + var i = 0 + var errors = 0 + for (item in GardenVisitorColorNames.visitorItems) { + val name = item.key + i++ + if (i == 5) { + i = 0 + bigList.add(list) + list = mutableListOf() } - val bigList = mutableListOf<List<Any>>() - var list = mutableListOf<Any>() - var i = 0 - var errors = 0 - for (item in GardenVisitorColorNames.visitorItems) { - val name = item.key - i++ - if (i == 5) { - i = 0 - bigList.add(list) - list = mutableListOf() + val coloredName = GardenVisitorColorNames.getColoredName(name) + list.add("$coloredName§7 (") + for (itemName in item.value) { + try { + val internalName = NEUInternalName.fromItemName(itemName) + list.add(internalName.getItemStack()) + } catch (e: Error) { + ChatUtils.debug("itemName '$itemName' is invalid for visitor '$name'") + errors++ } - - val coloredName = GardenVisitorColorNames.getColoredName(name) - list.add("$coloredName§7 (") - for (itemName in item.value) { - try { - val internalName = NEUInternalName.fromItemName(itemName) - list.add(internalName.getItemStack()) - } catch (e: Error) { - ChatUtils.debug("itemName '$itemName' is invalid for visitor '$name'") - errors++ - } - } - if (item.value.isEmpty()) { - list.add("Any") - } - list.add("§7) ") } - bigList.add(list) - displayList = bigList - if (errors == 0) { - ChatUtils.debug("Test garden visitor renderer: no errors") - } else { - ChatUtils.debug("Test garden visitor renderer: $errors errors") + if (item.value.isEmpty()) { + list.add("Any") } + list.add("§7) ") } - - fun reloadListeners() { - val blockedFeatures = try { - File("config/skyhanni/blocked-features.txt").readLines().toList() - } catch (e: Exception) { - emptyList() - } - - val modules = SkyHanniMod.modules - for (original in modules.toMutableList()) { - val javaClass = original.javaClass - val simpleName = javaClass.simpleName - MinecraftForge.EVENT_BUS.unregister(original) - println("Unregistered listener $simpleName") - - if (simpleName !in blockedFeatures) { - modules.remove(original) - val module = javaClass.newInstance() - modules.add(module) - - MinecraftForge.EVENT_BUS.register(module) - println("Registered listener $simpleName") - } else { - println("Skipped registering listener $simpleName") - } - } - ChatUtils.chat("reloaded ${modules.size} listener classes.") + bigList.add(list) + displayList = bigList + if (errors == 0) { + ChatUtils.debug("Test garden visitor renderer: no errors") + } else { + ChatUtils.debug("Test garden visitor renderer: $errors errors") } + } - fun stopListeners() { - val modules = SkyHanniMod.modules - for (original in modules.toMutableList()) { - val javaClass = original.javaClass - val simpleName = javaClass.simpleName - MinecraftForge.EVENT_BUS.unregister(original) - println("Unregistered listener $simpleName") - } - ChatUtils.chat("stopped ${modules.size} listener classes.") + fun reloadListeners() { + val blockedFeatures = try { + File("config/skyhanni/blocked-features.txt").readLines().toList() + } catch (e: Exception) { + emptyList() } - fun whereAmI() { - if (LorenzUtils.inSkyBlock) { - ChatUtils.chat("§eYou are currently in ${LorenzUtils.skyBlockIsland}.") - return + val modules = SkyHanniMod.modules + for (original in modules.toMutableList()) { + val javaClass = original.javaClass + val simpleName = javaClass.simpleName + MinecraftForge.EVENT_BUS.unregister(original) + println("Unregistered listener $simpleName") + + if (simpleName !in blockedFeatures) { + modules.remove(original) + val module = javaClass.newInstance() + modules.add(module) + + MinecraftForge.EVENT_BUS.register(module) + println("Registered listener $simpleName") + } else { + println("Skipped registering listener $simpleName") } - ChatUtils.chat("§eYou are not in Skyblock.") } + ChatUtils.chat("reloaded ${modules.size} listener classes.") + } - private var lastManualContestDataUpdate = SimpleTimeMark.farPast() + fun stopListeners() { + val modules = SkyHanniMod.modules + for (original in modules.toMutableList()) { + val javaClass = original.javaClass + val simpleName = javaClass.simpleName + MinecraftForge.EVENT_BUS.unregister(original) + println("Unregistered listener $simpleName") + } + ChatUtils.chat("stopped ${modules.size} listener classes.") + } - fun clearContestData() { - if (lastManualContestDataUpdate.passedSince() < 30.seconds) { - ChatUtils.userError("§cYou already cleared Jacob's Contest data recently!") - return - } - lastManualContestDataUpdate = SimpleTimeMark.now() - - GardenNextJacobContest.contests.clear() - GardenNextJacobContest.fetchedFromElite = false - GardenNextJacobContest.isFetchingContests = true - SkyHanniMod.coroutineScope.launch { - GardenNextJacobContest.fetchUpcomingContests() - GardenNextJacobContest.lastFetchAttempted = System.currentTimeMillis() - GardenNextJacobContest.isFetchingContests = false - } + fun whereAmI() { + if (LorenzUtils.inSkyBlock) { + ChatUtils.chat("§eYou are currently in ${LorenzUtils.skyBlockIsland}.") + return } + ChatUtils.chat("§eYou are not in Skyblock.") + } - fun copyLocation(args: Array<String>) { - val location = LocationUtils.playerLocation() - val x = (location.x + 0.001).round(1) - val y = (location.y + 0.001).round(1) - val z = (location.z + 0.001).round(1) - if (args.size == 1 && args[0].equals("json", false)) { - OSUtils.copyToClipboard("\"$x:$y:$z\"") - return - } + private var lastManualContestDataUpdate = SimpleTimeMark.farPast() - OSUtils.copyToClipboard("LorenzVec($x, $y, $z)") + fun clearContestData() { + if (lastManualContestDataUpdate.passedSince() < 30.seconds) { + ChatUtils.userError("§cYou already cleared Jacob's Contest data recently!") + return + } + lastManualContestDataUpdate = SimpleTimeMark.now() + + GardenNextJacobContest.contests.clear() + GardenNextJacobContest.fetchedFromElite = false + GardenNextJacobContest.isFetchingContests = true + SkyHanniMod.coroutineScope.launch { + GardenNextJacobContest.fetchUpcomingContests() + GardenNextJacobContest.lastFetchAttempted = System.currentTimeMillis() + GardenNextJacobContest.isFetchingContests = false } + } - fun debugVersion() { - val name = "SkyHanni ${SkyHanniMod.version}" - ChatUtils.chat("§eYou are using $name") - OSUtils.copyToClipboard(name) + fun copyLocation(args: Array<String>) { + val location = LocationUtils.playerLocation() + val x = (location.x + 0.001).round(1) + val y = (location.y + 0.001).round(1) + val z = (location.z + 0.001).round(1) + if (args.size == 1 && args[0].equals("json", false)) { + OSUtils.copyToClipboard("\"$x:$y:$z\"") + return } - fun copyItemInternalName() { - val hand = InventoryUtils.getItemInHand() - if (hand == null) { - ChatUtils.userError("No item in hand!") - return - } + OSUtils.copyToClipboard("LorenzVec($x, $y, $z)") + } - val internalName = hand.getInternalNameOrNull() - if (internalName == null) { - ChatUtils.error("§cInternal name is null for item ${hand.name}") - return - } + fun debugVersion() { + val name = "SkyHanni ${SkyHanniMod.version}" + ChatUtils.chat("§eYou are using $name") + OSUtils.copyToClipboard(name) + } - val rawInternalName = internalName.asString() - OSUtils.copyToClipboard(rawInternalName) - ChatUtils.chat("§eCopied internal name §7$rawInternalName §eto the clipboard!") + fun copyItemInternalName() { + val hand = InventoryUtils.getItemInHand() + if (hand == null) { + ChatUtils.userError("No item in hand!") + return } - fun toggleRender() { - globalRender = !globalRender - if (globalRender) { - ChatUtils.chat("§aEnabled global renderer!") - } else { - ChatUtils.chat("§cDisabled global renderer! Run this command again to show SkyHanni rendering again.") - } + val internalName = hand.getInternalNameOrNull() + if (internalName == null) { + ChatUtils.error("§cInternal name is null for item ${hand.name}") + return } - fun testItemCommand(args: Array<String>) { - if (args.isEmpty()) { - ChatUtils.userError("Usage: /shtestitem <item name or internal name>") - return - } + val rawInternalName = internalName.asString() + OSUtils.copyToClipboard(rawInternalName) + ChatUtils.chat("§eCopied internal name §7$rawInternalName §eto the clipboard!") + } - val input = args.joinToString(" ") - val result = buildList { - add("") - add("§bSkyHanni Test Item") - add("§einput: '§f$input§e'") - - NEUInternalName.fromItemNameOrNull(input)?.let { internalName -> - add("§eitem name -> internalName: '§7${internalName.asString()}§e'") - add(" §eitemName: '${internalName.itemName}§e'") - val price = internalName.getPriceOrNull()?.let { "§6" + it.addSeparators() } ?: "§7null" - add(" §eprice: '§6${price}§e'") - return@buildList - } + fun toggleRender() { + globalRender = !globalRender + if (globalRender) { + ChatUtils.chat("§aEnabled global renderer!") + } else { + ChatUtils.chat("§cDisabled global renderer! Run this command again to show SkyHanni rendering again.") + } + } - input.asInternalName().getItemStackOrNull()?.let { item -> - val itemName = item.itemName - val internalName = item.getInternalName() - add("§einternal name: §7${internalName.asString()}") - add("§einternal name -> item name: '$itemName§e'") - val price = internalName.getPriceOrNull()?.let { "§6" + it.addSeparators() } ?: "§7null" - add(" §eprice: '§6${price}§e'") - return@buildList - } + fun testItemCommand(args: Array<String>) { + if (args.isEmpty()) { + ChatUtils.userError("Usage: /shtestitem <item name or internal name>") + return + } + + val input = args.joinToString(" ") + val result = buildList { + add("") + add("§bSkyHanni Test Item") + add("§einput: '§f$input§e'") + + NEUInternalName.fromItemNameOrNull(input)?.let { internalName -> + add("§eitem name -> internalName: '§7${internalName.asString()}§e'") + add(" §eitemName: '${internalName.itemName}§e'") + val price = internalName.getPriceOrNull()?.let { "§6" + it.addSeparators() } ?: "§7null" + add(" §eprice: '§6${price}§e'") + return@buildList + } - add("§cNothing found!") + input.asInternalName().getItemStackOrNull()?.let { item -> + val itemName = item.itemName + val internalName = item.getInternalName() + add("§einternal name: §7${internalName.asString()}") + add("§einternal name -> item name: '$itemName§e'") + val price = internalName.getPriceOrNull()?.let { "§6" + it.addSeparators() } ?: "§7null" + add(" §eprice: '§6${price}§e'") + return@buildList } - ChatUtils.chat(result.joinToString("\n"), prefix = false) + + add("§cNothing found!") } + ChatUtils.chat(result.joinToString("\n"), prefix = false) } @SubscribeEvent |