aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/io
diff options
context:
space:
mode:
authorLinnea Gräf <nea@nea.moe>2024-04-10 12:37:49 +0200
committerGitHub <noreply@github.com>2024-04-10 12:37:49 +0200
commitc09c456d72ef95aeddf9c3b93639af8c64552fd1 (patch)
tree319d83484ffd6b92f83b65843d0fcdae680adc2a /src/main/kotlin/io
parentb04290ede8420e8ef9b56f2c8a9252224b8f1d2d (diff)
downloadNotEnoughUpdates-c09c456d72ef95aeddf9c3b93639af8c64552fd1.tar.gz
NotEnoughUpdates-c09c456d72ef95aeddf9c3b93639af8c64552fd1.tar.bz2
NotEnoughUpdates-c09c456d72ef95aeddf9c3b93639af8c64552fd1.zip
Add tab list tutorial (#1014)
Co-authored-by: Lulonaut <lulonaut@lulonaut.tech>
Diffstat (limited to 'src/main/kotlin/io')
-rw-r--r--src/main/kotlin/io/github/moulberry/notenoughupdates/commands/dev/NEUStatsCommand.kt7
-rw-r--r--src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/tablisttutorial/TablistAPI.kt146
-rw-r--r--src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/tablisttutorial/TablistTaskQueue.kt62
-rw-r--r--src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/tablisttutorial/TablistTutorial.kt268
-rw-r--r--src/main/kotlin/io/github/moulberry/notenoughupdates/util/StateManagerUtils.kt36
-rw-r--r--src/main/kotlin/io/github/moulberry/notenoughupdates/util/TabSkillInfoParser.kt16
6 files changed, 529 insertions, 6 deletions
diff --git a/src/main/kotlin/io/github/moulberry/notenoughupdates/commands/dev/NEUStatsCommand.kt b/src/main/kotlin/io/github/moulberry/notenoughupdates/commands/dev/NEUStatsCommand.kt
index d5b91b9d..9e9cca14 100644
--- a/src/main/kotlin/io/github/moulberry/notenoughupdates/commands/dev/NEUStatsCommand.kt
+++ b/src/main/kotlin/io/github/moulberry/notenoughupdates/commands/dev/NEUStatsCommand.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 NotEnoughUpdates contributors
+ * Copyright (C) 2023-2024 NotEnoughUpdates contributors
*
* This file is part of NotEnoughUpdates.
*
@@ -27,6 +27,7 @@ import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe
import io.github.moulberry.notenoughupdates.events.RegisterBrigadierCommandEvent
import io.github.moulberry.notenoughupdates.util.DiscordMarkdownBuilder
import io.github.moulberry.notenoughupdates.util.SBInfo
+import io.github.moulberry.notenoughupdates.util.TabListUtils
import io.github.moulberry.notenoughupdates.util.brigadier.reply
import io.github.moulberry.notenoughupdates.util.brigadier.thenExecute
import io.github.moulberry.notenoughupdates.util.brigadier.thenLiteralExecute
@@ -61,6 +62,9 @@ class NEUStatsCommand {
.toString()
)
}.withHelp("Copy the mod list to your clipboard")
+ thenLiteralExecute("tablist") {
+ clipboardAndSendMessage("```\n${TabListUtils.getTabList()}\n```")
+ }.withHelp("Copy the current tab list to your clipboard")
thenLiteralExecute("repo") {
clipboardAndSendMessage(
DiscordMarkdownBuilder()
@@ -173,7 +177,6 @@ class NEUStatsCommand {
Loader.instance().indexedModList[NotEnoughUpdates.MODID]!!.displayVersion
)
builder.append("SB Profile", SBInfo.getInstance().currentProfile)
- builder.append("Has Advanced Tab", if (SBInfo.getInstance().hasNewTab) "TRUE" else "FALSE")
.also(::appendRepoStats)
}
diff --git a/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/tablisttutorial/TablistAPI.kt b/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/tablisttutorial/TablistAPI.kt
new file mode 100644
index 00000000..5c493108
--- /dev/null
+++ b/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/tablisttutorial/TablistAPI.kt
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2024 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.miscfeatures.tablisttutorial
+
+import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe
+import io.github.moulberry.notenoughupdates.util.TabListUtils
+import io.github.moulberry.notenoughupdates.util.stripControlCodes
+import net.minecraft.client.Minecraft
+import net.minecraftforge.event.entity.EntityJoinWorldEvent
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import java.util.*
+
+@NEUAutoSubscribe
+object TablistAPI {
+
+ private var lastWorldSwitch = 0L
+ var lastWidgetEnabled: WidgetNames? = null
+
+ @SubscribeEvent
+ fun onWorldSwitch(event: EntityJoinWorldEvent) {
+ if (event.entity == Minecraft.getMinecraft().thePlayer) {
+ lastWorldSwitch = System.nanoTime()
+ }
+ }
+
+ @JvmStatic
+ fun getWidgetLinesInRegion(
+ widget: TablistTutorial.TabListWidget,
+ addToQueue: Boolean,
+ showNotification: Boolean
+ ): List<String> {
+ val regex = widget.widgetName.regex ?: Regex.fromLiteral("${widget.widgetName}:")
+ val list = mutableListOf<String>()
+ // If not a single reset is present, the tab list hasn't been initialized yet
+ var sawReset = false
+
+ for (entry in TabListUtils.getTabList()) {
+ if (entry.contains("§r")) {
+ sawReset = true
+ }
+
+ if (list.isNotEmpty()) {
+ // New tab section, or empty line indicate a new section
+ if (entry == "§r §r§3§lInfo§r" || entry == "§r") {
+ break
+ }
+ list.add(entry)
+ } else if (entry.stripControlCodes().matches(regex)) {
+ list.add(entry)
+ }
+ }
+ if (addToQueue &&
+ list.isEmpty() &&
+ sawReset &&
+ (System.nanoTime() - lastWorldSwitch > 10_000_000L) &&
+ widget.widgetName != lastWidgetEnabled
+ ) {
+ TablistTaskQueue.addToQueue(widget, showNotification)
+ }
+ return list
+ }
+
+ /**
+ * Attempt to get the lines for this widget.
+ * Otherwise, add the widget to the tablist queue and show a notification to the user
+ */
+ @JvmStatic
+ fun getWidgetLines(widgetName: WidgetNames): List<String> {
+ return getWidgetLinesInRegion(
+ TablistTutorial.TabListWidget("CURRENT_REGION", widgetName),
+ addToQueue = true,
+ showNotification = true
+ )
+ }
+
+ /**
+ * Attempt to get the lines for this widget.
+ * Otherwise, add the widget to the tablist queue without showing a notification to the user.
+ *
+ * Consider using this if there is a more optimal way of informing the user.
+ */
+ @JvmStatic
+ fun getWidgetLinesWithoutNotification(widgetName: WidgetNames): List<String> {
+ return getWidgetLinesInRegion(
+ TablistTutorial.TabListWidget("CURRENT_REGION", widgetName),
+ addToQueue = true,
+ showNotification = false
+ )
+ }
+
+ /**
+ * Attempt to get the lines for this widget.
+ * Otherwise, do nothing.
+ *
+ * Consider using this if the result is not important, but simply a nice to have.
+ */
+ @JvmStatic
+ fun getOptionalWidgetLines(widgetName: WidgetNames): List<String> {
+ return getWidgetLinesInRegion(
+ TablistTutorial.TabListWidget("CURRENT_REGION", widgetName),
+ addToQueue = false,
+ showNotification = false
+ )
+ }
+
+ enum class WidgetNames(val regex: Regex?) {
+ COMMISSIONS(null),
+ SKILLS(null),
+ TRAPPER(null),
+ FORGE(Regex.fromLiteral("Forges:")),
+ POWDER(Regex.fromLiteral("Powders:")),
+ PROFILE(Regex("Profile: ([A-Za-z]+)( .*)?"))
+ ;
+
+ override fun toString(): String {
+ return this.name.lowercase().split(" ").joinToString(" ") { str ->
+ str.replaceFirstChar {
+ if (it.isLowerCase()) {
+ it.titlecase(
+ Locale.ROOT
+ )
+ } else {
+ it.toString()
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/tablisttutorial/TablistTaskQueue.kt b/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/tablisttutorial/TablistTaskQueue.kt
new file mode 100644
index 00000000..8cbd27a0
--- /dev/null
+++ b/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/tablisttutorial/TablistTaskQueue.kt
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2024 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.miscfeatures.tablisttutorial
+
+import io.github.moulberry.notenoughupdates.util.NotificationHandler
+
+object TablistTaskQueue {
+ private val queue = mutableListOf<TablistTutorial.TabListWidget>()
+
+ fun addToQueue(task: TablistTutorial.TabListWidget, showNotification: Boolean) {
+ if (showNotification && !queueContainsElements()) {
+ NotificationHandler.displayNotification(
+ listOf(
+ "§l§4Widget missing",
+ "§cOne or more tab list widgets, which are required for NEU to function properly, are missing",
+ "§cOpen the Tablist Widgets settings using",
+ "§b/tab",
+ "§cto get some assistance in fixing this problem."
+ ),
+ false
+ )
+ }
+ if (task !in queue) {
+ // see todo in MiningOverlay.java:377
+// Utils.addChatMessage("Adding $task")
+ queue.add(task)
+ }
+ }
+
+ fun removeFromQueue(task: TablistTutorial.TabListWidget) {
+ queue.remove(task)
+ }
+
+ fun queueContainsElements(): Boolean {
+ return queue.isNotEmpty()
+ }
+
+ fun getNextQueueItem(): TablistTutorial.TabListWidget? {
+ return if (!queueContainsElements()) {
+ null
+ } else {
+ queue.removeLast()
+ }
+ }
+}
diff --git a/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/tablisttutorial/TablistTutorial.kt b/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/tablisttutorial/TablistTutorial.kt
new file mode 100644
index 00000000..e7299e12
--- /dev/null
+++ b/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/tablisttutorial/TablistTutorial.kt
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 2024 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.miscfeatures.tablisttutorial
+
+import com.mojang.brigadier.arguments.StringArgumentType.string
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates
+import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe
+import io.github.moulberry.notenoughupdates.core.util.StringUtils
+import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils
+import io.github.moulberry.notenoughupdates.events.RegisterBrigadierCommandEvent
+import io.github.moulberry.notenoughupdates.mixins.AccessorGlStateManager
+import io.github.moulberry.notenoughupdates.mixins.AccessorGuiContainer
+import io.github.moulberry.notenoughupdates.util.ItemUtils
+import io.github.moulberry.notenoughupdates.util.StateManagerUtils
+import io.github.moulberry.notenoughupdates.util.brigadier.thenArgument
+import io.github.moulberry.notenoughupdates.util.brigadier.thenExecute
+import io.github.moulberry.notenoughupdates.util.brigadier.withHelp
+import io.github.moulberry.notenoughupdates.util.stripControlCodes
+import net.minecraft.client.Minecraft
+import net.minecraft.client.gui.inventory.GuiChest
+import net.minecraft.client.gui.inventory.GuiContainer
+import net.minecraft.client.renderer.GlStateManager
+import net.minecraft.inventory.ContainerChest
+import net.minecraft.inventory.Slot
+import net.minecraft.util.ResourceLocation
+import net.minecraftforge.client.event.GuiScreenEvent
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+
+@NEUAutoSubscribe
+object TablistTutorial {
+ data class TabListWidget(
+ var regionName: String,
+ val widgetName: TablistAPI.WidgetNames,
+ )
+
+ private object Arrow {
+ val imageLocation = ResourceLocation("notenoughupdates:textures/gui/tablisttutorial/arrow.png")
+ val tipXOffset = 16
+ val tipYOffset = 64
+ val labelXOffset = 58
+ val labelYOffset = 19
+ val textureSize = 64
+ val textScale = 2f
+
+ fun drawBigRedArrow(x: Int, y: Int, label: String) {
+ val imgX = x - Arrow.tipXOffset
+ val imgY = y - Arrow.tipYOffset
+ val textX = imgX + Arrow.labelXOffset
+ val textY = imgY + Arrow.labelYOffset
+
+ GlStateManager.pushMatrix()
+ GlStateManager.translate(0f, 0f, 300f)
+ GlStateManager.color(1f, 1f, 1f, 1f)
+ Minecraft.getMinecraft().textureManager.bindTexture(imageLocation)
+ RenderUtils.drawTexturedRect(imgX.toFloat(), imgY.toFloat(), textureSize.toFloat(), textureSize.toFloat())
+ GlStateManager.translate(textX.toFloat(), textY.toFloat(), 0F)
+ GlStateManager.scale(textScale, textScale, 1F)
+ val fr = Minecraft.getMinecraft().fontRendererObj
+ fr.drawString(label, 0, -fr.FONT_HEIGHT / 2, -1)
+ GlStateManager.popMatrix()
+ }
+
+ fun drawBigRedArrow(gui: GuiContainer, slot: Slot, label: String) {
+ gui as AccessorGuiContainer
+ drawBigRedArrow(gui.guiLeft + slot.xDisplayPosition + 9, gui.guiTop + slot.yDisplayPosition, label)
+ }
+ }
+
+ var activeTask: TabListWidget? = null
+
+ @SubscribeEvent
+ fun onGuiPostRender(event: GuiScreenEvent.DrawScreenEvent.Post) {
+ if (activeTask == null) {
+ activeTask = TablistTaskQueue.getNextQueueItem()
+ }
+ val task = activeTask ?: return
+
+ val gui = event.gui as? GuiChest ?: return
+ val chestInventory = gui.inventorySlots as ContainerChest
+
+ val name = chestInventory.lowerChestInventory.displayName.unformattedText
+
+ StateManagerUtils.withSavedState(AccessorGlStateManager.getLightingState()) {
+ GlStateManager.disableLighting()
+ if (name == "Tablist Widgets") {
+ drawSelectAreaArrow(gui, chestInventory, task)
+ }
+ val regionName = getRegionName(name)
+
+ // Assume the user is capable of clicking on the current region
+ if (task.regionName == "CURRENT_REGION") {
+ activeTask!!.regionName = regionName ?: return
+ }
+ if (regionName == task.regionName) {
+ drawEnableEffect(gui, chestInventory, task)
+ } else if (regionName != null) {
+ val backSlot = chestInventory.inventorySlots.getOrNull(5 * 9 + 3)
+ if (backSlot != null) {
+ Arrow.drawBigRedArrow(gui, backSlot, "Go back!")
+ }
+ }
+ }
+ }
+
+ data class WidgetStatus(
+ val widgetName: String,
+ val enabled: Boolean,
+ val slot: Slot,
+ )
+
+ fun findWidgets(chestInventory: ContainerChest): List<WidgetStatus> {
+ return chestInventory.inventorySlots.mapNotNull {
+ val name = ItemUtils.getDisplayName(it.stack)?.let(StringUtils::cleanColour) ?: return@mapNotNull null
+ if (!name.endsWith(" Widget")) {
+ return@mapNotNull null
+ }
+ val disabled = name.startsWith("✖")
+ val enabled = name.startsWith("✔")
+ if (!(enabled || disabled)) {
+ return@mapNotNull null
+ }
+ return@mapNotNull WidgetStatus(name.drop(1).removeSuffix(" Widget").trim(), enabled, it)
+ }
+ }
+
+ private fun drawEnableEffect(gui: GuiChest, chestInventory: ContainerChest, task: TabListWidget) {
+ val widgets = findWidgets(chestInventory)
+ val widget = widgets.find { it.widgetName == task.widgetName.toString() }
+ if (widget == null) return
+ if (widget.enabled) {
+ drawPriorityClick(gui, chestInventory, widget)
+ return
+ }
+ Arrow.drawBigRedArrow(gui, widget.slot, "Click here!")
+ }
+
+ /*{
+ id: "minecraft:skull",
+ Count: 1b,
+ tag: {
+ overrideMeta: 1b,
+ HideFlags: 254,
+ SkullOwner: {
+ Id: "474a0574-24e5-4949-bf61-f8d06120815e",
+ hypixelPopulated: 1b,
+ Properties: {
+ textures: [{
+ Value: "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzljODg4MWU0MjkxNWE5ZDI5YmI2MWExNmZiMjZkMDU5OTEzMjA0ZDI2NWRmNWI0MzliM2Q3OTJhY2Q1NiJ9fX0="
+ }]
+ },
+ Name: "§474a0574-24e5-4949-bf61-f8d06120815e"
+ },
+ display: {
+ Lore: ["§7§3⬛ §3§lInfo", "§7§8⬛§f§b§lArea: §7Private Island", "§7§8⬛§f Server: §8mini4C", "§7§8⬛§f Gems: §a0", "§7§8⬛§f Crystals: §d3", "§7§8⬛§f", "§7§8⬛§f§b§lMinions§f: 27§7/§r28", "§7§8⬛§f 7x Ice VII §7[§aACTIVE§7]", "§7§8⬛§f 1x Acacia XI §7[§aACTIVE§7]", "§7§8⬛§f 1x Cave Spider XI §7[§aACTIVE§7]", "§7§8⬛§f 1x Cow XI §7[§aACTIVE§7]", "§7§8⬛§f 1x Creeper X §7[§aACTIVE§7]", "§7§8⬛§f 1x Fishing X §7[§aACTIVE§7]", "§7§8⬛§f 1x Ice XI §7[§aACTIVE§7]", "§7§8⬛§f 1x Iron XI §7[§aACTIVE§7]", "§7§8⬛§f 1x Jungle XI §7[§aACTIVE§7]", "§7§8⬛§f 1x Melon XI §7[§aACTIVE§7]", "§7§8⬛§f 1x Obsidian XI §7[§aACTIVE§7]", "§7§8⬛§f 1x Pig XI §7[§aACTIVE§7]", "§7§8⬛§f ... and 10 more."],
+ Name: "§aPrivate Island Widgets Preview"
+ },
+ AttributeModifiers: []
+ },
+ Damage: 3s
+ }*/
+ fun drawPriorityClick(gui: GuiChest, chestInventory: ContainerChest, widget: WidgetStatus) {
+ val prioritySlot = chestInventory.inventorySlots.getOrNull(13) ?: return
+ val leftSide = chestInventory.inventory.getOrNull(3).let(ItemUtils::getLore)
+ val middle = chestInventory.inventory.getOrNull(4).let(ItemUtils::getLore)
+ val rightSide = chestInventory.inventory.getOrNull(5).let(ItemUtils::getLore)
+
+ val priorityList = chestInventory.inventory.getOrNull(13).let(ItemUtils::getLore)
+ val allTabListEntries = leftSide + middle + rightSide
+ val regex = activeTask?.widgetName?.regex ?: Regex.fromLiteral("${widget.widgetName}:")
+ if (allTabListEntries.any { it.replace("⬛", "").stripControlCodes().matches(regex) }) {
+ TablistAPI.lastWidgetEnabled = activeTask!!.widgetName
+ activeTask = TablistTaskQueue.getNextQueueItem()
+// Utils.addChatMessage("Success! You enabled ${widget.widgetName}!")
+ return
+ }
+ val editingIndex = priorityList.indexOfFirst { it.contains("EDITING") }
+ val widgetPriorityIndex = priorityList.indexOfFirst { it.contains("${widget.widgetName} Widget") }
+ if (editingIndex < 0 || widgetPriorityIndex < 0) {
+ return
+ }
+ if (editingIndex == widgetPriorityIndex) {
+ Arrow.drawBigRedArrow(gui, prioritySlot, "Shift Right Click")
+ } else if (editingIndex < widgetPriorityIndex) {
+ Arrow.drawBigRedArrow(gui, prioritySlot, "Left Click")
+ } else {
+ Arrow.drawBigRedArrow(gui, prioritySlot, "Right Click")
+ }
+ }
+
+ fun getRegionName(label: String): String? {
+ if (!label.startsWith("Widgets")) return null
+ if (label == "Private Islands") return "Private Island"
+ return label.removePrefix("Widgets ").removePrefix("in ").removePrefix("on ")
+ .removePrefix("the ")
+ }
+
+ private fun drawSelectAreaArrow(gui: GuiChest, inventory: ContainerChest, task: TabListWidget) {
+ var regionName = task.regionName
+ if (regionName == "CURRENT_REGION") {
+ val infoSlot = inventory.inventory.getOrNull(4).let(ItemUtils::getLore)
+ if (infoSlot.isEmpty()) {
+ return
+ }
+ val lastLine = infoSlot.last().stripControlCodes()
+ val pattern = Regex("Click to edit (?<area>[\\w\\s]+) settings!")
+
+ val result = pattern.matchEntire(lastLine) ?: return
+ regionName = result.groups["area"]?.value!!
+ activeTask!!.regionName = regionName
+ }
+
+ val regionSlot = inventory.inventorySlots.find {
+ val name = ItemUtils.getDisplayName(it.stack)?.let(StringUtils::cleanColour) ?: ""
+ getRegionName(name) == regionName
+ } ?: return
+ Arrow.drawBigRedArrow(gui, regionSlot, "§cClick here!")
+ }
+
+ @SubscribeEvent
+ fun onCommands(event: RegisterBrigadierCommandEvent) {
+ event.command("neutesttablisttutorial") {
+ thenArgument("region", string()) { region ->
+ thenArgument("widget", string()) { widget ->
+ thenExecute {
+ TablistTaskQueue.addToQueue(
+ TabListWidget(
+ "Dwarven Mines",
+ TablistAPI.WidgetNames.COMMISSIONS,
+ ),
+ true
+ )
+ NotEnoughUpdates.INSTANCE.sendChatMessage("/tab")
+ }
+ }.withHelp("Test command for showing a tab list tutorial")
+ }
+ }
+
+ event.command("neutesttablistapi") {
+ thenExecute {
+ TablistAPI.getWidgetLinesInRegion(TabListWidget("CURRENT_REGION", TablistAPI.WidgetNames.SKILLS),
+ addToQueue = true,
+ showNotification = true
+ )
+ .forEach { println(it) }
+// println("SEP")
+// TablistAPI.getWidgetLines(TabListWidget("Dwarven Mines", TablistAPI.WidgetNames.FORGE))
+// .forEach { println(it) }
+ }
+ }
+ }
+}
diff --git a/src/main/kotlin/io/github/moulberry/notenoughupdates/util/StateManagerUtils.kt b/src/main/kotlin/io/github/moulberry/notenoughupdates/util/StateManagerUtils.kt
new file mode 100644
index 00000000..a7e50fda
--- /dev/null
+++ b/src/main/kotlin/io/github/moulberry/notenoughupdates/util/StateManagerUtils.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2024 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.util
+
+import io.github.moulberry.notenoughupdates.mixins.AccessorBooleanState
+import net.minecraft.client.renderer.GlStateManager
+
+object StateManagerUtils {
+ fun readState(state: GlStateManager.BooleanState): Boolean {
+ state as AccessorBooleanState
+ return state.currentState
+ }
+
+ inline fun withSavedState(state: GlStateManager.BooleanState, block: () -> Unit) {
+ val savedState = readState(state)
+ block()
+ state.setState(savedState)
+ }
+}
diff --git a/src/main/kotlin/io/github/moulberry/notenoughupdates/util/TabSkillInfoParser.kt b/src/main/kotlin/io/github/moulberry/notenoughupdates/util/TabSkillInfoParser.kt
index b4bfdf28..0c3e1901 100644
--- a/src/main/kotlin/io/github/moulberry/notenoughupdates/util/TabSkillInfoParser.kt
+++ b/src/main/kotlin/io/github/moulberry/notenoughupdates/util/TabSkillInfoParser.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 NotEnoughUpdates contributors
+ * Copyright (C) 2023-2024 NotEnoughUpdates contributors
*
* This file is part of NotEnoughUpdates.
*
@@ -20,15 +20,17 @@
package io.github.moulberry.notenoughupdates.util
import com.google.gson.JsonArray
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates
+import io.github.moulberry.notenoughupdates.miscfeatures.tablisttutorial.TablistAPI
import net.minecraft.util.EnumChatFormatting
import java.util.regex.Pattern
import kotlin.math.abs
object TabSkillInfoParser {
private val skillTabPattern: Pattern =
- Pattern.compile("^§r§e§lSkills: §r§a(?<type>\\w+) (?<level>\\d+): §r§3(?<progress>.+)%§r\$")
+ Pattern.compile("^§r (?<type>\\w+) (?<level>\\d+): §r§a(?<progress>.+)%§r\$")
private val maxSkillTabPattern: Pattern =
- Pattern.compile("^§r§e§lSkills: §r§a(?<type>\\w+) (?<level>\\d+): §r§c§lMAX§r\$")
+ Pattern.compile("^§r (?<type>\\w+) (?<level>\\d+): §r§c§lMAX§r\$")
private var sentErrorOnce = false
private fun calculateLevelXp(levelingArray: JsonArray, level: Int): Double {
@@ -58,12 +60,18 @@ object TabSkillInfoParser {
@JvmStatic
fun parseSkillInfo() {
+ if (!NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) {
+ return
+ }
+
if (Constants.LEVELING == null) {
sendError("${EnumChatFormatting.RED}[NEU] There is an error with your repo, please report this in the discord at ${EnumChatFormatting.AQUA}discord.gg/moulberry")
return
}
- for (s in TabListUtils.getTabList()) {
+ for (s in TablistAPI.getOptionalWidgetLines(
+ TablistAPI.WidgetNames.SKILLS
+ )) {
val matcher = skillTabPattern.matcher(s)
val maxLevelMatcher = maxSkillTabPattern.matcher(s)
if (matcher.matches()) {