From 56c5f9fc485731f2a33a2b61fa8b7d81193c207c Mon Sep 17 00:00:00 2001 From: hannibal2 <24389977+hannibal002@users.noreply.github.com> Date: Mon, 12 Jun 2023 12:49:20 +0200 Subject: Quick Mod Menu Switch (#232) --- .../skyhanni/features/misc/QuickModMenuSwitch.kt | 192 +++++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 src/main/java/at/hannibal2/skyhanni/features/misc/QuickModMenuSwitch.kt (limited to 'src/main/java/at/hannibal2/skyhanni/features') 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>() + private var tick = 0 + private var latestGuiPath = "" + + private var mods: List? = null + + private var currentlyOpeningMod = "" + private var lastGuiOpen = 0L + + @SubscribeEvent + fun onRepoReload(event: RepositoryReloadEvent) { + val modsJar = event.getConstant("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, val command: String, val guiPath: List) { + + 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): 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) = 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 +} -- cgit