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: Craftable Item List #1334

Merged
merged 43 commits into from
Jun 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
18b2bf9
Added Alignment
Thunderblade73 Jan 7, 2024
85d7705
Added ScrollList, ScrollTable
Thunderblade73 Jan 7, 2024
653d1e2
moved alignment enums to renderUtils
Thunderblade73 Jan 15, 2024
0323811
fixed scrolling
Thunderblade73 Jan 26, 2024
b88dc7b
Merge branch 'beta' into renderable-Align
Thunderblade73 Feb 5, 2024
fb4c99a
Merge branch 'renderable-Align' into renderable-scrollable
Thunderblade73 Feb 5, 2024
4b84824
Merge branch 'beta' into renderable-scrollable
Thunderblade73 Feb 26, 2024
fb5a7b8
Merge branch 'beta' into renderable-scrollable
Thunderblade73 Mar 4, 2024
3540f64
fix
Thunderblade73 Mar 4, 2024
c89da8a
abstracted ScrollInput properly
Thunderblade73 Mar 12, 2024
c0faf9e
Add Craftable Item List
hannibal002 Apr 1, 2024
981f0ed
typos
hannibal002 Apr 1, 2024
238e80b
Merge branch 'beta' into crabable-item-list
hannibal002 Apr 3, 2024
0bbe7d4
move
hannibal002 Apr 3, 2024
20e56b5
Merge branch 'beta' into crabable-item-list
hannibal002 Apr 4, 2024
15cf37a
toggle include to exclude, better description
hannibal002 Apr 4, 2024
0622235
Update src/main/java/at/hannibal2/skyhanni/features/inventory/craft/C…
hannibal002 Apr 5, 2024
905b974
Merge branch 'beta' into crabable-item-list
hannibal002 Apr 5, 2024
6f186ed
no longer removing name color
hannibal002 Apr 5, 2024
805ce1e
make the ScrollValue persistent even when the scroll object changes.
Thunderblade73 Apr 9, 2024
ecd370e
Merge branch 'beta' into renderable-scrollable
Thunderblade73 Apr 9, 2024
77ae3a3
Merge branch 'beta' into renderable-scrollable
Thunderblade73 Apr 13, 2024
471c4f4
Merge branch 'beta' into crabable-item-list
hannibal002 Apr 25, 2024
3301981
fix merge conflicts
hannibal002 Apr 25, 2024
82339c6
Merge branch 'beta' into fork/renderable-scrollable
hannibal002 Apr 30, 2024
4d6baf3
Merge branch 'fork/renderable-scrollable' into crabable-item-list
hannibal002 Apr 30, 2024
2a28b48
using scrollable list
hannibal002 Apr 30, 2024
6a1be68
bug fix
Thunderblade73 Apr 30, 2024
c4c825d
add last element if possible to list
Thunderblade73 Apr 30, 2024
45f5ed2
better default velocity
Thunderblade73 Apr 30, 2024
bbb2d7a
Merge branch 'beta' into renderable-scrollable
Thunderblade73 Apr 30, 2024
bf3b5f5
Merge branch 'fork/renderable-scrollable' into crabable-item-list
hannibal002 Apr 30, 2024
c995e65
fix some things
hannibal002 Apr 30, 2024
ae06a75
Merge branch 'beta' into crabable-item-list
hannibal002 Apr 30, 2024
b01db90
Merge branch 'beta' into crabable-item-list
CalMWolfs May 1, 2024
fe75367
Merge branch 'refs/heads/beta' into crabable-item-list
hannibal002 May 28, 2024
c2304c5
Merge branch 'refs/heads/beta' into crabable-item-list
hannibal002 Jun 16, 2024
d864960
code cleanup
hannibal002 Jun 16, 2024
d681794
code cleanup
hannibal002 Jun 16, 2024
b2d7d87
faster and more to scroll, sorts by single item price
hannibal002 Jun 16, 2024
2144a08
changed format, added recipe infos
hannibal002 Jun 16, 2024
46a736f
opens the super craft inventory directly
hannibal002 Jun 16, 2024
785f12b
refactoring
hannibal002 Jun 16, 2024
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package at.hannibal2.skyhanni.config.features.inventory;

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

public class CraftableItemListConfig {

@Expose
@ConfigOption(
name = "Enabled",
desc = "Shows a list of items that can be crafted with the items in inventory when inside the crafting menu. " +
"Click on the item to open §e/recipe§7."
)
@ConfigEditorBoolean
@FeatureToggle
public boolean enabled = false;

@Expose
@ConfigOption(
name = "Include Sacks",
desc = "Include items from inside the sacks.")
@ConfigEditorBoolean
public boolean includeSacks = false;

@Expose
@ConfigOption(
name = "Exclude Vanilla Items",
desc = "Hide vanilla items from the craftable item list.")
@ConfigEditorBoolean
public boolean excludeVanillaItems = true;

@Expose
@ConfigLink(owner = CraftableItemListConfig.class, field = "enabled")
public Position position = new Position(144, 139, false, true);
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,12 @@ public class InventoryConfig {
@Expose
@Category(name = "Chocolate Factory", desc = "Features to help you master the Chocolate Factory idle game.")
public ChocolateFactoryConfig chocolateFactory = new ChocolateFactoryConfig();


@Expose
@Category(name = "Craftable Item List", desc = "")
@Accordion
public CraftableItemListConfig craftableItemList = new CraftableItemListConfig();

@Expose
@ConfigOption(name = "Not Clickable Items", desc = "Better not click that item.")
@Accordion
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
package at.hannibal2.skyhanni.features.inventory.craft

import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.data.SackAPI.getAmountInSacks
import at.hannibal2.skyhanni.events.GuiRenderEvent
import at.hannibal2.skyhanni.events.InventoryCloseEvent
import at.hannibal2.skyhanni.events.InventoryOpenEvent
import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule
import at.hannibal2.skyhanni.utils.CollectionUtils.addOrPut
import at.hannibal2.skyhanni.utils.CollectionUtils.sortedDesc
import at.hannibal2.skyhanni.utils.HypixelCommands
import at.hannibal2.skyhanni.utils.InventoryUtils
import at.hannibal2.skyhanni.utils.ItemUtils.itemName
import at.hannibal2.skyhanni.utils.LorenzUtils
import at.hannibal2.skyhanni.utils.NEUInternalName
import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName
import at.hannibal2.skyhanni.utils.NEUItems
import at.hannibal2.skyhanni.utils.NEUItems.getPrice
import at.hannibal2.skyhanni.utils.NEUItems.isVanillaItem
import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators
import at.hannibal2.skyhanni.utils.NumberUtil.shortFormat
import at.hannibal2.skyhanni.utils.PrimitiveItemStack.Companion.toPrimitiveStackOrNull
import at.hannibal2.skyhanni.utils.RegexUtils.matches
import at.hannibal2.skyhanni.utils.RenderUtils.renderRenderables
import at.hannibal2.skyhanni.utils.StringUtils
import at.hannibal2.skyhanni.utils.renderables.Renderable
import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern
import io.github.moulberry.notenoughupdates.recipes.CraftingRecipe
import io.github.moulberry.notenoughupdates.recipes.NeuRecipe
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import kotlin.math.floor

@SkyHanniModule
object CraftableItemList {
private val config get() = SkyHanniMod.feature.inventory.craftableItemList

private var display = listOf<Renderable>()
private var inInventory = false
private val craftItemPattern by RepoPattern.pattern(
"craftableitemlist.craftitem",
"Craft Item",
)

@SubscribeEvent
fun onInventoryOpen(event: InventoryOpenEvent) {
if (!isEnabled()) return
if (!craftItemPattern.matches(event.inventoryName)) return
inInventory = true

val pricePer = mutableMapOf<NEUInternalName, Double>()
val lines = mutableMapOf<NEUInternalName, Renderable>()
loadItems(pricePer, lines)

display = if (lines.isEmpty()) {
listOf(Renderable.string("§7No Items to craft"))
} else {
val items = pricePer.sortedDesc().keys.map { lines[it] ?: error("impossible") }
listOf(
Renderable.string("§eCraftable items (${items.size})"),
Renderable.scrollList(items, height = 250, velocity = 20.0),
)
}
}

private fun loadItems(
pricePer: MutableMap<NEUInternalName, Double>,
lines: MutableMap<NEUInternalName, Renderable>,
) {
val availableMaterial = readItems()
for (internalName in NEUItems.allInternalNames) {
if (config.excludeVanillaItems && internalName.isVanillaItem()) continue

val recipes = NEUItems.getRecipes(internalName)
for (recipe in recipes) {
if (recipe !is CraftingRecipe) continue
val renderable = createItemRenderable(recipe, availableMaterial, pricePer, internalName) ?: continue
lines[internalName] = renderable
}
}
}

private fun createItemRenderable(
recipe: CraftingRecipe,
availableMaterial: Map<NEUInternalName, Long>,
pricePer: MutableMap<NEUInternalName, Double>,
internalName: NEUInternalName,
): Renderable? {
val neededItems = neededItems(recipe)
// Just a fail save, should not happen normally
if (neededItems.isEmpty()) return null

val canCraftAmount = canCraftAmount(neededItems, availableMaterial)
if (canCraftAmount <= 0) return null

val amountFormat = canCraftAmount.addSeparators()
val totalPrice = pricePer(neededItems)
pricePer[internalName] = totalPrice
val tooltip = buildList<String> {
add(internalName.itemName)
add("")
add("§7Craft cost: §6${totalPrice.shortFormat()}")
for ((item, amount) in neededItems) {
val name = item.itemName
val price = item.getPrice() * amount
add(" §8x${amount.addSeparators()} $name §7(§6${price.shortFormat()}§7)")
}
add("")
add("§7You have enough materials")
val timeName = StringUtils.pluralize(canCraftAmount, "time", "times")
add("§7to craft this item $amountFormat $timeName!")
add("")
add("§eClick to craft!")
}
return Renderable.clickAndHover(
"§8x$amountFormat ${internalName.itemName}",
tips = tooltip,
onClick = {
HypixelCommands.viewRecipe(internalName.asString())
},
)
}

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

private fun pricePer(neededItems: Map<NEUInternalName, Int>): Double = neededItems.map { it.key.getPrice() * it.value }.sum()

private fun canCraftAmount(
need: Map<NEUInternalName, Int>,
available: Map<NEUInternalName, Long>,
): Int {
val canCraftTotal = mutableListOf<Int>()
for ((name, neededAmount) in need) {
val inventory = available[name] ?: 0
val sacks = if (config.includeSacks) name.getAmountInSacks() else 0
val having = inventory + sacks
val canCraft = floor(having.toDouble() / neededAmount).toInt()
canCraftTotal.add(canCraft)
}
return canCraftTotal.min()
}

private fun neededItems(recipe: NeuRecipe): MutableMap<NEUInternalName, Int> {
val neededItems = mutableMapOf<NEUInternalName, Int>()
for (ingredient in recipe.ingredients) {
val material = ingredient.internalItemId.asInternalName()
val amount = ingredient.count.toInt()
neededItems.addOrPut(material, amount)
}
return neededItems
}

private fun readItems(): Map<NEUInternalName, Long> {
val materials = mutableMapOf<NEUInternalName, Long>()
for (stack in InventoryUtils.getItemsInOwnInventory()) {
val item = stack.toPrimitiveStackOrNull() ?: continue
materials.addOrPut(item.internalName, item.amount.toLong())
}
return materials
}

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

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

fun isEnabled() = LorenzUtils.inSkyBlock && config.enabled
}
5 changes: 3 additions & 2 deletions src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt
Original file line number Diff line number Diff line change
Expand Up @@ -215,8 +215,9 @@ object NEUItems {
fallbackItem
}

fun isVanillaItem(item: ItemStack): Boolean =
manager.auctionManager.isVanillaItem(item.getInternalName().asString())
fun isVanillaItem(item: ItemStack): Boolean = item.getInternalName().isVanillaItem()

fun NEUInternalName.isVanillaItem(): Boolean = manager.auctionManager.isVanillaItem(this.asString())

const val itemFontSize = 2.0 / 3.0

Expand Down
Loading