aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
authorhannibal2 <24389977+hannibal002@users.noreply.github.com>2023-06-12 12:49:20 +0200
committerGitHub <noreply@github.com>2023-06-12 12:49:20 +0200
commit56c5f9fc485731f2a33a2b61fa8b7d81193c207c (patch)
tree501b76594f2afa2057b1e45e402aa4c7f109dd12 /src/main
parentf7b36cc696105948a31a871f493a515c3be658cd (diff)
downloadskyhanni-56c5f9fc485731f2a33a2b61fa8b7d81193c207c.tar.gz
skyhanni-56c5f9fc485731f2a33a2b61fa8b7d81193c207c.tar.bz2
skyhanni-56c5f9fc485731f2a33a2b61fa8b7d81193c207c.zip
Quick Mod Menu Switch (#232)
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt1
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/DevData.java16
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/Misc.java26
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/QuickModMenuSwitch.kt192
-rw-r--r--src/main/java/at/hannibal2/skyhanni/test/SkyHanniTestCommand.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/jsonobjects/ModsJson.java25
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt38
7 files changed, 285 insertions, 15 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt
index ba8bb974d..9de04e760 100644
--- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt
+++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt
@@ -296,6 +296,7 @@ class SkyHanniMod {
loadModule(SlayerItemsOnGround())
loadModule(DetectBrokenHyperion())
loadModule(RestorePieceOfWizardPortalLore())
+ loadModule(QuickModMenuSwitch)
init()
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/DevData.java b/src/main/java/at/hannibal2/skyhanni/config/features/DevData.java
index d94d3a39a..85120f929 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/DevData.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/DevData.java
@@ -32,6 +32,22 @@ public class DevData {
public boolean commandLogs = false;
@Expose
+ @ConfigOption(
+ name = "Mod Menu Log",
+ desc = "Enables debug messages when the currently opened gui changes, with the path to the gui class. " +
+ "Useful for adding more mods to quick mod menu switch."
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 0)
+ public boolean modMenuLog = false;
+
+ @Expose
+ @ConfigOption(name = "Show internal name", desc = "Show internal names in item lores.")
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 0)
+ public boolean showInternalName = false;
+
+ @Expose
public Position debugPos = new Position(10, 10, false, true);
@Expose
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/Misc.java b/src/main/java/at/hannibal2/skyhanni/config/features/Misc.java
index 97a885cdc..64f14947a 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/Misc.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/Misc.java
@@ -446,6 +446,32 @@ public class Misc {
public boolean replaceLore = true;
}
+ @ConfigOption(name = "Quick Mod Menu Switch", desc = "")
+ @Accordion
+ @Expose
+ public QuickModMenuSwitch quickModMenuSwitch = new QuickModMenuSwitch();
+
+ public static class QuickModMenuSwitch {
+
+ @Expose
+ @ConfigOption(name = "Enabled", desc = "Adding a mod list, allowing to quickly switch between different mod menus")
+ @ConfigEditorBoolean
+ public boolean enabled = false;
+
+ @Expose
+ @ConfigOption(name = "Inside Escape Menu", desc = "Show the mod list while inside the Escape menu")
+ @ConfigEditorBoolean
+ public boolean insideEscapeMenu = true;
+
+ @Expose
+ @ConfigOption(name = "Inside Inventory", desc = "Show the mod list while inside the player inventory (no chest inventory)")
+ @ConfigEditorBoolean
+ public boolean insidePlayerInventory = false;
+
+ @Expose
+ public Position pos = new Position(-178, 143, false, true);
+ }
+
@Expose
@ConfigOption(name = "Exp Bottles", desc = "Hides all the experience orbs lying on the ground.")
@ConfigEditorBoolean
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/QuickModMenuSwitch.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/QuickModMenuSwitch.kt
new file mode 100644
index 000000000..a33cda9d1
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/QuickModMenuSwitch.kt
@@ -0,0 +1,192 @@
+package at.hannibal2.skyhanni.features.misc
+
+import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.events.RepositoryReloadEvent
+import at.hannibal2.skyhanni.test.command.CopyErrorCommand
+import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.RenderUtils.renderStringsAndItems
+import at.hannibal2.skyhanni.utils.jsonobjects.ModsJson
+import at.hannibal2.skyhanni.utils.renderables.Renderable
+import net.minecraft.client.Minecraft
+import net.minecraft.client.renderer.GlStateManager
+import net.minecraftforge.client.ClientCommandHandler
+import net.minecraftforge.client.event.GuiScreenEvent
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import net.minecraftforge.fml.common.gameevent.TickEvent
+
+object QuickModMenuSwitch {
+ private val config get() = SkyHanniMod.feature.misc.quickModMenuSwitch
+ private var display = listOf<List<Any>>()
+ private var tick = 0
+ private var latestGuiPath = ""
+
+ private var mods: List<Mod>? = null
+
+ private var currentlyOpeningMod = ""
+ private var lastGuiOpen = 0L
+
+ @SubscribeEvent
+ fun onRepoReload(event: RepositoryReloadEvent) {
+ val modsJar = event.getConstant<ModsJson>("ModGuiSwitcher") ?: return
+ mods = buildList {
+ out@ for ((name, mod) in modsJar.mods) {
+ for (path in mod.guiPath) {
+ try {
+ Class.forName(path)
+ add(Mod(name, mod.description, mod.command, mod.guiPath))
+ continue@out
+ } catch (ignored_: Exception) {
+ }
+ }
+ }
+ }
+ }
+
+ @SubscribeEvent
+ fun onTick(event: TickEvent.ClientTickEvent) {
+ if (!isEnabled()) return
+
+ if (tick++ % 5 == 0) {
+ update()
+ }
+ }
+
+ class Mod(val name: String, val description: List<String>, val command: String, val guiPath: List<String>) {
+
+ fun isInGui() = guiPath.any { latestGuiPath.startsWith(it) }
+ }
+
+ private fun update() {
+ var openGui = Minecraft.getMinecraft().currentScreen?.javaClass?.name ?: "none"
+ openGui = handleAbstractGuis(openGui)
+ if (latestGuiPath != openGui) {
+ latestGuiPath = openGui
+
+ if (SkyHanniMod.feature.dev.modMenuLog) {
+ LorenzUtils.debug("Open GUI: $latestGuiPath")
+ }
+ }
+ val mods = mods ?: return
+
+ display = if (!shouldShow(mods)) {
+ emptyList()
+ } else {
+ renderDisplay(mods)
+ }
+ }
+
+ private fun shouldShow(mods: List<Mod>): Boolean {
+ if (config.insideEscapeMenu && latestGuiPath == "net.minecraft.client.gui.GuiIngameMenu") return true
+ if (config.insidePlayerInventory && latestGuiPath == "net.minecraft.client.gui.inventory.GuiInventory") return true
+
+ return mods.any { it.isInGui() }
+ }
+
+ private fun handleAbstractGuis(openGui: String): String {
+ if (openGui == "gg.essential.vigilance.gui.SettingsGui") {
+ val clazz = Class.forName("gg.essential.vigilance.gui.SettingsGui")
+ val titleBarDelegate = clazz.getDeclaredField("titleBar\$delegate").also { it.isAccessible = true }
+ .get(Minecraft.getMinecraft().currentScreen)
+ val titleBar =
+ titleBarDelegate.javaClass.declaredFields[0].also { it.isAccessible = true }.get(titleBarDelegate)
+ val gui = titleBar.javaClass.getDeclaredField("gui").also { it.isAccessible = true }.get(titleBar)
+ val config = gui.javaClass.getDeclaredField("config").also { it.isAccessible = true }.get(gui)
+
+ return config.javaClass.name
+ }
+ if (openGui == "cc.polyfrost.oneconfig.gui.OneConfigGui") {
+ /** TODO support different oneconfig mods:
+ * Partly Sane Skies
+ * Dankers SkyBlock Mod
+ * Dulkir
+ */
+ }
+
+ return openGui
+ }
+
+ private fun renderDisplay(mods: List<Mod>) = buildList {
+ for (mod in mods) {
+ val currentlyOpen = mod.isInGui()
+ val nameFormat = if (currentlyOpen) "§c" else ""
+ var opening = mod.name == currentlyOpeningMod
+ if (currentlyOpen && opening) {
+ currentlyOpeningMod = ""
+ opening = false
+ }
+ val nameSuffix = if (opening) " §7(opening...)" else ""
+ val renderable = Renderable.link(
+ Renderable.string(nameFormat + mod.name),
+ bypassChecks = true,
+ onClick = { open(mod) },
+ condition = { System.currentTimeMillis() > lastGuiOpen + 250 }
+ )
+ add(listOf(renderable, nameSuffix))
+ }
+ }
+
+ private fun open(mod: Mod) {
+ lastGuiOpen = System.currentTimeMillis()
+ currentlyOpeningMod = mod.name
+ update()
+ try {
+ when (mod.command) {
+ "patcher" -> {
+ println("try opening patcher")
+ // GuiUtil.open(Objects.requireNonNull(Patcher.instance.getPatcherConfig().gui()))
+ val patcher = Class.forName("club.sk1er.patcher.Patcher")
+ val instance = patcher.getDeclaredField("instance").get(null)
+ val config = instance.javaClass.getDeclaredMethod("getPatcherConfig").invoke(instance)
+ val gui = Class.forName("gg.essential.vigilance.Vigilant").getDeclaredMethod("gui").invoke(config)
+ val guiUtils = Class.forName("gg.essential.api.utils.GuiUtil")
+ for (method in guiUtils.declaredMethods) {
+ try {
+ method.invoke(null, gui)
+ println("opened patcher")
+ return
+ } catch (_: Exception) {
+ }
+ }
+ LorenzUtils.chat("§c[SkyHanni] Error trying to open the gui for mod " + mod.name + "!")
+ }
+
+ "hytil" -> {
+ println("try opening hytil")
+ // HytilsReborn.INSTANCE.getConfig().openGui()
+ val hytilsReborn = Class.forName("cc.woverflow.hytils.HytilsReborn")
+ val instance = hytilsReborn.getDeclaredField("INSTANCE").get(null)
+ val config = instance.javaClass.getDeclaredMethod("getConfig").invoke(instance)
+ val gui = Class.forName("gg.essential.vigilance.Vigilant").getDeclaredMethod("gui").invoke(config)
+ val guiUtils = Class.forName("gg.essential.api.utils.GuiUtil")
+ for (method in guiUtils.declaredMethods) {
+ try {
+ method.invoke(null, gui)
+ println("opened hytil")
+ return
+ } catch (_: Exception) {
+ }
+ }
+ LorenzUtils.chat("§c[SkyHanni] Error trying to open the gui for mod " + mod.name + "!")
+ }
+
+ else -> {
+ val thePlayer = Minecraft.getMinecraft().thePlayer
+ ClientCommandHandler.instance.executeCommand(thePlayer, "/${mod.command}")
+ }
+ }
+ } catch (e: Exception) {
+ CopyErrorCommand.logError(e, "Error trying to open the gui for mod " + mod.name)
+ }
+ }
+
+ @SubscribeEvent
+ fun onRenderOverlay(event: GuiScreenEvent.DrawScreenEvent.Post) {
+ if (!isEnabled()) return
+
+ GlStateManager.pushMatrix()
+ config.pos.renderStringsAndItems(display, posLabel = "Quick Mod Menu Switch")
+ GlStateManager.popMatrix()
+ }
+
+ fun isEnabled() = LorenzUtils.inSkyBlock && config.enabled
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/test/SkyHanniTestCommand.kt b/src/main/java/at/hannibal2/skyhanni/test/SkyHanniTestCommand.kt
index bb03898d6..d3a7e982f 100644
--- a/src/main/java/at/hannibal2/skyhanni/test/SkyHanniTestCommand.kt
+++ b/src/main/java/at/hannibal2/skyhanni/test/SkyHanniTestCommand.kt
@@ -163,7 +163,7 @@ class SkyHanniTestCommand {
@SubscribeEvent
fun onItemTooltipLow(event: ItemTooltipEvent) {
- if (!SkyHanniMod.feature.dev.debugEnabled) return
+ if (!SkyHanniMod.feature.dev.showInternalName) return
val itemStack = event.itemStack
if (itemStack != null) {
val internalName = itemStack.getInternalName()
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/jsonobjects/ModsJson.java b/src/main/java/at/hannibal2/skyhanni/utils/jsonobjects/ModsJson.java
new file mode 100644
index 000000000..d765f3e02
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/utils/jsonobjects/ModsJson.java
@@ -0,0 +1,25 @@
+package at.hannibal2.skyhanni.utils.jsonobjects;
+
+import com.google.gson.annotations.Expose;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class ModsJson {
+
+ @Expose
+ public Map<String, Mod> mods = new HashMap<>();
+
+ public class Mod {
+ @Expose
+ public List<String> description = new ArrayList<>();
+
+ @Expose
+ public String command = "";
+
+ @Expose
+ public List<String> guiPath = new ArrayList<>();
+ }
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt b/src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt
index 5047c4744..acd1085ba 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt
@@ -40,19 +40,19 @@ interface Renderable {
else -> null
}
- fun link(text: String, onClick: () -> Unit): Renderable = link(string(text), onClick) { true }
- fun optionalLink(text: String, onClick: () -> Unit, condition: () -> Boolean = { true }): Renderable =
- link(string(text), onClick, condition)
+ fun link(text: String, bypassChecks: Boolean = false, onClick: () -> Unit): Renderable = link(string(text), onClick, bypassChecks = bypassChecks) { true }
+ fun optionalLink(text: String, onClick: () -> Unit, bypassChecks: Boolean = false, condition: () -> Boolean = { true }): Renderable =
+ link(string(text), onClick, bypassChecks, condition)
- fun link(renderable: Renderable, onClick: () -> Unit, condition: () -> Boolean = { true }): Renderable {
- return clickable(hoverable(underlined(renderable), renderable, condition), onClick, 0, condition)
+ fun link(renderable: Renderable, onClick: () -> Unit, bypassChecks: Boolean = false, condition: () -> Boolean = { true }): Renderable {
+ return clickable(hoverable(underlined(renderable), renderable, bypassChecks, condition = condition), onClick, 0, bypassChecks, condition)
}
- fun clickAndHover(text: String, tips: List<String>, onClick: () -> Unit): Renderable {
- return clickable(hoverTips(text, tips), onClick)
+ fun clickAndHover(text: String, tips: List<String>, bypassChecks: Boolean = false, onClick: () -> Unit): Renderable {
+ return clickable(hoverTips(text, tips, bypassChecks = bypassChecks), onClick, bypassChecks = bypassChecks)
}
- fun clickable(render: Renderable, onClick: () -> Unit, button: Int = 0, condition: () -> Boolean = { true }) =
+ fun clickable(render: Renderable, onClick: () -> Unit, button: Int = 0, bypassChecks: Boolean = false, condition: () -> Boolean = { true }) =
object : Renderable {
override val width: Int
get() = render.width
@@ -63,7 +63,7 @@ interface Renderable {
override fun render(posX: Int, posY: Int) {
val isDown = Mouse.isButtonDown(button)
if (isDown > wasDown && isHovered(posX, posY)) {
- if (condition() && shouldAllowLink(true)) {
+ if (condition() && shouldAllowLink(true, bypassChecks)) {
onClick()
}
}
@@ -72,7 +72,7 @@ interface Renderable {
}
}
- fun hoverTips(text: String, tips: List<String>, condition: () -> Boolean = { true }): Renderable {
+ fun hoverTips(text: String, tips: List<String>, bypassChecks: Boolean = false, condition: () -> Boolean = { true }): Renderable {
val render = string(text)
return object : Renderable {
override val width: Int
@@ -82,7 +82,7 @@ interface Renderable {
override fun render(posX: Int, posY: Int) {
render.render(posX, posY)
if (isHovered(posX, posY)) {
- if (condition() && shouldAllowLink(true)) {
+ if (condition() && shouldAllowLink(true, bypassChecks)) {
renderToolTips(posX, posY, tips)
}
}
@@ -91,6 +91,11 @@ interface Renderable {
}
private fun renderToolTips(posX: Int, posY: Int, tips: List<String>, border: Int = 1) {
+ GlStateManager.pushMatrix()
+// GlStateManager.translate(0f, 0f, 2f)
+// GuiRenderUtils.drawTooltip(tips, posX, posY, 0)
+// GlStateManager.translate(0f, 0f, -2f)
+
val x = Utils.getMouseX() - posX + 10
val startY = Utils.getMouseY() - posY - 10
var maxX = 0
@@ -121,10 +126,15 @@ interface Renderable {
LorenzColor.DARK_GRAY.toColor().rgb
)
GlStateManager.translate(0f, 0f, -1f)
+
+ GlStateManager.popMatrix()
}
- private fun shouldAllowLink(debug: Boolean = false): Boolean {
+ private fun shouldAllowLink(debug: Boolean = false, bypassChecks: Boolean): Boolean {
val isGuiScreen = Minecraft.getMinecraft().currentScreen != null
+ if (bypassChecks) {
+ return isGuiScreen
+ }
val isGuiPositionEditor = Minecraft.getMinecraft().currentScreen !is GuiPositionEditor
val isNotInSignAndOnSlot = if (Minecraft.getMinecraft().currentScreen !is GuiEditSign) {
ToolTipData.lastSlot == null
@@ -161,14 +171,14 @@ interface Renderable {
}
}
- fun hoverable(hovered: Renderable, unhovered: Renderable, condition: () -> Boolean = { true }) =
+ fun hoverable(hovered: Renderable, unhovered: Renderable, bypassChecks: Boolean = false, condition: () -> Boolean = { true }) =
object : Renderable {
override val width: Int
get() = max(hovered.width, unhovered.width)
override val height = 10
override fun render(posX: Int, posY: Int) {
- if (isHovered(posX, posY) && condition() && shouldAllowLink())
+ if (isHovered(posX, posY) && condition() && shouldAllowLink(true, bypassChecks))
hovered.render(posX, posY)
else
unhovered.render(posX, posY)