Skip to content

Commit

Permalink
Feature: Personal Compactor Overlay (#1869)
Browse files Browse the repository at this point in the history
Co-authored-by: CalMWolfs <94038482+CalMWolfs@users.noreply.github.com>
Co-authored-by: Cal <cwolfson58@gmail.com>
Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com>
Co-authored-by: ItsEmpa <itsempa@users.noreply.github.com>
  • Loading branch information
5 people authored Sep 7, 2024
1 parent e3b3975 commit f40863a
Show file tree
Hide file tree
Showing 10 changed files with 444 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ public class InventoryConfig {
@Accordion
public HideNotClickableConfig hideNotClickable = new HideNotClickableConfig();

@Expose
@ConfigOption(name = "Personal Compactor Overlay", desc = "Overlay for the Personal Compactor and Deletor.")
@Accordion
public PersonalCompactorConfig personalCompactor = new PersonalCompactorConfig();

@Expose
@ConfigOption(name = "RNG Meter", desc = "")
@Accordion
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package at.hannibal2.skyhanni.config.features.inventory;

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.ConfigEditorDropdown;
import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorKeybind;
import io.github.notenoughupdates.moulconfig.annotations.ConfigOption;
import org.lwjgl.input.Keyboard;

public class PersonalCompactorConfig {

@Expose
@ConfigOption(name = "Enabled", desc = "Enable showing what items are inside your personal compactor/deletor.")
@ConfigEditorBoolean
@FeatureToggle
public boolean enabled = true;

@Expose
@ConfigOption(name = "Visibility Mode", desc = "Choose when to show the overlay.")
@ConfigEditorDropdown
public VisibilityMode visibilityMode = VisibilityMode.EXCEPT_KEYBIND;

public enum VisibilityMode {
ALWAYS("Always"),
KEYBIND("Keybind Held"),
EXCEPT_KEYBIND("Except Keybind Held"),
;

private final String name;

VisibilityMode(String name) {
this.name = name;
}

@Override
public String toString() {
return name;
}
}

@Expose
@ConfigOption(name = "Keybind", desc = "The keybind to hold to show the overlay.")
@ConfigEditorKeybind(defaultKey = Keyboard.KEY_LSHIFT)
public int keybind = Keyboard.KEY_LSHIFT;

@Expose
@ConfigOption(name = "Show On/Off", desc = "Show whether the Personal Compactor/Deletor is currently turned on or off.")
@ConfigEditorBoolean
public boolean showToggle = true;
}
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ object ItemDisplayOverlayFeatures {
}
}

if (VACUUM_GARDEN.isSelected() && internalName in PestAPI.vacuumVariants && isOwnVacuum(lore)) {
if (VACUUM_GARDEN.isSelected() && internalName in PestAPI.vacuumVariants && isOwnItem(lore)) {
lore.matchFirst(gardenVacuumPatterm) {
val pests = group("amount").formatLong()
return if (config.vacuumBagCap) {
Expand Down Expand Up @@ -319,8 +319,13 @@ object ItemDisplayOverlayFeatures {
return null
}

private fun isOwnVacuum(lore: List<String>) =
lore.none { it.contains("Click to trade!") || it.contains("Starting bid:") || it.contains("Buy it now:") }
fun isOwnItem(lore: List<String>) =
lore.none {
it.contains("Click to trade!") ||
it.contains("Starting bid:") ||
it.contains("Buy it now:") ||
it.contains("Click to inspect")
}

var done = false

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

import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.config.features.inventory.PersonalCompactorConfig
import at.hannibal2.skyhanni.events.InventoryCloseEvent
import at.hannibal2.skyhanni.events.InventoryUpdatedEvent
import at.hannibal2.skyhanni.events.LorenzToolTipEvent
import at.hannibal2.skyhanni.events.RenderItemTipEvent
import at.hannibal2.skyhanni.events.RenderObject
import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule
import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName
import at.hannibal2.skyhanni.utils.ItemUtils.getInternalNameOrNull
import at.hannibal2.skyhanni.utils.KeyboardManager.isKeyHeld
import at.hannibal2.skyhanni.utils.LorenzUtils
import at.hannibal2.skyhanni.utils.NEUItems.getInternalNameFromHypixelId
import at.hannibal2.skyhanni.utils.NEUItems.getItemStack
import at.hannibal2.skyhanni.utils.NumberUtil.formatInt
import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher
import at.hannibal2.skyhanni.utils.RegexUtils.matches
import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getAttributeString
import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getItemUuid
import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getPersonalCompactorActive
import at.hannibal2.skyhanni.utils.renderables.Renderable
import at.hannibal2.skyhanni.utils.renderables.RenderableInventory
import at.hannibal2.skyhanni.utils.renderables.RenderableTooltips
import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern
import net.minecraft.item.ItemStack
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent

@SkyHanniModule
object PersonalCompactorOverlay {

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

private val group = RepoPattern.group("inventory.personalcompactor")
private val internalNamePattern by group.pattern(
"internalname",
"PERSONAL_(?<type>[^_]+)_(?<tier>\\d+)",
)

private val slotsMap = mapOf(
7000 to 12,
6000 to 7,
5000 to 3,
4000 to 1
)

private const val MAX_ITEMS_PER_ROW = 7

private val compactorRenderableMap = mutableMapOf<String, Renderable>()
private val compactorEnabledMap = mutableMapOf<String, Boolean>()

@SubscribeEvent
fun onTooltip(event: LorenzToolTipEvent) {
if (!isEnabled()) return
if (!shouldShow()) return

val itemStack = event.itemStack
val internalName = itemStack.getInternalName()
val name = event.toolTip.firstOrNull() ?: return
val (type, tier) = internalNamePattern.matchMatcher(internalName.asString()) {
group("type") to group("tier").formatInt()
} ?: return

val prefix = when (type) {
"COMPACTOR" -> "personal_compact_"
"DELETOR" -> "personal_deletor_"
else -> return
}

val uuid = itemStack.getItemUuid() ?: return
val enabled = getPersonalCompactorEnabled(itemStack) ?: return

val fakeInventory = compactorRenderableMap.getOrPut(uuid) {
val slots = slotsMap[tier] ?: return
val itemList = (0 until slots).map { slot ->
val skyblockId = itemStack.getAttributeString(prefix + slot)
skyblockId?.let { getInternalNameFromHypixelId(it) }?.getItemStack()
}

RenderableInventory.fakeInventory(itemList, MAX_ITEMS_PER_ROW, 1.0)
}

val title = Renderable.string(name)
val status = Renderable.string(
"§7Status: " + if (enabled) "§aEnabled" else "§cDisabled"
)

RenderableTooltips.setTooltipForRender(listOf(title, status, fakeInventory), spacedTitle = true)
event.cancel()
}

@SubscribeEvent
fun onInventoryClose(event: InventoryCloseEvent) {
compactorRenderableMap.clear()
}

@SubscribeEvent
fun onInventoryUpdate(event: InventoryUpdatedEvent) {
compactorEnabledMap.clear()
}

@SubscribeEvent
fun onRenderItemTip(event: RenderItemTipEvent) {
if (!LorenzUtils.inSkyBlock) return
if (!config.showToggle) return
val itemStack = event.stack
val internalName = itemStack.getInternalNameOrNull() ?: return
if (!internalNamePattern.matches(internalName.asString())) return

val enabled = getPersonalCompactorEnabled(itemStack) ?: return
val text = if (enabled) "§a✔" else "§c✖"
val renderObject = RenderObject(
text,
-8,
-10
)
event.renderObjects.add(renderObject)
}

private fun shouldShow() = when (config.visibilityMode) {
PersonalCompactorConfig.VisibilityMode.ALWAYS -> true
PersonalCompactorConfig.VisibilityMode.KEYBIND -> config.keybind.isKeyHeld()
PersonalCompactorConfig.VisibilityMode.EXCEPT_KEYBIND -> !config.keybind.isKeyHeld()
else -> false
}

private fun getPersonalCompactorEnabled(itemStack: ItemStack): Boolean? {
val uuid = itemStack.getItemUuid() ?: return null
return compactorEnabledMap.getOrPut(uuid) { itemStack.getPersonalCompactorActive() }
}

private fun isEnabled() = LorenzUtils.inSkyBlock && config.enabled
}
11 changes: 11 additions & 0 deletions src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import at.hannibal2.skyhanni.utils.NumberUtil.isInt
import at.hannibal2.skyhanni.utils.PrimitiveItemStack.Companion.makePrimitiveStack
import at.hannibal2.skyhanni.utils.json.BaseGsonBuilder
import at.hannibal2.skyhanni.utils.json.fromJson
import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getItemId
import at.hannibal2.skyhanni.utils.system.PlatformUtils
import com.google.gson.JsonObject
import com.google.gson.JsonPrimitive
Expand Down Expand Up @@ -169,6 +170,16 @@ object NEUItems {
fun getInternalNameOrNull(nbt: NBTTagCompound): NEUInternalName? =
ItemResolutionQuery(manager).withItemNBT(nbt).resolveInternalName()?.asInternalName()

fun getInternalNameFromHypixelIdOrNull(hypixelId: String): NEUInternalName? {
val internalName = hypixelId.replace(':', '-')
return internalName.asInternalName().takeIf { it.getItemStackOrNull()?.getItemId() == internalName }
}

fun getInternalNameFromHypixelId(hypixelId: String): NEUInternalName =
getInternalNameFromHypixelIdOrNull(hypixelId)
?: error("hypixel item id does not match internal name: $hypixelId")


@Deprecated("Moved to ItemPriceUtils", ReplaceWith(""))
fun NEUInternalName.getPrice(
priceSource: ItemPriceSource = ItemPriceSource.BAZAAR_INSTANT_BUY,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,8 @@ object SkyBlockItemModifierUtils {

fun ItemStack.getNewYearCake() = getAttributeInt("new_years_cake")

fun ItemStack.getPersonalCompactorActive() = getAttributeByte("PERSONAL_DELETOR_ACTIVE") == 1.toByte()

fun ItemStack.getEnchantments(): Map<String, Int>? = getExtraAttributes()
?.takeIf { it.hasKey("enchantments") }
?.run {
Expand Down Expand Up @@ -253,7 +255,7 @@ object SkyBlockItemModifierUtils {
list
}

private fun ItemStack.getAttributeString(label: String) =
fun ItemStack.getAttributeString(label: String) =
getExtraAttributes()?.getString(label)?.takeUnless { it.isBlank() }

private fun ItemStack.getAttributeInt(label: String) =
Expand All @@ -262,9 +264,11 @@ object SkyBlockItemModifierUtils {
private fun ItemStack.getAttributeLong(label: String) =
getExtraAttributes()?.getLong(label)?.takeUnless { it == 0L }

private fun ItemStack.getAttributeBoolean(label: String): Boolean {
return getExtraAttributes()?.getBoolean(label) ?: false
}
private fun ItemStack.getAttributeBoolean(label: String) =
getExtraAttributes()?.getBoolean(label) ?: false

private fun ItemStack.getAttributeByte(label: String) =
getExtraAttributes()?.getByte(label) ?: 0

fun ItemStack.getExtraAttributes() = tagCompound?.getCompoundTag("ExtraAttributes")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ interface Renderable {
highlightsOnHoverSlots: List<Int> = listOf(),
stack: ItemStack? = null,
color: LorenzColor? = null,
spacedTitle: Boolean = false,
bypassChecks: Boolean = false,
snapsToTopIfToLong: Boolean = true,
condition: () -> Boolean = { true },
Expand Down Expand Up @@ -231,6 +232,7 @@ interface Renderable {
stack = stack,
borderColor = color,
snapsToTopIfToLong = snapsToTopIfToLong,
spacedTitle = spacedTitle,
)
GlStateManager.popMatrix()
}
Expand Down Expand Up @@ -839,6 +841,25 @@ interface Renderable {
}
}

fun paddingContainer(
content: Renderable,
topSpacing: Int = 0,
bottomSpacing: Int = 0,
leftSpacing: Int = 0,
rightSpacing: Int = 0,
) = object : Renderable {
override val width = content.width + leftSpacing + rightSpacing
override val height = content.height + topSpacing + bottomSpacing
override val horizontalAlign = content.horizontalAlign
override val verticalAlign = content.verticalAlign

override fun render(posX: Int, posY: Int) {
GlStateManager.translate(leftSpacing.toFloat(), topSpacing.toFloat(), 0f)
content.render(posX + leftSpacing, posY + topSpacing)
GlStateManager.translate(-leftSpacing.toFloat(), -topSpacing.toFloat(), 0f)
}
}

fun scrollList(
list: List<Renderable>,
height: Int,
Expand Down Expand Up @@ -1063,11 +1084,56 @@ interface Renderable {
}
}

fun drawInsideFixedSizedImage(
input: Renderable,
texture: ResourceLocation,
width: Int = input.width,
height: Int = input.height,
alpha: Int = 255,
padding: Int = 2,
uMin: Float = 0f,
uMax: Float = 1f,
vMin: Float = 0f,
vMax: Float = 1f,
horizontalAlign: HorizontalAlignment = HorizontalAlignment.LEFT,
verticalAlign: VerticalAlignment = VerticalAlignment.TOP,
) = object : Renderable {
override val width = width
override val height = height
override val horizontalAlign = horizontalAlign
override val verticalAlign = verticalAlign

override fun render(posX: Int, posY: Int) {
Minecraft.getMinecraft().textureManager.bindTexture(texture)
GlStateManager.color(1f, 1f, 1f, alpha / 255f)
Utils.drawTexturedRect(
0f,
0f,
width.toFloat(),
height.toFloat(),
uMin,
uMax,
vMin,
vMax,
GL11.GL_NEAREST
)
GlStateManager.color(1f, 1f, 1f, 1f)

GlStateManager.translate(padding.toFloat(), padding.toFloat(), 0f)
input.render(posX + padding, posY + padding)
GlStateManager.translate(-padding.toFloat(), -padding.toFloat(), 0f)
}
}

fun image(
texture: ResourceLocation,
width: Int,
height: Int,
alpha: Int = 255,
uMin: Float = 0f,
uMax: Float = 1f,
vMin: Float = 0f,
vMax: Float = 1f,
horizontalAlign: HorizontalAlignment = HorizontalAlignment.LEFT,
verticalAlign: VerticalAlignment = VerticalAlignment.TOP,
) = object : Renderable {
Expand All @@ -1079,7 +1145,17 @@ interface Renderable {
override fun render(posX: Int, posY: Int) {
Minecraft.getMinecraft().textureManager.bindTexture(texture)
GlStateManager.color(1f, 1f, 1f, alpha / 255f)
Utils.drawTexturedRect(0f, 0f, width.toFloat(), height.toFloat(), GL11.GL_NEAREST)
Utils.drawTexturedRect(
0f,
0f,
width.toFloat(),
height.toFloat(),
uMin,
uMax,
vMin,
vMax,
GL11.GL_NEAREST
)
GlStateManager.color(1f, 1f, 1f, 1f)
}
}
Expand Down
Loading

0 comments on commit f40863a

Please sign in to comment.