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: Extra Harp Features #741

Merged
merged 14 commits into from
Jan 21, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,17 @@ public class HelperConfig {
public HarpConfig harp = new HarpConfig();

public static class HarpConfig {
@Expose
@ConfigOption(name = "GUI Scale", desc = "Automatically sets the GUI scale to \"AUTO\" when entering the Harp.")
@ConfigEditorBoolean
public boolean guiScale = false;

@Expose
@ConfigOption(name = "Quick Restart", desc = "Once you've launched the Harp, quickly hit the close button in the Harp Menu to initiate the selected song.")
@ConfigEditorBoolean
@FeatureToggle
public boolean quickRestart = false;

@Expose
@ConfigOption(name = "Use Keybinds", desc = "In the Harp, press buttons with your number row on the keyboard instead of clicking.")
@ConfigEditorBoolean
Expand Down
112 changes: 106 additions & 6 deletions src/main/java/at/hannibal2/skyhanni/features/inventory/HarpFeatures.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,40 @@ package at.hannibal2.skyhanni.features.inventory

import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator
import at.hannibal2.skyhanni.events.GuiContainerEvent
import at.hannibal2.skyhanni.events.InventoryCloseEvent
import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent
import at.hannibal2.skyhanni.events.RenderItemTipEvent
import at.hannibal2.skyhanni.utils.InventoryUtils.openInventoryName
import at.hannibal2.skyhanni.utils.DelayedRun
import at.hannibal2.skyhanni.utils.InventoryUtils
import at.hannibal2.skyhanni.utils.ItemUtils.getLore
import at.hannibal2.skyhanni.utils.KeyboardManager
import at.hannibal2.skyhanni.utils.KeyboardManager.isKeyHeld
import at.hannibal2.skyhanni.utils.LorenzUtils
import at.hannibal2.skyhanni.utils.SimpleTimeMark
import at.hannibal2.skyhanni.utils.StringUtils.anyMatches
import at.hannibal2.skyhanni.utils.StringUtils.matches
import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern
import net.minecraft.client.Minecraft
import net.minecraft.client.gui.ScaledResolution
import net.minecraft.client.gui.inventory.GuiChest
import net.minecraft.item.Item
import net.minecraftforge.client.event.GuiScreenEvent
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import net.minecraftforge.fml.common.network.FMLNetworkEvent
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds

// Delaying key presses by 300ms comes from NotEnoughUpdates
object HarpFeatures {

private val config get() = SkyHanniMod.feature.inventory.helper.harp
private var lastClick = SimpleTimeMark.farPast()

private const val closeButtonSlot = 40

private object KeyIterable : Iterable<Int> {

override fun iterator() = object : Iterator<Int> {
private var currentIndex = 0

Expand All @@ -33,15 +46,18 @@ object HarpFeatures {
}

private val buttonColors = listOf('d', 'e', 'a', '2', '5', '9', 'b')
private val inventoryTitlePattern by RepoPattern.pattern("harp.inventory", "^Harp.*")
private val inventoryTitlePattern by RepoPattern.pattern("harp.inventory", "Harp.*")
private val menuTitlePattern by RepoPattern.pattern("harp.menu", "Melody.*")
private val songSelectedPattern by RepoPattern.pattern("harp.song.selected", "§aSong is selected!")

private fun isHarpGui() = inventoryTitlePattern.matches(openInventoryName())
private fun isHarpGui(chestName: String) = inventoryTitlePattern.matches(chestName)
private fun isMenuGui(chestName: String) = menuTitlePattern.matches(chestName)

@SubscribeEvent
fun onGui(event: GuiScreenEvent) {
if (!LorenzUtils.inSkyBlock) return
if (!config.keybinds) return
if (!isHarpGui()) return
if (!isHarpGui(InventoryUtils.openInventoryName())) return
val chest = event.gui as? GuiChest ?: return

for ((index, key) in KeyIterable.withIndex()) {
Expand Down Expand Up @@ -72,19 +88,103 @@ object HarpFeatures {
else -> null
}

private var openTime: SimpleTimeMark = SimpleTimeMark.farPast()

@SubscribeEvent
fun onInventoryOpen(event: InventoryFullyOpenedEvent) {
if (!LorenzUtils.inSkyBlock) return
if (!config.guiScale) return
when {
isMenuGui(event.inventoryName) -> {
setGUIScale()
openTime = SimpleTimeMark.now()
}

isHarpGui(event.inventoryName) -> {
setGUIScale()
}
}
}

private fun updateScale() {
if (Minecraft.getMinecraft().currentScreen == null) {
DelayedRun.runNextTick() {
updateScale()
}
return
}
// Copied from Minecraft Code to update the scale
val minecraft = Minecraft.getMinecraft()
val scaledresolution = ScaledResolution(minecraft)
val i = scaledresolution.scaledWidth
val j = scaledresolution.scaledHeight
minecraft.currentScreen.setWorldAndResolution(minecraft, i, j)
}

@SubscribeEvent
fun onInventoryCloseEvent(event: InventoryCloseEvent) {
if (!LorenzUtils.inSkyBlock) return
if (!config.guiScale) return
unSetGUIScale()
}

@SubscribeEvent
fun onLeave(event: FMLNetworkEvent.ClientDisconnectionFromServerEvent) {
if (!config.guiScale) return
unSetGUIScale()
}

private var guiSetting: Int = 0
private var isGUIScaled = false

private fun setGUIScale() {
val gameSettings = Minecraft.getMinecraft().gameSettings ?: return
guiSetting = gameSettings.guiScale
gameSettings.guiScale = 0
isGUIScaled = true
updateScale()
}

private fun unSetGUIScale() {
if (!isGUIScaled) return
Minecraft.getMinecraft().gameSettings.guiScale = guiSetting
isGUIScaled = false
}

@SubscribeEvent
fun onSlotClick(event: GuiContainerEvent.SlotClickEvent) {
if (!LorenzUtils.inSkyBlock) return
if (!config.quickRestart) return
if (!isMenuGui(InventoryUtils.openInventoryName())) return
if (event.slot?.slotNumber != closeButtonSlot) return
if (openTime.passedSince() > 2.seconds) return
event.container.inventory.indexOfFirst {
songSelectedPattern.anyMatches(it.getLore())
}.takeIf { it != -1 }?.let {
event.isCanceled = true
Minecraft.getMinecraft().playerController.windowClick(
event.container.windowId,
it,
event.clickedButton,
event.clickType,
Minecraft.getMinecraft().thePlayer
)
}
}

@SubscribeEvent
fun onRenderItemTip(event: RenderItemTipEvent) {
if (!LorenzUtils.inSkyBlock) return
if (!config.showNumbers) return
if (!isHarpGui()) return
if (!isHarpGui(InventoryUtils.openInventoryName())) return
if (Item.getIdFromItem(event.stack.item) != 159) return // Stained hardened clay item id = 159

// Example: §9| §7Click! will select the 9
val index = buttonColors.indexOfFirst { it == event.stack.displayName[1] }
if (index == -1) return // this should never happen unless there's an update

val keyCode = getKey(index) ?: return
event.stackTip = KeyboardManager.getKeyName(keyCode)
event.stackTip = KeyboardManager.getKeyName(keyCode).take(3)
}

@SubscribeEvent
Expand Down
1 change: 1 addition & 0 deletions src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ object StringUtils {
fun String.convertToFormatted(): String = this.replace("&&", "§")

fun Pattern.matches(string: String?) = string?.let { matcher(it).matches() } ?: false
fun Pattern.anyMatches(list: List<String>?) = list?.any { this.matches(it) } ?: false

fun Pattern.find(string: String?) = string?.let { matcher(it).find() } ?: false

Expand Down
Loading