Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Profit per corpse loot #1734

Merged
merged 6 commits into from
May 8, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,8 @@ import at.hannibal2.skyhanni.features.mining.fossilexcavator.FossilExcavatorAPI
import at.hannibal2.skyhanni.features.mining.fossilexcavator.GlacitePowderFeatures
import at.hannibal2.skyhanni.features.mining.fossilexcavator.ProfitPerExcavation
import at.hannibal2.skyhanni.features.mining.fossilexcavator.solver.FossilSolverDisplay
import at.hannibal2.skyhanni.features.mining.mineshaft.CorpseAPI
import at.hannibal2.skyhanni.features.mining.mineshaft.MineshaftCorpseProfitPer
import at.hannibal2.skyhanni.features.mining.powdertracker.PowderTracker
import at.hannibal2.skyhanni.features.minion.InfernoMinionFeatures
import at.hannibal2.skyhanni.features.minion.MinionCollectLogic
Expand Down Expand Up @@ -742,6 +744,8 @@ class SkyHanniMod {
loadModule(ExcavatorProfitTracker())
loadModule(ProfitPerExcavation())
loadModule(GlacitePowderFeatures())
loadModule(MineshaftCorpseProfitPer())
loadModule(CorpseAPI())
loadModule(GardenOptimalSpeed())
loadModule(GardenLevelDisplay())
loadModule(FarmingWeightDisplay())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ public class FossilExcavatorConfig {

@Expose
@ConfigOption(
name = "Profit Per",
desc = "Show profit/loss in chat after each excavation. Also include breakdown information on hover."
name = "Profit Per Excavation",
desc = "Show profit/loss in chat after each excavation. Also includes breakdown information on hover."
)
@ConfigEditorBoolean
@FeatureToggle
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package at.hannibal2.skyhanni.config.features.mining;

import at.hannibal2.skyhanni.config.FeatureToggle;
import com.google.gson.annotations.Expose;
import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean;
import io.github.notenoughupdates.moulconfig.annotations.ConfigOption;

public class MineshaftConfig {

@Expose
@ConfigOption(
name = "Profit Per Corpse",
desc = "Show profit/loss in chat after each looted corpse in the Mineshaft. Also includes breakdown information on hover."
)
@ConfigEditorBoolean
@FeatureToggle
public boolean profitPerCorpseLoot = true;
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ public class MiningConfig {
@Accordion
public CommissionsBlocksColorConfig commissionsBlocksColor = new CommissionsBlocksColorConfig();

@Expose
@ConfigOption(name = "Mineshaft", desc = "")
@Accordion
public MineshaftConfig mineshaft = new MineshaftConfig();

@Expose
@ConfigOption(name = "Highlight Commission Mobs", desc = "Highlight Mobs that are part of active commissions.")
@ConfigEditorBoolean
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package at.hannibal2.skyhanni.events.mining

import at.hannibal2.skyhanni.events.LorenzEvent
import at.hannibal2.skyhanni.features.mining.mineshaft.CorpeType

class CorpseLootedEvent(val corpseType: CorpeType, val loot: List<Pair<String, Int>>) : LorenzEvent()
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ object FossilExcavatorAPI {
} ?: return
// Workaround: If it is a enchanted book, we assume it is a paleontologist I book
if (pair.first.let { it == "§fEnchanted" || it == "§fEnchanted Book" }) {
pair = "Paleontologist I" to pair.second
pair = "§9Paleontologist I" to pair.second
}
loot.add(pair)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class ProfitPerExcavation {
val pricePer = it.getPrice()
if (pricePer == -1.0) continue
val profit = amount * pricePer
val text = "Found $name §8${amount.addSeparators()}x §7(§6${NumberUtil.format(profit)}§7)"
val text = "§eFound $name §8${amount.addSeparators()}x §7(§6${NumberUtil.format(profit)}§7)"
map[text] = profit
totalProfit += profit
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package at.hannibal2.skyhanni.features.mining.mineshaft

import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName

enum class CorpeType(val displayName: String, private val keyName: String? = null) {
LAPIS("§9Lapis"),
TUNGSTEN("§7Tungsten", "TUNGSTEN_KEY"),
UMBER("§6Umber", "UMBER_KEY"),
VANGUARD("§fVanguard", "SKELETON_KEY"),
;

val key by lazy { keyName?.asInternalName() }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package at.hannibal2.skyhanni.features.mining.mineshaft

import at.hannibal2.skyhanni.data.IslandType
import at.hannibal2.skyhanni.events.LorenzChatEvent
import at.hannibal2.skyhanni.events.mining.CorpseLootedEvent
import at.hannibal2.skyhanni.utils.ItemUtils
import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland
import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher
import at.hannibal2.skyhanni.utils.StringUtils.matches
import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent

class CorpseAPI {

private val patternGroup = RepoPattern.group("mining.mineshaft")
private val chatPatternGroup = patternGroup.group("chat")

/**
* REGEX-TEST: §r§b§l§r§9§lLAPIS §r§b§lCORPSE LOOT!
* REGEX-TEST: §r§b§l§r§7§lTUNGSTEN §r§b§lCORPSE LOOT!
* REGEX-TEST: §r§b§l§r§6§lUMBER §r§b§lCORPSE LOOT!
* REGEX-TEST: §r§b§l§r§f§lVANGUARD §r§b§lCORPSE LOOT!
*/
private val startPattern by chatPatternGroup.pattern(
"start",
" {2}§r§b§l§r§(?<color>.)§l(?<name>.*) §r§b§lCORPSE LOOT! ?"
)

/**
* REGEX-TEST: §a§l▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
*/
private val endPattern by chatPatternGroup.pattern("end", "§a§l▬{64}")

/**
* REGEX-TEST: §r§9☠ Fine Onyx Gemstone §r§8x2
*/
private val itemPattern by chatPatternGroup.pattern("item", " {4}§r(?<item>.+)")

private var inLoot = false
private val loot = mutableListOf<Pair<String, Int>>()

private var corpeType: CorpeType? = null

@SubscribeEvent
fun onChat(event: LorenzChatEvent) {
if (!IslandType.MINESHAFT.isInIsland()) return

val message = event.message

startPattern.matchMatcher(message) {
inLoot = true
val name = group("name")
corpeType = CorpeType.valueOf(name)
return
}

if (!inLoot) return

if (endPattern.matches(message)) {
corpeType?.let {
CorpseLootedEvent(it, loot.toList()).postAndCatch()
}
corpeType = null
loot.clear()
inLoot = false
return
}
var pair = itemPattern.matchMatcher(message) {
/**
* TODO fix the bug that readItemAmount produces two different outputs:
* §r§fEnchanted Book -> §fEnchanted
* §fEnchanted Book §r§8x -> §fEnchanted Book
*
* also maybe this is no bug, as enchanted book is no real item?
*/
ItemUtils.readItemAmount(group("item"))
} ?: return
// Workaround: If it is a enchanted book, we assume it is a paleontologist I book
if (pair.first.let { it == "§fEnchanted" || it == "§fEnchanted Book" }) {
// pair = "Paleontologist I" to pair.second
pair = "§9Ice Cold I" to pair.second
}
loot.add(pair)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package at.hannibal2.skyhanni.features.mining.mineshaft

import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.events.mining.CorpseLootedEvent
import at.hannibal2.skyhanni.utils.ChatUtils
import at.hannibal2.skyhanni.utils.CollectionUtils.sortedDesc
import at.hannibal2.skyhanni.utils.ItemUtils.itemName
import at.hannibal2.skyhanni.utils.NEUInternalName
import at.hannibal2.skyhanni.utils.NEUItems.getPrice
import at.hannibal2.skyhanni.utils.NumberUtil
import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent

class MineshaftCorpseProfitPer {
private val config get() = SkyHanniMod.feature.mining.mineshaft

@SubscribeEvent
fun onFossilExcavation(event: CorpseLootedEvent) {
if (!config.profitPerCorpseLoot) return
val loot = event.loot

var totalProfit = 0.0
val map = mutableMapOf<String, Double>()
for ((name, amount) in loot) {
if (name == "§bGlacite Powder") continue
NEUInternalName.fromItemNameOrNull(name)?.let {
val pricePer = it.getPrice()
if (pricePer == -1.0) continue
val profit = amount * pricePer
val text = "§eFound $name §8${amount.addSeparators()}x §7(§6${NumberUtil.format(profit)}§7)"
map[text] = profit
totalProfit += profit
}
}

val corpseType = event.corpseType
val name = corpseType.displayName

corpseType.key?.let {
val keyName = it.itemName
val price = it.getPrice()

map["$keyName: §c-${NumberUtil.format(price)}"] = -price
totalProfit -= price
}

val hover = map.sortedDesc().keys.toMutableList()
val profitPrefix = if (totalProfit < 0) "§c" else "§6"
val totalMessage = "Profit for $name§e: $profitPrefix${NumberUtil.format(totalProfit)}"
hannibal002 marked this conversation as resolved.
Show resolved Hide resolved
hover.add("")
hover.add("§e$totalMessage")
ChatUtils.hoverableChat(totalMessage, hover)
}
}
33 changes: 22 additions & 11 deletions src/main/java/at/hannibal2/skyhanni/test/command/TestChatCommand.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,35 @@ object TestChatCommand {
val isComplex = mutArgs.remove("-complex")
val isClipboard = mutArgs.remove("-clipboard")
val isHidden = mutArgs.remove("-s")
val multiLines = mutArgs.remove("-lines")
val text = if (isClipboard) {
OSUtils.readFromClipboard()
?: return@launchCoroutine ChatUtils.userError("Clipboard does not contain a string!")
} else mutArgs.joinToString(" ")
val component =
if (isComplex)
try {
IChatComponent.Serializer.jsonToComponent(text)
} catch (ex: Exception) {
ChatUtils.userError("Please provide a valid JSON chat component (either in the command or via -clipboard)")
return@launchCoroutine
}
else ChatComponentText(text.replace("&", "§"))
if (!isHidden) ChatUtils.chat("Testing message: §7${component.formattedText}", prefixColor = "§a")
test(component)
if (multiLines) {
for (line in text.split("\n")) {
extracted(isComplex, line, isHidden)
}
} else {
extracted(isComplex, text, isHidden)
}
}
}

private fun extracted(isComplex: Boolean, text: String, isHidden: Boolean) {
val component =
if (isComplex)
try {
IChatComponent.Serializer.jsonToComponent(text)
} catch (ex: Exception) {
ChatUtils.userError("Please provide a valid JSON chat component (either in the command or via -clipboard)")
return
}
else ChatComponentText(text.replace("&", "§"))
if (!isHidden) ChatUtils.chat("Testing message: §7${component.formattedText}", prefixColor = "§a")
test(component)
}

private fun test(componentText: IChatComponent) {
val message = componentText.formattedText.stripHypixelMessage()
val event = LorenzChatEvent(message, componentText)
Expand Down
Loading