diff options
author | ILike2WatchMemes <ilike2watchmemes@gmail.com> | 2024-10-02 09:56:10 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-10-02 09:56:10 +0200 |
commit | 1bf9db2453b5af2781b6de22afca6296ef395c57 (patch) | |
tree | 1b05b72d709f312b1c7cc0a646cd772b643a9641 | |
parent | f7a51f5ec5e992c53cd6ef7bc2ece482ead848f0 (diff) | |
download | skyhanni-1bf9db2453b5af2781b6de22afca6296ef395c57.tar.gz skyhanni-1bf9db2453b5af2781b6de22afca6296ef395c57.tar.bz2 skyhanni-1bf9db2453b5af2781b6de22afca6296ef395c57.zip |
Fix: Superpair Data (#2566)
Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com>
Co-authored-by: CalMWolfs <94038482+CalMWolfs@users.noreply.github.com>
3 files changed, 300 insertions, 278 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/ExperimentationTableAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/ExperimentationTableAPI.kt index 25abb16ed..9fcbbad0b 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/ExperimentationTableAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/ExperimentationTableAPI.kt @@ -69,7 +69,7 @@ object ExperimentationTableAPI { */ val rewardPattern by patternGroup.pattern( "rewards", - "\\d{1,3}k Enchanting Exp|Enchanted Book|(?:Titanic |Grand |\\b)Experience Bottle|Metaphysical Serum|Experiment The Fish", + "\\d{1,3}k Enchanting Exp|Enchanted Book|(?:Titanic |Grand |\\b)Experience Bottle|Metaphysical Serum|Experiment the Fish", ) /** @@ -132,6 +132,14 @@ object ExperimentationTableAPI { ) /** + * REGEX-TEST: Remaining Clicks: 22 + */ + val remainingClicksPattern by patternGroup.pattern( + "clicks", + "Remaining Clicks: (?<clicks>\\d+)" + ) + + /** * REGEX-TEST: ☕ You renewed the experiment table! (1/3) */ val experimentRenewPattern by patternGroup.pattern( diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/SuperpairDataDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/SuperpairDataDisplay.kt new file mode 100644 index 000000000..627974e6b --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/SuperpairDataDisplay.kt @@ -0,0 +1,291 @@ +package at.hannibal2.skyhanni.features.inventory.experimentationtable + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.data.IslandType +import at.hannibal2.skyhanni.events.GuiContainerEvent.SlotClickEvent +import at.hannibal2.skyhanni.events.GuiRenderEvent +import at.hannibal2.skyhanni.events.InventoryCloseEvent +import at.hannibal2.skyhanni.features.inventory.experimentationtable.ExperimentationTableAPI.remainingClicksPattern +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.utils.CollectionUtils.equalsOneOf +import at.hannibal2.skyhanni.utils.DelayedRun +import at.hannibal2.skyhanni.utils.InventoryUtils +import at.hannibal2.skyhanni.utils.ItemUtils.getLore +import at.hannibal2.skyhanni.utils.LorenzUtils.isAnyOf +import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland +import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher +import at.hannibal2.skyhanni.utils.RegexUtils.matches +import at.hannibal2.skyhanni.utils.RenderUtils.renderStrings +import at.hannibal2.skyhanni.utils.StringUtils.removeColor +import net.minecraft.item.ItemStack +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import kotlin.time.Duration.Companion.milliseconds + +// TODO important: all use cases of listOf in combination with string needs to be gone. no caching, constant new list creation, and bad design. +@SkyHanniModule +object SuperpairDataDisplay { + + private val config get() = SkyHanniMod.feature.inventory.experimentationTable + + private data class SuperpairItem(val index: Int, val reward: String, val damage: Int) + private data class FoundData(val item: SuperpairItem? = null, val first: SuperpairItem? = null, val second: SuperpairItem? = null) + + private enum class FoundType { + NORMAL, + POWERUP, + MATCH, + PAIR + } + + private val sideSpaces1 = listOf(17, 18, 26, 27, 35, 36) + private val sideSpaces2 = listOf(16, 17, 18, 19, 25, 26, 27, 28, 34, 35, 36, 37) + private val emptySuperpairItem = SuperpairItem(-1, "", -1) + + private var display = emptyList<String>() + private var uncoveredItems = mutableMapOf<Int, SuperpairItem>() + private var found = mutableMapOf<FoundType, MutableList<FoundData>>() + + @SubscribeEvent + fun onInventoryClose(event: InventoryCloseEvent) { + display = emptyList() + + uncoveredItems = mutableMapOf() + found.clear() + } + + @SubscribeEvent + fun onChestGuiOverlayRendered(event: GuiRenderEvent.ChestGuiOverlayRenderEvent) { + if (!isEnabled()) return + if (display.isEmpty()) display = drawDisplay() + + config.superpairDisplayPosition.renderStrings(display, posLabel = "Superpair Experiment Information") + } + + @SubscribeEvent + fun onSlotClick(event: SlotClickEvent) { + if (!isEnabled()) return + val currentExperiment = ExperimentationTableAPI.getCurrentExperiment() ?: return + + val item = event.item ?: return + if (isOutOfBounds(event.slotId, currentExperiment) || item.displayName.removeColor() == "?") return + + val clicksItem = InventoryUtils.getItemAtSlotIndex(4) + + // TODO add variable name to indicate what is going on here + if (uncoveredItems.none { it.value.index == event.slotId && it.key == uncoveredItems.keys.max() }) { + if (clicksItem != null) { + remainingClicksPattern.matchMatcher(clicksItem.displayName.removeColor()) { if (group("clicks").toInt() == 0) return } + } + + handleItem(event.slotId) + } + } + + private fun handleItem(slot: Int) = DelayedRun.runDelayed(200.milliseconds) { + val itemNow = InventoryUtils.getItemAtSlotIndex(slot) ?: return@runDelayed + val itemName = itemNow.displayName.removeColor() + val reward = convertToReward(itemNow) + val itemData = SuperpairItem(slot, reward, itemNow.itemDamage) + val uncovered = uncoveredItems.keys.maxOrNull() ?: -1 + + if (isWaiting(itemName)) return@runDelayed + + if (uncoveredItems.none { it.key == uncovered && it.value.index == slot }) uncoveredItems[uncovered + 1] = itemData + + when { + isPowerUp(reward) -> handlePowerUp(itemData, uncovered + 1) + isReward(itemName) -> handleReward(itemData, uncovered + 1) + } + + val since = clicksSinceSeparator(uncoveredItems) + + val lastReward = uncoveredItems.entries.last().value.reward + // TODO use repo patterns for "Instant Find" + if ((since >= 2 || (since == -1 && uncoveredItems.size >= 2)) && lastReward != "Instant Find") uncoveredItems[uncovered + 2] = + emptySuperpairItem + + display = drawDisplay() + } + + private fun handlePowerUp(item: SuperpairItem, uncovered: Int) { + // TODO use repo patterns for "Instant Find" + if (item.reward != "Instant Find") uncoveredItems.remove(uncovered) + + val itemData = FoundData(item = item) + found.getOrPut(FoundType.POWERUP) { mutableListOf(itemData) }.apply { if (!contains(itemData)) add(itemData) } + } + + private fun handleReward(item: SuperpairItem, uncovered: Int) { + val last = uncoveredItems.getOrDefault(uncovered - 1, item) + + if (isWaiting(last.reward)) return + + when { + // TODO use repo patterns for "Instant Find" + last.reward == "Instant Find" -> handleInstantFind(item, uncovered) + hasFoundPair(item, last) -> handleFoundPair(item, last) + hasFoundMatch(item) -> handleFoundMatch(item) + else -> handleNormalReward(item) + } + + println(found) + } + + private fun handleInstantFind(item: SuperpairItem, uncovered: Int) { + uncoveredItems[uncovered - 1] = item + uncoveredItems[uncovered] = emptySuperpairItem + + handleFoundPair(item, emptySuperpairItem) + } + + private fun handleFoundPair( + first: SuperpairItem, + second: SuperpairItem, + ) { + found.entries.forEach { + when (it.key) { + FoundType.MATCH -> it.value.removeIf { data -> data.first?.sameAs(first) ?: false || data.second?.sameAs(first) ?: false } + FoundType.NORMAL -> it.value.removeIf { data -> data.item?.sameAs(first) ?: false || data.item?.sameAs(second) ?: false } + else -> {} + } + } + + val pairData = FoundData(first = first, second = second) + + found.getOrPut(FoundType.PAIR) { mutableListOf(pairData) }.apply { if (!contains(pairData)) add(pairData) } + } + + private fun handleFoundMatch(item: SuperpairItem) { + // TODO better name + val match = uncoveredItems.values.find { it.index != item.index && it.sameAs(item) } ?: return + + found.entries.forEach { + when { + it.key.isAnyOf(FoundType.MATCH, FoundType.PAIR) -> { + // TODO extract logic in some way + if (it.value.any { data -> + (data.first?.index ?: -1).equalsOneOf(item.index, match.index) || + (data.second?.index + ?: -1).equalsOneOf(item.index, match.index) + }) { + return + } + } + + it.key == FoundType.NORMAL -> it.value.removeIf { data -> + (data.item?.index ?: -1).equalsOneOf(item.index, match.index) + } + + else -> {} + } + } + + val pairData = FoundData(first = item, second = match) + found.getOrPut(FoundType.MATCH) { mutableListOf(pairData) }.apply { if (!contains(pairData)) add(pairData) } + } + + private fun handleNormalReward(item: SuperpairItem) { + for ((key, value) in found.entries) { + when { + key.isAnyOf(FoundType.MATCH, FoundType.PAIR) -> { + if (value.any { data -> + item.index.equalsOneOf(data.first?.index ?: -1, data.second?.index ?: -1) + }) return + } + + else -> if (value.any { data -> + (data.item?.index ?: -1) == item.index && data.item?.sameAs(item) == true + }) return + } + } + + val itemData = FoundData(item = item) + found.getOrPut(FoundType.NORMAL) { mutableListOf(itemData) }.apply { if (!contains(itemData)) add(itemData) } + } + + private fun drawDisplay() = buildList { + val currentExperiment = ExperimentationTableAPI.getCurrentExperiment() ?: return emptyList<String>() + + add("§6Superpair Experimentation Data") + add("") + + val normals = found.entries.firstOrNull { it.key == FoundType.NORMAL }?.value ?: mutableListOf() + val powerups = found.entries.firstOrNull { it.key == FoundType.POWERUP }?.value ?: mutableListOf() + val matches = found.entries.firstOrNull { it.key == FoundType.MATCH }?.value ?: mutableListOf() + val pairs = found.entries.firstOrNull { it.key == FoundType.PAIR }?.value ?: mutableListOf() + val possiblePairs = calculatePossiblePairs(currentExperiment) + + if (pairs.isNotEmpty()) add("§2Found") + for (pair in pairs) { + val prefix = determinePrefix(pairs.indexOf(pair), pairs.lastIndex) + add(" $prefix §a${pair.first?.reward ?: ""}") + } + if (matches.isNotEmpty()) add("§eMatched") + for (match in matches) { + val prefix = determinePrefix(matches.indexOf(match), matches.lastIndex) + add(" $prefix §e${match.first?.reward ?: ""}") + } + if (powerups.isNotEmpty()) add("§bPowerUp") + for (powerup in powerups) { + val prefix = determinePrefix(powerups.indexOf(powerup), powerups.size - 1) + add(" $prefix §b${powerup.item?.reward ?: ""}") + } + val toAdd = mutableListOf<String>() + if (possiblePairs >= 1) toAdd.add("§ePairs - $possiblePairs") + if (2 - powerups.size >= 1) toAdd.add("§bPowerUps - ${2 - powerups.size}") + if (normals.isNotEmpty()) toAdd.add("§7Normals - ${normals.size}") + + if (toAdd.isNotEmpty()) { + add("") + add("§4Not found") + } + for (string in toAdd) if (string != toAdd.last()) add(" ├ $string") else add(" └ $string") + } + + private fun calculatePossiblePairs(currentExperiment: Experiment) = + ((currentExperiment.gridSize - 2) / 2) - found.filter { it.key != FoundType.POWERUP }.values.sumOf { it.size } + + private fun convertToReward(item: ItemStack) = if (item.displayName.removeColor() == "Enchanted Book") item.getLore()[2].removeColor() + else item.displayName.removeColor() + + private fun determinePrefix(index: Int, lastIndex: Int) = if (index == lastIndex) "└" else "├" + + private fun hasFoundPair( + first: SuperpairItem, + second: SuperpairItem, + ) = first.index != second.index && first.sameAs(second) + + // TODO extract logic greatly + private fun hasFoundMatch(firstItem: SuperpairItem) = + uncoveredItems.any { it.value.index != firstItem.index && it.value.sameAs(firstItem) } && + found.entries.none { + it.key.isAnyOf(FoundType.PAIR, FoundType.MATCH) && + it.value.any { data -> + firstItem.index.equalsOneOf(data.first?.index ?: -1, data.second?.index ?: -1) + } + } + + private fun isPowerUp(reward: String) = ExperimentationTableAPI.powerUpPattern.matches(reward) + + private fun isReward(reward: String) = + ExperimentationTableAPI.rewardPattern.matches(reward) || ExperimentationTableAPI.powerUpPattern.matches(reward) + + // TODO use repo patterns instead + private fun isWaiting(itemName: String) = + listOf("Click any button!", "Click a second button!", "Next button is instantly rewarded!").contains(itemName) + + private fun clicksSinceSeparator(list: MutableMap<Int, SuperpairItem>): Int { + val lastIndex = list.entries.indexOfLast { it.value == emptySuperpairItem } + return if (lastIndex != -1) list.size - 1 - lastIndex else -1 + } + + private fun isOutOfBounds(slot: Int, experiment: Experiment): Boolean = + slot <= experiment.startSlot || + slot >= experiment.endSlot || + (if (experiment.sideSpace == 1) slot in sideSpaces1 else slot in sideSpaces2) + + private fun SuperpairItem?.sameAs(other: SuperpairItem) = this?.reward == other.reward && this?.damage == other.damage + + private fun isEnabled() = + IslandType.PRIVATE_ISLAND.isInIsland() && config.superpairDisplay && ExperimentationTableAPI.getCurrentExperiment() != null +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/SuperpairExperimentInformationDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/SuperpairExperimentInformationDisplay.kt deleted file mode 100644 index cb3102ca8..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/SuperpairExperimentInformationDisplay.kt +++ /dev/null @@ -1,277 +0,0 @@ -package at.hannibal2.skyhanni.features.inventory.experimentationtable - -import at.hannibal2.skyhanni.SkyHanniMod -import at.hannibal2.skyhanni.events.GuiContainerEvent.SlotClickEvent -import at.hannibal2.skyhanni.events.GuiRenderEvent -import at.hannibal2.skyhanni.events.InventoryCloseEvent -import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule -import at.hannibal2.skyhanni.utils.InventoryUtils -import at.hannibal2.skyhanni.utils.ItemUtils.getLore -import at.hannibal2.skyhanni.utils.LorenzUtils -import at.hannibal2.skyhanni.utils.RegexUtils.matches -import at.hannibal2.skyhanni.utils.RenderUtils.renderStrings -import at.hannibal2.skyhanni.utils.SimpleTimeMark -import at.hannibal2.skyhanni.utils.StringUtils.removeColor -import net.minecraft.item.ItemStack -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent -import kotlin.time.Duration.Companion.milliseconds - -// TODO important: all use cases of listOf in combination with string needs to be gone. no caching, constant new list creation, and bad design. -@SkyHanniModule -object SuperpairExperimentInformationDisplay { - - private val config get() = SkyHanniMod.feature.inventory.experimentationTable - - private var display = emptyList<String>() - - private var uncoveredAt = 0 - private var uncoveredItems = mutableListOf<Pair<Int, String>>() - private var possiblePairs = 0 - - data class Item(val index: Int, val name: String) - data class ItemPair(val first: Item, val second: Item) - - // TODO remove string. use enum instead! maybe even create new data type instead of map of pairs - private var found = mutableMapOf<Pair<Item?, ItemPair?>, String>() - - private var toCheck = mutableListOf<Pair<Int, Int>>() - private var lastClicked = mutableListOf<Pair<Int, Int>>() - private var lastClick = SimpleTimeMark.farPast() - private var currentExperiment = Experiment.NONE - private var instantFind = 0 - - private val sideSpaces1 = listOf(17, 18, 26, 27, 35, 36) - private val sideSpaces2 = listOf(16, 17, 18, 19, 25, 26, 27, 28, 34, 35, 36, 37) - - @SubscribeEvent - fun onInventoryClose(event: InventoryCloseEvent) { - display = emptyList() - - uncoveredAt = 0 - uncoveredItems.clear() - possiblePairs = 0 - - found.clear() - toCheck.clear() - lastClicked.clear() - lastClick = SimpleTimeMark.farPast() - currentExperiment = Experiment.NONE - instantFind = 0 - } - - @SubscribeEvent - fun onChestGuiOverlayRendered(event: GuiRenderEvent.ChestGuiOverlayRenderEvent) { - if (!isEnabled()) return - config.superpairDisplayPosition.renderStrings(display, posLabel = "Superpair Experiment Information") - display = checkItems(toCheck) - } - - @SubscribeEvent - fun onSlotClick(event: SlotClickEvent) { - if (!isEnabled()) return - currentExperiment = ExperimentationTableAPI.getCurrentExperiment() ?: return - - if (isOutOfBounds(event.slotId, currentExperiment)) return - val item = event.item ?: return - if (item.displayName.removeColor() == "?") return - val clicksItem = InventoryUtils.getItemAtSlotIndex(4) - - if (lastClicked.none { it.first == event.slotId && it.second == uncoveredAt } && lastClick.passedSince() > 100.milliseconds) { - if (clicksItem != null && clicksItem.displayName.removeColor().split(" ")[1] == "0") return - lastClicked.add(Pair(event.slotId, uncoveredAt)) - lastClick = SimpleTimeMark.now() - toCheck.add(event.slotId to uncoveredAt) - uncoveredAt += 1 - } - } - - private fun checkItems(check: MutableList<Pair<Int, Int>>): List<String> { - currentExperiment = ExperimentationTableAPI.getCurrentExperiment() ?: return listOf() - if (check.isEmpty()) return drawDisplay() - - for ((slot, uncovered) in check) { - val itemNow = InventoryUtils.getItemAtSlotIndex(slot) ?: return drawDisplay() - val itemName = itemNow.displayName.removeColor() - - if (isWaiting(itemName) || isOutOfBounds(slot, currentExperiment)) return drawDisplay() - - val reward = convertToReward(itemNow) - if (uncoveredItems.none { it.first == slot }) uncoveredItems.add(Pair(slot, reward)) - - when { - isPowerUp(reward) -> handlePowerUp(slot, reward) - isReward(itemName) -> handleReward(slot, uncovered, reward) - } - - possiblePairs = calculatePossiblePairs() - - val since = clicksSinceSeparator(lastClicked) - - if ((since >= 2 || (since == -1 && lastClicked.size >= 2)) && instantFind == 0) { - lastClicked.add(-1 to uncoveredAt) - uncoveredAt += 1 - } - toCheck.removeIf { it.first == slot } - - return drawDisplay() - } - possiblePairs = calculatePossiblePairs() - return drawDisplay() - } - - private fun handlePowerUp(slot: Int, reward: String) { - val item = toEither(Item(slot, reward)) - - found[item] = "Powerup" - possiblePairs-- - lastClicked.removeIf { it.first == slot } - uncoveredAt -= 1 - if (reward == "Instant Find") instantFind += 1 - } - - private fun handleReward(slot: Int, uncovered: Int, reward: String) { - val lastSlotClicked = - if (instantFind == 0 && lastClicked.none { it.first == -1 && it.second == uncovered - 1 } && lastClicked.size != 1) lastClicked.find { it.second == uncovered - 1 } - ?: return else lastClicked.find { it.second == uncovered } ?: return - - val lastItem = InventoryUtils.getItemAtSlotIndex(lastSlotClicked.first) ?: return - val itemClicked = InventoryUtils.getItemAtSlotIndex(slot) ?: return - - val lastItemName = convertToReward(lastItem) - - if (isWaiting(lastItemName)) return - - when { - instantFind >= 1 -> { - handleFoundPair(slot, reward, lastSlotClicked.first) - instantFind -= 1 - lastClicked.add(-1 to uncoveredAt) - uncoveredAt += 1 - } - - hasFoundPair(slot, lastSlotClicked.first, reward, lastItemName) && lastItem.itemDamage == itemClicked.itemDamage -> handleFoundPair( - slot, - reward, - lastSlotClicked.first, - ) - - hasFoundMatch(slot, reward) -> handleFoundMatch(slot, reward) - else -> handleNormalReward(slot, reward) - } - - } - - private fun handleFoundPair( - slot: Int, - reward: String, - lastSlotClicked: Int, - ) { - val pair = toEither(ItemPair(Item(slot, reward), Item(lastSlotClicked, reward))) - - found[pair] = "Pair" - found.entries.removeIf { - it.value == "Match" && right(it.key).first.index == slot - } - found.entries.removeIf { - it.value == "Normal" && (left(it.key).index == slot || left(it.key).index == lastSlotClicked) - } - } - - private fun handleFoundMatch(slot: Int, reward: String) { - val match = uncoveredItems.find { it.second == reward }?.first ?: return - val pair = toEither(ItemPair(Item(slot, reward), Item(match, reward))) - - if (found.none { - listOf("Pair", "Match").contains(it.value) && (right(it.key).first.index == slot) - }) found[pair] = "Match" - found.entries.removeIf { it.value == "Normal" && (left(it.key).index == slot || left(it.key).index == match) } - } - - private fun handleNormalReward(slot: Int, reward: String) { - val item = toEither(Item(slot, reward)) - - if (found.none { - listOf("Match", "Pair").contains(it.value) && (right(it.key).first.index == slot || right(it.key).second.index == slot) - } && found.none { it.value == "Normal" && left(it.key).index == slot }) found[item] = "Normal" - } - - private fun calculatePossiblePairs() = - ((currentExperiment.gridSize - 2) / 2) - found.filter { listOf("Pair", "Match", "Normal").contains(it.value) }.size - - private fun drawDisplay() = buildList { - add("§6Superpair Experimentation Data") - add("") - - val pairs = found.entries.filter { it.value == "Pair" } - val matches = found.entries.filter { it.value == "Match" } - val powerups = found.entries.filter { it.value == "Powerup" } - val normals = found.entries.filter { it.value == "Normal" } - - if (pairs.isNotEmpty()) add("§2Found") - for (pair in pairs) { - val prefix = determinePrefix(pairs.indexOf(pair), pairs.lastIndex) - add(" $prefix §a${right(pair.key).first.name}") - } - if (matches.isNotEmpty()) add("§eMatched") - for (match in matches) { - val prefix = determinePrefix(matches.indexOf(match), matches.lastIndex) - add(" $prefix §e${right(match.key).first.name}") - } - if (powerups.isNotEmpty()) add("§bPowerUp") - for (powerup in powerups) { - val prefix = determinePrefix(powerups.indexOf(powerup), powerups.size - 1) - add(" $prefix §b${left(powerup.key).name}") - } - val toAdd = mutableListOf<String>() - if (possiblePairs >= 1) toAdd.add("§ePairs - $possiblePairs") - if (2 - powerups.size >= 1) toAdd.add("§bPowerUps - ${2 - powerups.size}") - if (normals.isNotEmpty()) toAdd.add("§7Normals - ${normals.size}") - - if (toAdd.isNotEmpty()) { - add("") - add("§4Not found") - } - for (string in toAdd) if (string != toAdd.last()) add(" ├ $string") else add(" └ $string") - } - - private fun convertToReward(item: ItemStack) = if (item.displayName.removeColor() == "Enchanted Book") item.getLore()[2].removeColor() - else item.displayName.removeColor() - - private fun determinePrefix(index: Int, lastIndex: Int) = if (index == lastIndex) "└" else "├" - - private fun hasFoundPair( - firstSlot: Int, - secondSlot: Int, - firstName: String, - secondName: String, - ) = firstSlot != secondSlot && firstName == secondName - - private fun hasFoundMatch(itemSlot: Int, reward: String) = - uncoveredItems.any { (slot, name) -> slot != itemSlot && name == reward } && found.none { - listOf("Pair", "Match").contains(it.value) && (right(it.key).first.index == itemSlot || right(it.key).second.index == itemSlot) - } - - private fun isPowerUp(reward: String) = ExperimentationTableAPI.powerUpPattern.matches(reward) - - private fun isReward(reward: String) = ExperimentationTableAPI.rewardPattern.matches(reward) - - private fun isWaiting(itemName: String) = - listOf("Click any button!", "Click a second button!", "Next button is instantly rewarded!").contains(itemName) - - private fun clicksSinceSeparator(list: MutableList<Pair<Int, Int>>): Int { - val lastIndex = list.indexOfLast { it.first == -1 } - return if (lastIndex != -1) list.size - 1 - lastIndex else -1 - } - - private fun isOutOfBounds(slot: Int, experiment: Experiment): Boolean = - slot <= experiment.startSlot || slot >= experiment.endSlot || (if (experiment.sideSpace == 1) slot in sideSpaces1 else slot in sideSpaces2) - - // TODO remove left and right, use custom data type instead - private fun left(it: Pair<Item?, ItemPair?>): Item = it.first ?: Item(-1, "") - - private fun right(it: Pair<Item?, ItemPair?>): ItemPair = it.second ?: ItemPair(Item(-1, ""), Item(-1, "")) - - private fun toEither(it: Any): Pair<Item?, ItemPair?> = if (it is Item) it to null else null to it as ItemPair - - private fun isEnabled() = LorenzUtils.inSkyBlock && config.superpairDisplay && ExperimentationTableAPI.getCurrentExperiment() != null -} |