Skip to content

Commit

Permalink
Feature: Craft Materials From Bazaar (hannibal002#1104)
Browse files Browse the repository at this point in the history
Co-authored-by: Thunderblade73 <85900443+Thunderblade73@users.noreply.github.com>
Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com>
  • Loading branch information
3 people committed Mar 14, 2024
1 parent 8feecf4 commit 23a1d04
Show file tree
Hide file tree
Showing 5 changed files with 189 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ import at.hannibal2.skyhanni.features.inventory.bazaar.BazaarBestSellMethod
import at.hannibal2.skyhanni.features.inventory.bazaar.BazaarCancelledBuyOrderClipboard
import at.hannibal2.skyhanni.features.inventory.bazaar.BazaarOpenPriceWebsite
import at.hannibal2.skyhanni.features.inventory.bazaar.BazaarOrderHelper
import at.hannibal2.skyhanni.features.inventory.bazaar.CraftMaterialsFromBazaar
import at.hannibal2.skyhanni.features.inventory.tiarelay.TiaRelayHelper
import at.hannibal2.skyhanni.features.inventory.tiarelay.TiaRelayWaypoints
import at.hannibal2.skyhanni.features.itemabilities.ChickenHeadTimer
Expand Down Expand Up @@ -789,6 +790,7 @@ class SkyHanniMod {
loadModule(InfernoMinionFeatures())
loadModule(LimboPlaytime())
loadModule(RareDropMessages())
loadModule(CraftMaterialsFromBazaar())

init()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,13 @@ public class BazaarConfig {

@Expose
public Position maxPurseItemsPosition = new Position(346, 90, true, false);

@Expose
@ConfigOption(name = "Craft Materials Bazaar", desc = "In the crafting view, offer a shopping list of required materials for the craft along with a convenient shortcut for purchasing them from the Bazaar.")
@ConfigEditorBoolean
@FeatureToggle
public boolean craftMaterialsFromBazaar = false;

@Expose
public Position craftMaterialsFromBazaarPosition = new Position(50, 50, true, false);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package at.hannibal2.skyhanni.events

import at.hannibal2.skyhanni.data.OtherInventoryData
import at.hannibal2.skyhanni.utils.PrimitiveItemStack
import at.hannibal2.skyhanni.utils.PrimitiveItemStack.Companion.toPrimitiveStackOrNull
import net.minecraft.item.ItemStack

open class InventoryOpenEvent(private val inventory: OtherInventoryData.Inventory) : LorenzEvent() {
Expand All @@ -12,6 +14,15 @@ open class InventoryOpenEvent(private val inventory: OtherInventoryData.Inventor
val inventoryItemsWithNull: Map<Int, ItemStack?> by lazy {
(0 until inventorySize).associateWith { inventoryItems[it] }
}
val inventoryItemsPrimitive: Map<Int, PrimitiveItemStack> by lazy {
val map = mutableMapOf<Int, PrimitiveItemStack>()
for ((slot, item) in inventoryItems) {
item.toPrimitiveStackOrNull()?.let {
map[slot] = it
}
}
map
}
val fullyOpenedOnce: Boolean get() = inventory.fullyOpenedOnce
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
package at.hannibal2.skyhanni.features.inventory.bazaar

import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.events.GuiRenderEvent
import at.hannibal2.skyhanni.events.InventoryCloseEvent
import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent
import at.hannibal2.skyhanni.features.inventory.bazaar.BazaarApi.Companion.isBazaarItem
import at.hannibal2.skyhanni.utils.CollectionUtils.addOrPut
import at.hannibal2.skyhanni.utils.ItemUtils.itemName
import at.hannibal2.skyhanni.utils.ItemUtils.itemNameWithoutColor
import at.hannibal2.skyhanni.utils.ItemUtils.name
import at.hannibal2.skyhanni.utils.LorenzUtils
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 at.hannibal2.skyhanni.utils.PrimitiveItemStack
import at.hannibal2.skyhanni.utils.PrimitiveItemStack.Companion.makePrimitiveStack
import at.hannibal2.skyhanni.utils.RenderUtils.renderRenderables
import at.hannibal2.skyhanni.utils.StringUtils.matches
import at.hannibal2.skyhanni.utils.renderables.Renderable
import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent

class CraftMaterialsFromBazaar {

private val config get() = SkyHanniMod.feature.inventory.bazaar

private val materialSlots = listOf(10, 11, 12, 19, 20, 21, 28, 29, 30)
private val inventoryPattern by RepoPattern.pattern(
"inventory.recipe.title",
".* Recipe"
)

private var inRecipeInventory = false
private var purchasing = false
private var display = listOf<Renderable>()
private var neededMaterials = listOf<PrimitiveItemStack>()
private var multiplier = 1

@SubscribeEvent
fun onInventoryOpen(event: InventoryFullyOpenedEvent) {
if (!isEnabled()) return
val correctInventoryName = inventoryPattern.matches(event.inventoryName)
val items = event.inventoryItems
val correctItem = items[23]?.name == "§aCrafting Table"

inRecipeInventory = correctInventoryName && correctItem && !purchasing
if (!inRecipeInventory) return

val recipeName = items[25]?.itemName ?: return
showRecipe(calculateMaterialsNeeded(event.inventoryItemsPrimitive), recipeName)
}

private fun showRecipe(
recipeMaterials: List<PrimitiveItemStack>,
recipeName: String,
) {
val neededMaterials = mutableListOf<PrimitiveItemStack>()
display = buildList {
val totalPrice = calculateTotalPrice(recipeMaterials, 1)
add(Renderable.string("§7Craft $recipeName §7(§6${NumberUtil.format(totalPrice)}§7)"))
for (item in recipeMaterials) {
val material = item.internalName
val amount = item.amount
var text = "§8${amount.addSeparators()}x " + material.itemName
if (material.isBazaarItem()) {
neededMaterials.add(item)
text += " §6${NumberUtil.format(material.getPrice() * amount)}"
}
add(Renderable.string(text))
}
if (neededMaterials.isNotEmpty()) {
add(
Renderable.clickAndHover(
"§eGet from bazaar!",
listOf("§eClick here to buy the items from bazaar!"),
onClick = {
getFromBazaar(neededMaterials)
})
)
}
}
}

private fun calculateMaterialsNeeded(items: Map<Int, PrimitiveItemStack>): List<PrimitiveItemStack> {
val recipeMaterials = mutableMapOf<NEUInternalName, Int>()
for (slot in materialSlots) {
val item = items[slot] ?: continue
val internalName = item.internalName
recipeMaterials.addOrPut(internalName, item.amount)
}
return recipeMaterials.map { it.key.makePrimitiveStack(it.value) }
}

private fun getFromBazaar(neededMaterials: MutableList<PrimitiveItemStack>) {
this.neededMaterials = neededMaterials
this.multiplier = 1
purchasing = true
updateBazaarDisplay()
}

private fun updateBazaarDisplay() {
display = buildList {
add(Renderable.string("§7Buy items from Bazaar:"))
for ((material, amount) in neededMaterials) {
val priceMultiplier = amount * multiplier
val text = "§8${priceMultiplier.addSeparators()}x " + material.itemName +
" §6${NumberUtil.format(material.getPrice() * priceMultiplier)}"
add(Renderable.optionalLink(text, onClick = {
BazaarApi.searchForBazaarItem(material.itemNameWithoutColor, priceMultiplier)
}))
}
add(
Renderable.clickAndHover(
"§eStop!",
listOf("§eClick here to stop this view!"),
onClick = {
purchasing = false
display = emptyList()
})
)
addMultipliers()
}
}

private fun MutableList<Renderable>.addMultipliers() {
for (m in listOf(1, 5, 16, 32, 64, 512)) {
val nameColor = if (m == multiplier) "§amount" else "§e"
val priceColor = if (m == multiplier) "§6" else "§7"
val price = priceColor + NumberUtil.format(calculateTotalPrice(neededMaterials, m))
add(
Renderable.clickAndHover(
"${nameColor}Mulitply x$m $price",
listOf("§eClick here to multiply the items needed times $m!"),
onClick = {
multiplier = m
updateBazaarDisplay()
})
)
}
}

private fun calculateTotalPrice(neededMaterials: List<PrimitiveItemStack>, multiplier: Int): Double =
neededMaterials
.filter { it.internalName.isBazaarItem() }
.sumOf { it.internalName.getPrice() * it.amount * multiplier }

@SubscribeEvent
fun onInventoryClose(event: InventoryCloseEvent) {
inRecipeInventory = false
}

@SubscribeEvent
fun onRenderOverlay(event: GuiRenderEvent.ChestGuiOverlayRenderEvent) {
if (!isEnabled()) return
if (!inRecipeInventory && !purchasing) return

config.craftMaterialsFromBazaarPosition.renderRenderables(display, posLabel = "Craft Materials From Bazaar")
}

fun isEnabled() = LorenzUtils.inSkyBlock && config.craftMaterialsFromBazaar

}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package at.hannibal2.skyhanni.utils

import at.hannibal2.skyhanni.utils.ItemUtils.getInternalNameOrNull
import at.hannibal2.skyhanni.utils.ItemUtils.itemName
import at.hannibal2.skyhanni.utils.NEUItems.getItemStack
import net.minecraft.item.ItemStack

data class PrimitiveItemStack(val internalName: NEUInternalName, val amount: Int) {

Expand All @@ -12,5 +14,6 @@ data class PrimitiveItemStack(val internalName: NEUInternalName, val amount: Int
companion object {

fun NEUInternalName.makePrimitiveStack(amount: Int) = PrimitiveItemStack(this, amount)
fun ItemStack.toPrimitiveStackOrNull() = getInternalNameOrNull()?.let { PrimitiveItemStack(it, stackSize) }
}
}

0 comments on commit 23a1d04

Please sign in to comment.