From 93e6e0ab16df0808ee7720202a32967eddcf5c10 Mon Sep 17 00:00:00 2001 From: Linnea Gräf Date: Tue, 7 May 2024 21:11:09 +0200 Subject: Fix up most of the remaining event handlers [no changelog] --- .../firmament/events/subscription/Subscription.kt | 5 +- .../moe/nea/firmament/features/FirmamentFeature.kt | 4 +- .../nea/firmament/features/chat/AutoCompletions.kt | 43 +-- .../moe/nea/firmament/features/chat/ChatLinks.kt | 131 ++++---- .../nea/firmament/features/chat/QuickCommands.kt | 48 +-- .../firmament/features/debug/DeveloperFeatures.kt | 4 - .../nea/firmament/features/debug/MinorTrolling.kt | 18 +- .../nea/firmament/features/debug/PowerUserTools.kt | 175 +++++------ .../features/diana/AncestralSpadeSolver.kt | 13 +- .../nea/firmament/features/diana/DianaWaypoints.kt | 11 - .../features/diana/NearbyBurrowsSolver.kt | 12 +- .../features/fixes/CompatibliltyFeatures.kt | 18 +- .../moe/nea/firmament/features/fixes/Fixes.kt | 44 +-- .../features/inventory/CraftingOverlay.kt | 62 ++-- .../features/inventory/ItemRarityCosmetics.kt | 25 +- .../nea/firmament/features/inventory/PriceData.kt | 5 +- .../features/inventory/SaveCursorPosition.kt | 4 - .../firmament/features/inventory/SlotLocking.kt | 143 ++++----- .../features/inventory/buttons/InventoryButtons.kt | 56 ++-- .../inventory/storageoverlay/StorageOverlay.kt | 51 ++-- .../firmament/features/mining/PickaxeAbility.kt | 94 +++--- .../features/mining/PristineProfitTracker.kt | 32 +- .../features/texturepack/CustomSkyBlockTextures.kt | 24 +- .../moe/nea/firmament/features/world/FairySouls.kt | 87 +++--- .../moe/nea/firmament/features/world/Waypoints.kt | 334 +++++++++++---------- 25 files changed, 745 insertions(+), 698 deletions(-) (limited to 'src') diff --git a/src/main/kotlin/moe/nea/firmament/events/subscription/Subscription.kt b/src/main/kotlin/moe/nea/firmament/events/subscription/Subscription.kt index 1e7a6a8..a4542e7 100644 --- a/src/main/kotlin/moe/nea/firmament/events/subscription/Subscription.kt +++ b/src/main/kotlin/moe/nea/firmament/events/subscription/Subscription.kt @@ -8,8 +8,11 @@ package moe.nea.firmament.events.subscription import moe.nea.firmament.events.FirmamentEvent import moe.nea.firmament.events.FirmamentEventBus +import moe.nea.firmament.features.FirmamentFeature -interface SubscriptionOwner +interface SubscriptionOwner { + val delegateFeature: FirmamentFeature +} data class Subscription( val owner: SubscriptionOwner, diff --git a/src/main/kotlin/moe/nea/firmament/features/FirmamentFeature.kt b/src/main/kotlin/moe/nea/firmament/features/FirmamentFeature.kt index 2416fec..4b7ba9e 100644 --- a/src/main/kotlin/moe/nea/firmament/features/FirmamentFeature.kt +++ b/src/main/kotlin/moe/nea/firmament/features/FirmamentFeature.kt @@ -19,7 +19,9 @@ interface FirmamentFeature : SubscriptionOwner { set(value) { FeatureManager.setEnabled(identifier, value) } + override val delegateFeature: FirmamentFeature + get() = this val config: ManagedConfig? get() = null - fun onLoad() + fun onLoad() {} } diff --git a/src/main/kotlin/moe/nea/firmament/features/chat/AutoCompletions.kt b/src/main/kotlin/moe/nea/firmament/features/chat/AutoCompletions.kt index 9912321..3351970 100644 --- a/src/main/kotlin/moe/nea/firmament/features/chat/AutoCompletions.kt +++ b/src/main/kotlin/moe/nea/firmament/features/chat/AutoCompletions.kt @@ -7,6 +7,7 @@ package moe.nea.firmament.features.chat import com.mojang.brigadier.arguments.StringArgumentType.string +import moe.nea.firmament.annotations.Subscribe import moe.nea.firmament.commands.get import moe.nea.firmament.commands.suggestsList import moe.nea.firmament.commands.thenArgument @@ -30,28 +31,28 @@ object AutoCompletions : FirmamentFeature { override val identifier: String get() = "auto-completions" - override fun onLoad() { - MaskCommands.subscribe { - if (TConfig.provideWarpTabCompletion) { - it.mask("warp") - } + @Subscribe + fun onMaskCommands(event: MaskCommands) { + if (TConfig.provideWarpTabCompletion) { + event.mask("warp") } - CommandEvent.subscribe { - if (TConfig.provideWarpTabCompletion) { - it.deleteCommand("warp") - it.register("warp") { - thenArgument("to", string()) { toArg -> - suggestsList { - RepoManager.neuRepo.constants?.islands?.warps?.flatMap { listOf(it.warp) + it.aliases } ?: listOf() - } - thenExecute { - val warpName = get(toArg) - if (warpName == "is" && TConfig.replaceWarpIsByWarpIsland) { - MC.sendServerCommand("warp island") - } else { - MC.sendServerCommand("warp ${warpName}") - } - } + } + + @Subscribe + fun onCommandEvent(event: CommandEvent) { + if (!TConfig.provideWarpTabCompletion) return + event.deleteCommand("warp") + event.register("warp") { + thenArgument("to", string()) { toArg -> + suggestsList { + RepoManager.neuRepo.constants?.islands?.warps?.flatMap { listOf(it.warp) + it.aliases } ?: listOf() + } + thenExecute { + val warpName = get(toArg) + if (warpName == "is" && TConfig.replaceWarpIsByWarpIsland) { + MC.sendServerCommand("warp island") + } else { + MC.sendServerCommand("warp $warpName") } } } diff --git a/src/main/kotlin/moe/nea/firmament/features/chat/ChatLinks.kt b/src/main/kotlin/moe/nea/firmament/features/chat/ChatLinks.kt index 6bb6f6e..717e503 100644 --- a/src/main/kotlin/moe/nea/firmament/features/chat/ChatLinks.kt +++ b/src/main/kotlin/moe/nea/firmament/features/chat/ChatLinks.kt @@ -6,11 +6,11 @@ package moe.nea.firmament.features.chat -import io.ktor.client.request.* -import io.ktor.client.statement.* -import io.ktor.utils.io.jvm.javaio.* +import io.ktor.client.request.get +import io.ktor.client.statement.bodyAsChannel +import io.ktor.utils.io.jvm.javaio.toInputStream import java.net.URL -import java.util.* +import java.util.Collections import moe.nea.jarvis.api.Point import kotlinx.coroutines.Deferred import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -26,6 +26,7 @@ import net.minecraft.text.Text import net.minecraft.util.Formatting import net.minecraft.util.Identifier import moe.nea.firmament.Firmament +import moe.nea.firmament.annotations.Subscribe import moe.nea.firmament.events.ModifyChatEvent import moe.nea.firmament.events.ScreenRenderPostEvent import moe.nea.firmament.features.FirmamentFeature @@ -96,69 +97,69 @@ object ChatLinks : FirmamentFeature { return (url.substringAfterLast('.').lowercase() in imageExtensions) } + @Subscribe @OptIn(ExperimentalCoroutinesApi::class) - override fun onLoad() { - ModifyChatEvent.subscribe { - if (TConfig.enableLinks) - it.replaceWith = it.replaceWith.transformEachRecursively { child -> - val text = child.string - if ("://" !in text) return@transformEachRecursively child - val s = Text.empty().setStyle(child.style) - var index = 0 - while (index < text.length) { - val nextMatch = urlRegex.find(text, index) - if (nextMatch == null) { - s.append(Text.literal(text.substring(index, text.length))) - break - } - val range = nextMatch.groups[0]!!.range - val url = nextMatch.groupValues[0] - s.append(Text.literal(text.substring(index, range.first))) - s.append( - Text.literal(url).setStyle( - Style.EMPTY.withUnderline(true).withColor( - Formatting.AQUA - ).withHoverEvent(HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.literal(url))) - .withClickEvent(ClickEvent(ClickEvent.Action.OPEN_URL, url)) - ) - ) - if (isImageUrl(url)) - tryCacheUrl(url) - index = range.last + 1 - } - s - } - } + fun onRender(it: ScreenRenderPostEvent) { + if (!TConfig.imageEnabled) return + if (it.screen !is ChatScreen) return + val hoveredComponent = + MC.inGameHud.chatHud.getTextStyleAt(it.mouseX.toDouble(), it.mouseY.toDouble()) ?: return + val hoverEvent = hoveredComponent.hoverEvent ?: return + val value = hoverEvent.getValue(HoverEvent.Action.SHOW_TEXT) ?: return + val url = urlRegex.matchEntire(value.unformattedString)?.groupValues?.get(0) ?: return + if (!isImageUrl(url)) return + val imageFuture = imageCache[url] ?: return + if (!imageFuture.isCompleted) return + val image = imageFuture.getCompleted() ?: return + it.drawContext.matrices.push() + val pos = TConfig.position + pos.applyTransformations(it.drawContext.matrices) + val scale = min(1F, min((9 * 20F) / image.height, (16 * 20F) / image.width)) + it.drawContext.matrices.scale(scale, scale, 1F) + it.drawContext.drawTexture( + image.texture, + 0, + 0, + 1F, + 1F, + image.width, + image.height, + image.width, + image.height, + ) + it.drawContext.matrices.pop() + } - ScreenRenderPostEvent.subscribe { - if (!TConfig.imageEnabled) return@subscribe - if (it.screen !is ChatScreen) return@subscribe - val hoveredComponent = - MC.inGameHud.chatHud.getTextStyleAt(it.mouseX.toDouble(), it.mouseY.toDouble()) ?: return@subscribe - val hoverEvent = hoveredComponent.hoverEvent ?: return@subscribe - val value = hoverEvent.getValue(HoverEvent.Action.SHOW_TEXT) ?: return@subscribe - val url = urlRegex.matchEntire(value.unformattedString)?.groupValues?.get(0) ?: return@subscribe - if (!isImageUrl(url)) return@subscribe - val imageFuture = imageCache[url] ?: return@subscribe - if (!imageFuture.isCompleted) return@subscribe - val image = imageFuture.getCompleted() ?: return@subscribe - it.drawContext.matrices.push() - val pos = TConfig.position - pos.applyTransformations(it.drawContext.matrices) - val scale = min(1F, min((9 * 20F) / image.height, (16 * 20F) / image.width)) - it.drawContext.matrices.scale(scale, scale, 1F) - it.drawContext.drawTexture( - image.texture, - 0, - 0, - 1F, - 1F, - image.width, - image.height, - image.width, - image.height, - ) - it.drawContext.matrices.pop() + @Subscribe + fun onModifyChat(it: ModifyChatEvent) { + if (!TConfig.enableLinks) return + it.replaceWith = it.replaceWith.transformEachRecursively { child -> + val text = child.string + if ("://" !in text) return@transformEachRecursively child + val s = Text.empty().setStyle(child.style) + var index = 0 + while (index < text.length) { + val nextMatch = urlRegex.find(text, index) + if (nextMatch == null) { + s.append(Text.literal(text.substring(index, text.length))) + break + } + val range = nextMatch.groups[0]!!.range + val url = nextMatch.groupValues[0] + s.append(Text.literal(text.substring(index, range.first))) + s.append( + Text.literal(url).setStyle( + Style.EMPTY.withUnderline(true).withColor( + Formatting.AQUA + ).withHoverEvent(HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.literal(url))) + .withClickEvent(ClickEvent(ClickEvent.Action.OPEN_URL, url)) + ) + ) + if (isImageUrl(url)) + tryCacheUrl(url) + index = range.last + 1 + } + s } } } diff --git a/src/main/kotlin/moe/nea/firmament/features/chat/QuickCommands.kt b/src/main/kotlin/moe/nea/firmament/features/chat/QuickCommands.kt index 47be3c1..97ec6e8 100644 --- a/src/main/kotlin/moe/nea/firmament/features/chat/QuickCommands.kt +++ b/src/main/kotlin/moe/nea/firmament/features/chat/QuickCommands.kt @@ -8,6 +8,7 @@ package moe.nea.firmament.features.chat import com.mojang.brigadier.context.CommandContext import net.minecraft.text.Text +import moe.nea.firmament.annotations.Subscribe import moe.nea.firmament.commands.DefaultSource import moe.nea.firmament.commands.RestArgumentType import moe.nea.firmament.commands.get @@ -34,29 +35,30 @@ object QuickCommands : FirmamentFeature { val kuudraLevelNames = listOf("NORMAL", "HOT", "BURNING", "FIERY", "INFERNAL") val dungeonLevelNames = listOf("ONE", "TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN") - override fun onLoad() { - CommandEvent.subscribe { - it.register("join") { - thenArgument("what", RestArgumentType) { what -> - thenExecute { - val what = this[what] - if (!SBData.isOnSkyblock) { - MC.sendCommand("join $what") - return@thenExecute - } - val joinName = getNameForFloor(what.replace(" ", "").lowercase()) - if (joinName == null) { - source.sendFeedback(Text.stringifiedTranslatable("firmament.quick-commands.join.unknown", what)) - } else { - source.sendFeedback(Text.stringifiedTranslatable("firmament.quick-commands.join.success", joinName)) - MC.sendCommand("joininstance $joinName") - } - } - } + + @Subscribe + fun onCommands(it: CommandEvent) { + it.register("join") { + thenArgument("what", RestArgumentType) { what -> thenExecute { - source.sendFeedback(Text.translatable("firmament.quick-commands.join.explain")) + val what = this[what] + if (!SBData.isOnSkyblock) { + MC.sendCommand("join $what") + return@thenExecute + } + val joinName = getNameForFloor(what.replace(" ", "").lowercase()) + if (joinName == null) { + source.sendFeedback(Text.stringifiedTranslatable("firmament.quick-commands.join.unknown", what)) + } else { + source.sendFeedback(Text.stringifiedTranslatable("firmament.quick-commands.join.success", + joinName)) + MC.sendCommand("joininstance $joinName") + } } } + thenExecute { + source.sendFeedback(Text.translatable("firmament.quick-commands.join.explain")) + } } } @@ -70,7 +72,8 @@ object QuickCommands : FirmamentFeature { ) } if (l !in kuudraLevelNames.indices) { - source.sendFeedback(Text.stringifiedTranslatable("firmament.quick-commands.join.unknown-kuudra", kuudraLevel)) + source.sendFeedback(Text.stringifiedTranslatable("firmament.quick-commands.join.unknown-kuudra", + kuudraLevel)) return null } return "KUUDRA_${kuudraLevelNames[l]}" @@ -90,7 +93,8 @@ object QuickCommands : FirmamentFeature { return "CATACOMBS_ENTRANCE" } if (l !in dungeonLevelNames.indices) { - source.sendFeedback(Text.stringifiedTranslatable("firmament.quick-commands.join.unknown-catacombs", kuudraLevel)) + source.sendFeedback(Text.stringifiedTranslatable("firmament.quick-commands.join.unknown-catacombs", + kuudraLevel)) return null } return "${if (masterLevel != null) "MASTER_" else ""}CATACOMBS_FLOOR_${dungeonLevelNames[l]}" diff --git a/src/main/kotlin/moe/nea/firmament/features/debug/DeveloperFeatures.kt b/src/main/kotlin/moe/nea/firmament/features/debug/DeveloperFeatures.kt index 6bbbdf0..1d7ce49 100644 --- a/src/main/kotlin/moe/nea/firmament/features/debug/DeveloperFeatures.kt +++ b/src/main/kotlin/moe/nea/firmament/features/debug/DeveloperFeatures.kt @@ -55,9 +55,5 @@ object DeveloperFeatures : FirmamentFeature { } return reloadFuture.thenCompose { client.reloadResources() } } - - - override fun onLoad() { - } } diff --git a/src/main/kotlin/moe/nea/firmament/features/debug/MinorTrolling.kt b/src/main/kotlin/moe/nea/firmament/features/debug/MinorTrolling.kt index 95c77ab..57fd8e2 100644 --- a/src/main/kotlin/moe/nea/firmament/features/debug/MinorTrolling.kt +++ b/src/main/kotlin/moe/nea/firmament/features/debug/MinorTrolling.kt @@ -6,9 +6,10 @@ package moe.nea.firmament.features.debug +import net.minecraft.text.Text +import moe.nea.firmament.annotations.Subscribe import moe.nea.firmament.events.ModifyChatEvent import moe.nea.firmament.features.FirmamentFeature -import net.minecraft.text.Text // In memorian Dulkir @@ -19,13 +20,12 @@ object MinorTrolling : FirmamentFeature { val trollers = listOf("nea89o", "lrg89") val t = "From(?: \\[[^\\]]+])? ([^:]+): (.*)".toRegex() - override fun onLoad() { - ModifyChatEvent.subscribe { - val m = t.matchEntire(it.unformattedString) ?: return@subscribe - val (_, name, text) = m.groupValues - if (name !in trollers) return@subscribe - if (!text.startsWith("c:")) return@subscribe - it.replaceWith = Text.literal(text.substring(2).replace("&", "§")) - } + @Subscribe + fun onTroll(it: ModifyChatEvent) { + val m = t.matchEntire(it.unformattedString) ?: return + val (_, name, text) = m.groupValues + if (name !in trollers) return + if (!text.startsWith("c:")) return + it.replaceWith = Text.literal(text.substring(2).replace("&", "§")) } } diff --git a/src/main/kotlin/moe/nea/firmament/features/debug/PowerUserTools.kt b/src/main/kotlin/moe/nea/firmament/features/debug/PowerUserTools.kt index 99ef0d5..d530487 100644 --- a/src/main/kotlin/moe/nea/firmament/features/debug/PowerUserTools.kt +++ b/src/main/kotlin/moe/nea/firmament/features/debug/PowerUserTools.kt @@ -15,6 +15,7 @@ import net.minecraft.item.Items import net.minecraft.text.Text import net.minecraft.util.hit.BlockHitResult import net.minecraft.util.hit.HitResult +import moe.nea.firmament.annotations.Subscribe import moe.nea.firmament.events.CustomItemModelEvent import moe.nea.firmament.events.HandledScreenKeyPressedEvent import moe.nea.firmament.events.ItemTooltipEvent @@ -54,42 +55,6 @@ object PowerUserTools : FirmamentFeature { var lastCopiedStackViewTime = false override fun onLoad() { - ItemTooltipEvent.subscribe { - if (TConfig.showItemIds) { - val id = it.stack.skyBlockId ?: return@subscribe - it.lines.add(Text.stringifiedTranslatable("firmament.tooltip.skyblockid", id.neuItem)) - } - val (item, text) = lastCopiedStack ?: return@subscribe - if (!ItemStack.areEqual(item, it.stack)) { - lastCopiedStack = null - return@subscribe - } - lastCopiedStackViewTime = true - it.lines.add(text) - } - WorldKeyboardEvent.subscribe { - if (it.matches(TConfig.copySkullTexture)) { - val p = MC.camera ?: return@subscribe - val blockHit = p.raycast(20.0, 0.0f, false) ?: return@subscribe - if (blockHit.type != HitResult.Type.BLOCK || blockHit !is BlockHitResult) { - MC.sendChat(Text.translatable("firmament.tooltip.copied.skull.fail")) - return@subscribe - } - val blockAt = p.world.getBlockState(blockHit.blockPos)?.block - val entity = p.world.getBlockEntity(blockHit.blockPos) - if (blockAt !is SkullBlock || entity !is SkullBlockEntity || entity.owner == null) { - MC.sendChat(Text.translatable("firmament.tooltip.copied.skull.fail")) - return@subscribe - } - val id = CustomSkyBlockTextures.getSkullTexture(entity.owner!!) - if (id == null) { - MC.sendChat(Text.translatable("firmament.tooltip.copied.skull.fail")) - } else { - ClipboardUtils.setTextContent(id.toString()) - MC.sendChat(Text.stringifiedTranslatable("firmament.tooltip.copied.skull", id.toString())) - } - } - } TickEvent.subscribe { if (!lastCopiedStackViewTime) lastCopiedStack = null @@ -98,56 +63,98 @@ object PowerUserTools : FirmamentFeature { ScreenChangeEvent.subscribe { lastCopiedStack = null } - HandledScreenKeyPressedEvent.subscribe { - if (it.screen !is AccessorHandledScreen) return@subscribe - val item = it.screen.focusedItemStack ?: return@subscribe - if (it.matches(TConfig.copyItemId)) { - val sbId = item.skyBlockId - if (sbId == null) { - lastCopiedStack = Pair(item, Text.translatable("firmament.tooltip.copied.skyblockid.fail")) - return@subscribe - } - ClipboardUtils.setTextContent(sbId.neuItem) - lastCopiedStack = - Pair(item, Text.stringifiedTranslatable("firmament.tooltip.copied.skyblockid", sbId.neuItem)) - } else if (it.matches(TConfig.copyTexturePackId)) { - val model = CustomItemModelEvent.getModelIdentifier(item) - if (model == null) { - lastCopiedStack = Pair(item, Text.translatable("firmament.tooltip.copied.modelid.fail")) - return@subscribe - } - ClipboardUtils.setTextContent(model.toString()) - lastCopiedStack = - Pair(item, Text.stringifiedTranslatable("firmament.tooltip.copied.modelid", model.toString())) - } else if (it.matches(TConfig.copyNbtData)) { - // TODO: copy full nbt - val nbt = item.get(DataComponentTypes.CUSTOM_DATA)?.nbt?.toString() ?: "" - ClipboardUtils.setTextContent(nbt) - lastCopiedStack = Pair(item, Text.translatable("firmament.tooltip.copied.nbt")) - } else if (it.matches(TConfig.copySkullTexture)) { - if (item.item != Items.PLAYER_HEAD) { - lastCopiedStack = Pair(item, Text.translatable("firmament.tooltip.copied.skull-id.fail.no-skull")) - return@subscribe - } - val profile = item.get(DataComponentTypes.PROFILE) - if (profile == null) { - lastCopiedStack = Pair(item, Text.translatable("firmament.tooltip.copied.skull-id.fail.no-profile")) - return@subscribe - } - val skullTexture = CustomSkyBlockTextures.getSkullTexture(profile) - if (skullTexture == null) { - lastCopiedStack = Pair(item, Text.translatable("firmament.tooltip.copied.skull-id.fail.no-texture")) - return@subscribe - } - ClipboardUtils.setTextContent(skullTexture.toString()) - lastCopiedStack = - Pair( - item, - Text.stringifiedTranslatable("firmament.tooltip.copied.skull-id", skullTexture.toString()) - ) - println("Copied skull id: $skullTexture") + } + + @Subscribe + fun copyInventoryInfo(it: HandledScreenKeyPressedEvent) { + if (it.screen !is AccessorHandledScreen) return + val item = it.screen.focusedItemStack ?: return + if (it.matches(TConfig.copyItemId)) { + val sbId = item.skyBlockId + if (sbId == null) { + lastCopiedStack = Pair(item, Text.translatable("firmament.tooltip.copied.skyblockid.fail")) + return + } + ClipboardUtils.setTextContent(sbId.neuItem) + lastCopiedStack = + Pair(item, Text.stringifiedTranslatable("firmament.tooltip.copied.skyblockid", sbId.neuItem)) + } else if (it.matches(TConfig.copyTexturePackId)) { + val model = CustomItemModelEvent.getModelIdentifier(item) + if (model == null) { + lastCopiedStack = Pair(item, Text.translatable("firmament.tooltip.copied.modelid.fail")) + return + } + ClipboardUtils.setTextContent(model.toString()) + lastCopiedStack = + Pair(item, Text.stringifiedTranslatable("firmament.tooltip.copied.modelid", model.toString())) + } else if (it.matches(TConfig.copyNbtData)) { + // TODO: copy full nbt + val nbt = item.get(DataComponentTypes.CUSTOM_DATA)?.nbt?.toString() ?: "" + ClipboardUtils.setTextContent(nbt) + lastCopiedStack = Pair(item, Text.translatable("firmament.tooltip.copied.nbt")) + } else if (it.matches(TConfig.copySkullTexture)) { + if (item.item != Items.PLAYER_HEAD) { + lastCopiedStack = Pair(item, Text.translatable("firmament.tooltip.copied.skull-id.fail.no-skull")) + return + } + val profile = item.get(DataComponentTypes.PROFILE) + if (profile == null) { + lastCopiedStack = Pair(item, Text.translatable("firmament.tooltip.copied.skull-id.fail.no-profile")) + return + } + val skullTexture = CustomSkyBlockTextures.getSkullTexture(profile) + if (skullTexture == null) { + lastCopiedStack = Pair(item, Text.translatable("firmament.tooltip.copied.skull-id.fail.no-texture")) + return } + ClipboardUtils.setTextContent(skullTexture.toString()) + lastCopiedStack = + Pair( + item, + Text.stringifiedTranslatable("firmament.tooltip.copied.skull-id", skullTexture.toString()) + ) + println("Copied skull id: $skullTexture") + } + } + + @Subscribe + fun onCopyWorldInfo(it: WorldKeyboardEvent) { + if (it.matches(TConfig.copySkullTexture)) { + val p = MC.camera ?: return + val blockHit = p.raycast(20.0, 0.0f, false) ?: return + if (blockHit.type != HitResult.Type.BLOCK || blockHit !is BlockHitResult) { + MC.sendChat(Text.translatable("firmament.tooltip.copied.skull.fail")) + return + } + val blockAt = p.world.getBlockState(blockHit.blockPos)?.block + val entity = p.world.getBlockEntity(blockHit.blockPos) + if (blockAt !is SkullBlock || entity !is SkullBlockEntity || entity.owner == null) { + MC.sendChat(Text.translatable("firmament.tooltip.copied.skull.fail")) + return + } + val id = CustomSkyBlockTextures.getSkullTexture(entity.owner!!) + if (id == null) { + MC.sendChat(Text.translatable("firmament.tooltip.copied.skull.fail")) + } else { + ClipboardUtils.setTextContent(id.toString()) + MC.sendChat(Text.stringifiedTranslatable("firmament.tooltip.copied.skull", id.toString())) + } + } + } + + @Subscribe + fun addItemId(it: ItemTooltipEvent) { + if (TConfig.showItemIds) { + val id = it.stack.skyBlockId ?: return + it.lines.add(Text.stringifiedTranslatable("firmament.tooltip.skyblockid", id.neuItem)) + } + val (item, text) = lastCopiedStack ?: return + if (!ItemStack.areEqual(item, it.stack)) { + lastCopiedStack = null + return } + lastCopiedStackViewTime = true + it.lines.add(text) } diff --git a/src/main/kotlin/moe/nea/firmament/features/diana/AncestralSpadeSolver.kt b/src/main/kotlin/moe/nea/firmament/features/diana/AncestralSpadeSolver.kt index b9c83e6..e80ef92 100644 --- a/src/main/kotlin/moe/nea/firmament/features/diana/AncestralSpadeSolver.kt +++ b/src/main/kotlin/moe/nea/firmament/features/diana/AncestralSpadeSolver.kt @@ -10,17 +10,20 @@ import kotlin.time.Duration.Companion.seconds import net.minecraft.particle.ParticleTypes import net.minecraft.sound.SoundEvents import net.minecraft.util.math.Vec3d +import moe.nea.firmament.annotations.Subscribe import moe.nea.firmament.events.ParticleSpawnEvent import moe.nea.firmament.events.SoundReceiveEvent import moe.nea.firmament.events.WorldKeyboardEvent import moe.nea.firmament.events.WorldReadyEvent import moe.nea.firmament.events.WorldRenderLastEvent +import moe.nea.firmament.events.subscription.SubscriptionOwner +import moe.nea.firmament.features.FirmamentFeature import moe.nea.firmament.util.SBData import moe.nea.firmament.util.TimeMark import moe.nea.firmament.util.WarpUtil import moe.nea.firmament.util.render.RenderInWorldContext -object AncestralSpadeSolver { +object AncestralSpadeSolver : SubscriptionOwner { var lastDing = TimeMark.farPast() private set private val pitches = mutableListOf() @@ -33,6 +36,7 @@ object AncestralSpadeSolver { fun isEnabled() = DianaWaypoints.TConfig.ancestralSpadeSolver && SBData.skyblockLocation == "hub" + @Subscribe fun onKeyBind(event: WorldKeyboardEvent) { if (!isEnabled()) return if (!event.matches(DianaWaypoints.TConfig.ancestralSpadeTeleport)) return @@ -42,6 +46,7 @@ object AncestralSpadeSolver { lastTeleportAttempt = TimeMark.now() } + @Subscribe fun onParticleSpawn(event: ParticleSpawnEvent) { if (!isEnabled()) return if (event.particleEffect != ParticleTypes.DRIPPING_LAVA) return @@ -53,6 +58,7 @@ object AncestralSpadeSolver { } } + @Subscribe fun onPlaySound(event: SoundReceiveEvent) { if (!isEnabled()) return if (!SoundEvents.BLOCK_NOTE_BLOCK_HARP.matchesId(event.sound.value().id)) return @@ -92,6 +98,7 @@ object AncestralSpadeSolver { nextGuess = event.position.add(lastParticleDirection.multiply(soundDistanceEstimate)) } + @Subscribe fun onWorldRender(event: WorldRenderLastEvent) { if (!isEnabled()) return RenderInWorldContext.renderInWorld(event) { @@ -108,6 +115,7 @@ object AncestralSpadeSolver { } } + @Subscribe fun onSwapWorld(event: WorldReadyEvent) { nextGuess = null particlePositions.clear() @@ -115,4 +123,7 @@ object AncestralSpadeSolver { lastDing = TimeMark.farPast() } + override val delegateFeature: FirmamentFeature + get() = DianaWaypoints + } diff --git a/src/main/kotlin/moe/nea/firmament/features/diana/DianaWaypoints.kt b/src/main/kotlin/moe/nea/firmament/features/diana/DianaWaypoints.kt index 9102497..b1f66c1 100644 --- a/src/main/kotlin/moe/nea/firmament/features/diana/DianaWaypoints.kt +++ b/src/main/kotlin/moe/nea/firmament/features/diana/DianaWaypoints.kt @@ -28,23 +28,12 @@ object DianaWaypoints : FirmamentFeature { } override fun onLoad() { - ParticleSpawnEvent.subscribe(NearbyBurrowsSolver::onParticles) - WorldReadyEvent.subscribe(NearbyBurrowsSolver::onSwapWorld) - WorldRenderLastEvent.subscribe(NearbyBurrowsSolver::onRender) UseBlockEvent.subscribe { NearbyBurrowsSolver.onBlockClick(it.hitResult.blockPos) } AttackBlockEvent.subscribe { NearbyBurrowsSolver.onBlockClick(it.blockPos) } - ProcessChatEvent.subscribe(NearbyBurrowsSolver::onChatEvent) - - - WorldKeyboardEvent.subscribe(AncestralSpadeSolver::onKeyBind) - ParticleSpawnEvent.subscribe(AncestralSpadeSolver::onParticleSpawn) - SoundReceiveEvent.subscribe(AncestralSpadeSolver::onPlaySound) - WorldRenderLastEvent.subscribe(AncestralSpadeSolver::onWorldRender) - WorldReadyEvent.subscribe(AncestralSpadeSolver::onSwapWorld) } } diff --git a/src/main/kotlin/moe/nea/firmament/features/diana/NearbyBurrowsSolver.kt b/src/main/kotlin/moe/nea/firmament/features/diana/NearbyBurrowsSolver.kt index 1ab7e01..e6aeeae 100644 --- a/src/main/kotlin/moe/nea/firmament/features/diana/NearbyBurrowsSolver.kt +++ b/src/main/kotlin/moe/nea/firmament/features/diana/NearbyBurrowsSolver.kt @@ -11,15 +11,18 @@ import net.minecraft.particle.ParticleTypes import net.minecraft.util.math.BlockPos import net.minecraft.util.math.MathHelper import net.minecraft.util.math.Position +import moe.nea.firmament.annotations.Subscribe import moe.nea.firmament.events.ParticleSpawnEvent import moe.nea.firmament.events.ProcessChatEvent import moe.nea.firmament.events.WorldReadyEvent import moe.nea.firmament.events.WorldRenderLastEvent +import moe.nea.firmament.events.subscription.SubscriptionOwner +import moe.nea.firmament.features.FirmamentFeature import moe.nea.firmament.util.TimeMark import moe.nea.firmament.util.mutableMapWithMaxSize import moe.nea.firmament.util.render.RenderInWorldContext.Companion.renderInWorld -object NearbyBurrowsSolver { +object NearbyBurrowsSolver : SubscriptionOwner { private val recentlyDugBurrows: MutableMap = mutableMapWithMaxSize(20) @@ -32,6 +35,7 @@ object NearbyBurrowsSolver { val burrows = mutableMapOf() + @Subscribe fun onChatEvent(event: ProcessChatEvent) { val lastClickedBurrow = lastBlockClick ?: return if (event.unformattedString.startsWith("You dug out a Griffin Burrow!") || @@ -62,6 +66,7 @@ object NearbyBurrowsSolver { recentEnchantParticles[blockPos] = TimeMark.now() } + @Subscribe fun onParticles(event: ParticleSpawnEvent) { if (!DianaWaypoints.TConfig.nearbyWaypoints) return @@ -106,6 +111,7 @@ object NearbyBurrowsSolver { } } + @Subscribe fun onRender(event: WorldRenderLastEvent) { if (!DianaWaypoints.TConfig.nearbyWaypoints) return renderInWorld(event) { @@ -120,6 +126,7 @@ object NearbyBurrowsSolver { } } + @Subscribe fun onSwapWorld(worldReadyEvent: WorldReadyEvent) { burrows.clear() recentEnchantParticles.clear() @@ -132,6 +139,9 @@ object NearbyBurrowsSolver { burrows.remove(blockPos) lastBlockClick = blockPos } + + override val delegateFeature: FirmamentFeature + get() = DianaWaypoints } fun Position.toBlockPos(): BlockPos { diff --git a/src/main/kotlin/moe/nea/firmament/features/fixes/CompatibliltyFeatures.kt b/src/main/kotlin/moe/nea/firmament/features/fixes/CompatibliltyFeatures.kt index d3029d8..041e9f3 100644 --- a/src/main/kotlin/moe/nea/firmament/features/fixes/CompatibliltyFeatures.kt +++ b/src/main/kotlin/moe/nea/firmament/features/fixes/CompatibliltyFeatures.kt @@ -10,6 +10,7 @@ import net.fabricmc.loader.api.FabricLoader import net.superkat.explosiveenhancement.api.ExplosiveApi import net.minecraft.particle.ParticleTypes import net.minecraft.util.math.Vec3d +import moe.nea.firmament.annotations.Subscribe import moe.nea.firmament.events.ParticleSpawnEvent import moe.nea.firmament.features.FirmamentFeature import moe.nea.firmament.gui.config.ManagedConfig @@ -41,15 +42,14 @@ object CompatibliltyFeatures : FirmamentFeature { ExplosiveApiWrapperImpl() } else null - override fun onLoad() { - ParticleSpawnEvent.subscribe { - if (TConfig.enhancedExplosions && - it.particleEffect.type == ParticleTypes.EXPLOSION_EMITTER && - explosiveApiWrapper != null - ) { - it.cancel() - explosiveApiWrapper.spawnParticle(it.position, 2F) - } + @Subscribe + fun onExplosion(it: ParticleSpawnEvent) { + if (TConfig.enhancedExplosions && + it.particleEffect.type == ParticleTypes.EXPLOSION_EMITTER && + explosiveApiWrapper != null + ) { + it.cancel() + explosiveApiWrapper.spawnParticle(it.position, 2F) } } } diff --git a/src/main/kotlin/moe/nea/firmament/features/fixes/Fixes.kt b/src/main/kotlin/moe/nea/firmament/features/fixes/Fixes.kt index 200bb74..26cfe6b 100644 --- a/src/main/kotlin/moe/nea/firmament/features/fixes/Fixes.kt +++ b/src/main/kotlin/moe/nea/firmament/features/fixes/Fixes.kt @@ -13,6 +13,7 @@ import net.minecraft.client.option.KeyBinding import net.minecraft.entity.player.PlayerEntity import net.minecraft.text.Text import net.minecraft.util.Arm +import moe.nea.firmament.annotations.Subscribe import moe.nea.firmament.events.HudRenderEvent import moe.nea.firmament.events.WorldKeyboardEvent import moe.nea.firmament.features.FirmamentFeature @@ -50,27 +51,28 @@ object Fixes : FirmamentFeature { } } - override fun onLoad() { - WorldKeyboardEvent.subscribe { - if (it.matches(TConfig.autoSprintKeyBinding)) { - TConfig.autoSprint = !TConfig.autoSprint - } - } - HudRenderEvent.subscribe { - if (!TConfig.autoSprintKeyBinding.isBound) return@subscribe - it.context.matrices.push() - TConfig.autoSprintHud.applyTransformations(it.context.matrices) - it.context.drawText( - MC.font, Text.translatable( - if (TConfig.autoSprint) - "firmament.fixes.auto-sprint.on" - else if (MC.player?.isSprinting == true) - "firmament.fixes.auto-sprint.sprinting" - else - "firmament.fixes.auto-sprint.not-sprinting" - ), 0, 0, -1, false - ) - it.context.matrices.pop() + @Subscribe + fun onRenderHud(it: HudRenderEvent) { + if (!TConfig.autoSprintKeyBinding.isBound) return + it.context.matrices.push() + TConfig.autoSprintHud.applyTransformations(it.context.matrices) + it.context.drawText( + MC.font, Text.translatable( + if (TConfig.autoSprint) + "firmament.fixes.auto-sprint.on" + else if (MC.player?.isSprinting == true) + "firmament.fixes.auto-sprint.sprinting" + else + "firmament.fixes.auto-sprint.not-sprinting" + ), 0, 0, -1, false + ) + it.context.matrices.pop() + } + + @Subscribe + fun onWorldKeyboard(it: WorldKeyboardEvent) { + if (it.matches(TConfig.autoSprintKeyBinding)) { + TConfig.autoSprint = !TConfig.autoSprint } } diff --git a/src/main/kotlin/moe/nea/firmament/features/inventory/CraftingOverlay.kt b/src/main/kotlin/moe/nea/firmament/features/inventory/CraftingOverlay.kt index e7f821d..866d1cc 100644 --- a/src/main/kotlin/moe/nea/firmament/features/inventory/CraftingOverlay.kt +++ b/src/main/kotlin/moe/nea/firmament/features/inventory/CraftingOverlay.kt @@ -9,11 +9,12 @@ package moe.nea.firmament.features.inventory import net.minecraft.client.gui.screen.ingame.GenericContainerScreen import net.minecraft.item.ItemStack import net.minecraft.util.Formatting +import moe.nea.firmament.annotations.Subscribe import moe.nea.firmament.events.SlotRenderEvents import moe.nea.firmament.features.FirmamentFeature -import moe.nea.firmament.rei.recipes.SBCraftingRecipe import moe.nea.firmament.rei.FirmamentReiPlugin.Companion.asItemEntry import moe.nea.firmament.rei.SBItemEntryDefinition +import moe.nea.firmament.rei.recipes.SBCraftingRecipe import moe.nea.firmament.util.MC object CraftingOverlay : FirmamentFeature { @@ -35,36 +36,35 @@ object CraftingOverlay : FirmamentFeature { override val identifier: String get() = "crafting-overlay" - override fun onLoad() { - SlotRenderEvents.After.subscribe { event -> - val slot = event.slot - val recipe = this.recipe ?: return@subscribe - if (slot.inventory != screen?.screenHandler?.inventory) return@subscribe - val recipeIndex = craftingOverlayIndices.indexOf(slot.index) - if (recipeIndex < 0) return@subscribe - val expectedItem = recipe.neuRecipe.inputs[recipeIndex] - val actualStack = slot.stack ?: ItemStack.EMPTY!! - val actualEntry = SBItemEntryDefinition.getEntry(actualStack).value - if ((actualEntry.skyblockId.neuItem != expectedItem.itemId || actualEntry.stackSize < expectedItem.amount) && expectedItem.amount.toInt() != 0) { - event.context.fill( - event.slot.x, - event.slot.y, - event.slot.x + 16, - event.slot.y + 16, - 0x80FF0000.toInt() - ) - } - if (!slot.hasStack()) { - val itemStack = SBItemEntryDefinition.getEntry(expectedItem).asItemEntry().value - event.context.drawItem(itemStack, event.slot.x, event.slot.y) - event.context.drawItemInSlot( - MC.font, - itemStack, - event.slot.x, - event.slot.y, - "${Formatting.RED}${expectedItem.amount.toInt()}" - ) - } + @Subscribe + fun onSlotRender(event: SlotRenderEvents.After) { + val slot = event.slot + val recipe = this.recipe ?: return + if (slot.inventory != screen?.screenHandler?.inventory) return + val recipeIndex = craftingOverlayIndices.indexOf(slot.index) + if (recipeIndex < 0) return + val expectedItem = recipe.neuRecipe.inputs[recipeIndex] + val actualStack = slot.stack ?: ItemStack.EMPTY!! + val actualEntry = SBItemEntryDefinition.getEntry(actualStack).value + if ((actualEntry.skyblockId.neuItem != expectedItem.itemId || actualEntry.stackSize < expectedItem.amount) && expectedItem.amount.toInt() != 0) { + event.context.fill( + event.slot.x, + event.slot.y, + event.slot.x + 16, + event.slot.y + 16, + 0x80FF0000.toInt() + ) + } + if (!slot.hasStack()) { + val itemStack = SBItemEntryDefinition.getEntry(expectedItem).asItemEntry().value + event.context.drawItem(itemStack, event.slot.x, event.slot.y) + event.context.drawItemInSlot( + MC.font, + itemStack, + event.slot.x, + event.slot.y, + "${Formatting.RED}${expectedItem.amount.toInt()}" + ) } } } diff --git a/src/main/kotlin/moe/nea/firmament/features/inventory/ItemRarityCosmetics.kt b/src/main/kotlin/moe/nea/firmament/features/inventory/ItemRarityCosmetics.kt index ac53546..dde0ddb 100644 --- a/src/main/kotlin/moe/nea/firmament/features/inventory/ItemRarityCosmetics.kt +++ b/src/main/kotlin/moe/nea/firmament/features/inventory/ItemRarityCosmetics.kt @@ -12,6 +12,7 @@ import net.minecraft.client.gui.DrawContext import net.minecraft.item.ItemStack import net.minecraft.util.Formatting import net.minecraft.util.Identifier +import moe.nea.firmament.annotations.Subscribe import moe.nea.firmament.events.HotbarItemRenderEvent import moe.nea.firmament.events.SlotRenderEvents import moe.nea.firmament.features.FirmamentFeature @@ -65,16 +66,18 @@ object ItemRarityCosmetics : FirmamentFeature { ) } - override fun onLoad() { - HotbarItemRenderEvent.subscribe { - if (!TConfig.showItemRarityInHotbar) return@subscribe - val stack = it.item - drawItemStackRarity(it.context, it.x, it.y, stack) - } - SlotRenderEvents.Before.subscribe { - if (!TConfig.showItemRarityBackground) return@subscribe - val stack = it.slot.stack ?: return@subscribe - drawItemStackRarity(it.context, it.slot.x, it.slot.y, stack) - } + + @Subscribe + fun onRenderSlot(it: SlotRenderEvents.Before) { + if (!TConfig.showItemRarityBackground) return + val stack = it.slot.stack ?: return + drawItemStackRarity(it.context, it.slot.x, it.slot.y, stack) + } + + @Subscribe + fun onRenderHotbarItem(it: HotbarItemRenderEvent) { + if (!TConfig.showItemRarityInHotbar) return + val stack = it.item + drawItemStackRarity(it.context, it.x, it.y, stack) } } diff --git a/src/main/kotlin/moe/nea/firmament/features/inventory/PriceData.kt b/src/main/kotlin/moe/nea/firmament/features/inventory/PriceData.kt index b511611..fb99c7c 100644 --- a/src/main/kotlin/moe/nea/firmament/features/inventory/PriceData.kt +++ b/src/main/kotlin/moe/nea/firmament/features/inventory/PriceData.kt @@ -27,11 +27,8 @@ object PriceData : FirmamentFeature { override val config get() = TConfig - override fun onLoad() { - } - @Subscribe - fun function(it: ItemTooltipEvent) { + fun onItemTooltip(it: ItemTooltipEvent) { if (!TConfig.tooltipEnabled && !TConfig.enableKeybinding.isPressed()) { return } diff --git a/src/main/kotlin/moe/nea/firmament/features/inventory/SaveCursorPosition.kt b/src/main/kotlin/moe/nea/firmament/features/inventory/SaveCursorPosition.kt index 2748822..e2d48a9 100644 --- a/src/main/kotlin/moe/nea/firmament/features/inventory/SaveCursorPosition.kt +++ b/src/main/kotlin/moe/nea/firmament/features/inventory/SaveCursorPosition.kt @@ -27,10 +27,6 @@ object SaveCursorPosition : FirmamentFeature { override val config: TConfig get() = TConfig - override fun onLoad() { - - } - var savedPositionedP1: Pair? = null var savedPosition: SavedPosition? = null diff --git a/src/main/kotlin/moe/nea/firmament/features/inventory/SlotLocking.kt b/src/main/kotlin/moe/nea/firmament/features/inventory/SlotLocking.kt index aee985c..b0fb57b 100644 --- a/src/main/kotlin/moe/nea/firmament/features/inventory/SlotLocking.kt +++ b/src/main/kotlin/moe/nea/firmament/features/inventory/SlotLocking.kt @@ -10,7 +10,7 @@ package moe.nea.firmament.features.inventory import com.mojang.blaze3d.systems.RenderSystem -import java.util.* +import java.util.UUID import org.lwjgl.glfw.GLFW import kotlinx.serialization.Serializable import kotlinx.serialization.UseSerializers @@ -18,6 +18,7 @@ import kotlinx.serialization.serializer import net.minecraft.client.gui.screen.ingame.HandledScreen import net.minecraft.entity.player.PlayerInventory import net.minecraft.screen.GenericContainerScreenHandler +import net.minecraft.screen.slot.Slot import net.minecraft.screen.slot.SlotActionType import net.minecraft.util.Identifier import moe.nea.firmament.annotations.Subscribe @@ -96,81 +97,89 @@ object SlotLocking : FirmamentFeature { return (lore.lastOrNull() ?: return false).unformattedString == "Click to buyback!" } - override fun onLoad() { - HandledScreenKeyPressedEvent.subscribe { - if (!it.matches(TConfig.lockSlot)) return@subscribe - val inventory = MC.handledScreen ?: return@subscribe - inventory as AccessorHandledScreen - - val slot = inventory.focusedSlot_Firmament ?: return@subscribe - val lockedSlots = lockedSlots ?: return@subscribe - if (slot.inventory is PlayerInventory) { - if (slot.index in lockedSlots) { - lockedSlots.remove(slot.index) - } else { - lockedSlots.add(slot.index) - } - DConfig.markDirty() - CommonSoundEffects.playSuccess() - } + @Subscribe + fun onSalvageProtect(event: IsSlotProtectedEvent) { + if (event.slot == null) return + if (!event.slot.hasStack()) return + if (event.slot.stack.displayNameAccordingToNbt?.unformattedString != "Salvage Items") return + val inv = event.slot.inventory + var anyBlocked = false + for (i in 0 until event.slot.index) { + val stack = inv.getStack(i) + if (IsSlotProtectedEvent.shouldBlockInteraction(null, SlotActionType.THROW, stack)) + anyBlocked = true } - HandledScreenKeyPressedEvent.subscribe { - if (!it.matches(TConfig.lockUUID)) return@subscribe - val inventory = MC.handledScreen ?: return@subscribe - inventory as AccessorHandledScreen - - val slot = inventory.focusedSlot_Firmament ?: return@subscribe - val stack = slot.stack ?: return@subscribe - val uuid = stack.skyblockUUID ?: return@subscribe - val lockedUUIDs = lockedUUIDs ?: return@subscribe - if (uuid in lockedUUIDs) { - lockedUUIDs.remove(uuid) - } else { - lockedUUIDs.add(uuid) - } - DConfig.markDirty() - CommonSoundEffects.playSuccess() + if (anyBlocked) { + event.protectSilent() } - IsSlotProtectedEvent.subscribe { - if (it.slot != null && it.slot.inventory is PlayerInventory && it.slot.index in (lockedSlots ?: setOf())) { - it.protect() - } + } + + @Subscribe + fun onProtectUuidItems(event: IsSlotProtectedEvent) { + val doesNotDeleteItem = event.actionType == SlotActionType.SWAP + || event.actionType == SlotActionType.PICKUP + || event.actionType == SlotActionType.QUICK_MOVE + || event.actionType == SlotActionType.QUICK_CRAFT + || event.actionType == SlotActionType.CLONE + || event.actionType == SlotActionType.PICKUP_ALL + val isSellOrTradeScreen = + isNpcShop(MC.handledScreen) || isTradeScreen(MC.handledScreen) || isSalvageScreen(MC.handledScreen) + if (!isSellOrTradeScreen && doesNotDeleteItem) return + val stack = event.itemStack ?: return + val uuid = stack.skyblockUUID ?: return + if (uuid in (lockedUUIDs ?: return)) { + event.protect() } - IsSlotProtectedEvent.subscribe { event -> - val doesNotDeleteItem = event.actionType == SlotActionType.SWAP - || event.actionType == SlotActionType.PICKUP - || event.actionType == SlotActionType.QUICK_MOVE - || event.actionType == SlotActionType.QUICK_CRAFT - || event.actionType == SlotActionType.CLONE - || event.actionType == SlotActionType.PICKUP_ALL - val isSellOrTradeScreen = - isNpcShop(MC.handledScreen) || isTradeScreen(MC.handledScreen) || isSalvageScreen(MC.handledScreen) - if (!isSellOrTradeScreen && doesNotDeleteItem) return@subscribe - val stack = event.itemStack ?: return@subscribe - val uuid = stack.skyblockUUID ?: return@subscribe - if (uuid in (lockedUUIDs ?: return@subscribe)) { - event.protect() - } + } + + @Subscribe + fun onProtectSlot(it: IsSlotProtectedEvent) { + if (it.slot != null && it.slot.inventory is PlayerInventory && it.slot.index in (lockedSlots ?: setOf())) { + it.protect() } - IsSlotProtectedEvent.subscribe { event -> - if (event.slot == null) return@subscribe - if (!event.slot.hasStack()) return@subscribe - if (event.slot.stack.displayNameAccordingToNbt?.unformattedString != "Salvage Items") return@subscribe - val inv = event.slot.inventory - var anyBlocked = false - for (i in 0 until event.slot.index) { - val stack = inv.getStack(i) - if (IsSlotProtectedEvent.shouldBlockInteraction(null, SlotActionType.THROW, stack)) - anyBlocked = true - } - if (anyBlocked) { - event.protectSilent() + } + + @Subscribe + fun onLockUUID(it: HandledScreenKeyPressedEvent) { + if (!it.matches(TConfig.lockUUID)) return + val inventory = MC.handledScreen ?: return + inventory as AccessorHandledScreen + + val slot = inventory.focusedSlot_Firmament ?: return + val stack = slot.stack ?: return + val uuid = stack.skyblockUUID ?: return + val lockedUUIDs = lockedUUIDs ?: return + if (uuid in lockedUUIDs) { + lockedUUIDs.remove(uuid) + } else { + lockedUUIDs.add(uuid) + } + DConfig.markDirty() + CommonSoundEffects.playSuccess() + it.cancel() + } + + @Subscribe + fun onLockSlot(it: HandledScreenKeyPressedEvent) { + if (!it.matches(TConfig.lockSlot)) return + val inventory = MC.handledScreen ?: return + inventory as AccessorHandledScreen + + val slot = inventory.focusedSlot_Firmament ?: return + val lockedSlots = lockedSlots ?: return + if (slot.inventory is PlayerInventory) { + if (slot.index in lockedSlots) { + lockedSlots.remove(slot.index) + } else { + lockedSlots.add(slot.index) } + DConfig.markDirty() + CommonSoundEffects.playSuccess() } } @Subscribe - fun function(it: SlotRenderEvents.After) { + fun onRenderSlotOverlay(it: SlotRenderEvents.After) { val isSlotLocked = it.slot.inventory is PlayerInventory && it.slot.index in (lockedSlots ?: setOf()) val isUUIDLocked = (it.slot.stack?.skyblockUUID) in (lockedUUIDs ?: setOf()) if (isSlotLocked || isUUIDLocked) { diff --git a/src/main/kotlin/moe/nea/firmament/features/inventory/buttons/InventoryButtons.kt b/src/main/kotlin/moe/nea/firmament/features/inventory/buttons/InventoryButtons.kt index 1fe222d..a6dbb5f 100644 --- a/src/main/kotlin/moe/nea/firmament/features/inventory/buttons/InventoryButtons.kt +++ b/src/main/kotlin/moe/nea/firmament/features/inventory/buttons/InventoryButtons.kt @@ -9,6 +9,7 @@ package moe.nea.firmament.features.inventory.buttons import me.shedaniel.math.Rectangle import kotlinx.serialization.Serializable import kotlinx.serialization.serializer +import moe.nea.firmament.annotations.Subscribe import moe.nea.firmament.events.HandledScreenClickEvent import moe.nea.firmament.events.HandledScreenForegroundEvent import moe.nea.firmament.events.HandledScreenPushREIEvent @@ -28,6 +29,7 @@ object InventoryButtons : FirmamentFeature { openEditor() } } + object DConfig : DataHolder(serializer(), identifier, ::Data) @Serializable @@ -40,35 +42,39 @@ object InventoryButtons : FirmamentFeature { get() = TConfig fun getValidButtons() = DConfig.data.buttons.asSequence().filter { it.isValid() } - override fun onLoad() { - HandledScreenForegroundEvent.subscribe { - val bounds = it.screen.getRectangle() - for (button in getValidButtons()) { - val buttonBounds = button.getBounds(bounds) - it.context.matrices.push() - it.context.matrices.translate(buttonBounds.minX.toFloat(), buttonBounds.minY.toFloat(), 0F) - button.render(it.context) - it.context.matrices.pop() - } - lastRectangle = bounds + + @Subscribe + fun onRectangles(it: HandledScreenPushREIEvent) { + val bounds = it.screen.getRectangle() + for (button in getValidButtons()) { + val buttonBounds = button.getBounds(bounds) + it.block(buttonBounds) } - HandledScreenClickEvent.subscribe { - val bounds = it.screen.getRectangle() - for (button in getValidButtons()) { - val buttonBounds = button.getBounds(bounds) - if (buttonBounds.contains(it.mouseX, it.mouseY)) { - MC.sendCommand(button.command!! /* non null invariant covered by getValidButtons */) - break - } + } + + @Subscribe + fun onClickScreen(it: HandledScreenClickEvent) { + val bounds = it.screen.getRectangle() + for (button in getValidButtons()) { + val buttonBounds = button.getBounds(bounds) + if (buttonBounds.contains(it.mouseX, it.mouseY)) { + MC.sendCommand(button.command!! /* non null invariant covered by getValidButtons */) + break } } - HandledScreenPushREIEvent.subscribe { - val bounds = it.screen.getRectangle() - for (button in getValidButtons()) { - val buttonBounds = button.getBounds(bounds) - it.block(buttonBounds) - } + } + + @Subscribe + fun onRenderForeground(it: HandledScreenForegroundEvent) { + val bounds = it.screen.getRectangle() + for (button in getValidButtons()) { + val buttonBounds = button.getBounds(bounds) + it.context.matrices.push() + it.context.matrices.translate(buttonBounds.minX.toFloat(), buttonBounds.minY.toFloat(), 0F) + button.render(it.context) + it.context.matrices.pop() } + lastRectangle = bounds } var lastRectangle: Rectangle? = null diff --git a/src/main/kotlin/moe/nea/firmament/features/inventory/storageoverlay/StorageOverlay.kt b/src/main/kotlin/moe/nea/firmament/features/inventory/storageoverlay/StorageOverlay.kt index b0ebea6..0426e34 100644 --- a/src/main/kotlin/moe/nea/firmament/features/inventory/storageoverlay/StorageOverlay.kt +++ b/src/main/kotlin/moe/nea/firmament/features/inventory/storageoverlay/StorageOverlay.kt @@ -6,9 +6,10 @@ package moe.nea.firmament.features.inventory.storageoverlay -import java.util.* +import java.util.SortedMap import kotlinx.serialization.serializer import net.minecraft.client.gui.screen.Screen +import moe.nea.firmament.annotations.Subscribe import moe.nea.firmament.events.ScreenChangeEvent import moe.nea.firmament.events.TickEvent import moe.nea.firmament.features.FirmamentFeature @@ -40,31 +41,33 @@ object StorageOverlay : FirmamentFeature { var shouldReturnToStorageOverlay: Screen? = null var currentHandler: StorageBackingHandle? = StorageBackingHandle.None - override fun onLoad() { - ScreenChangeEvent.subscribe { - if (lastStorageOverlay != null && it.new != null) { - shouldReturnToStorageOverlay = lastStorageOverlay - shouldReturnToStorageOverlayFrom = it.new - lastStorageOverlay = null - } else if (it.old === shouldReturnToStorageOverlayFrom) { - if (shouldReturnToStorageOverlay != null && it.new == null) - setScreenLater(shouldReturnToStorageOverlay) - shouldReturnToStorageOverlay = null - shouldReturnToStorageOverlayFrom = null - } - } + @Subscribe + fun onTick(event: TickEvent) { + rememberContent(currentHandler ?: return) + } - ScreenChangeEvent.subscribe { event -> - currentHandler = StorageBackingHandle.fromScreen(event.new) - if (event.old is StorageOverlayScreen && !event.old.isClosing) { - event.old.setHandler(currentHandler) - if (currentHandler != null) - // TODO: Consider instead only replacing rendering? might make a lot of stack handling easier - event.cancel() - } + @Subscribe + fun onScreenChangeLegacy(event: ScreenChangeEvent) { + currentHandler = StorageBackingHandle.fromScreen(event.new) + if (event.old is StorageOverlayScreen && !event.old.isClosing) { + event.old.setHandler(currentHandler) + if (currentHandler != null) + // TODO: Consider instead only replacing rendering? might make a lot of stack handling easier + event.cancel() } - TickEvent.subscribe { - rememberContent(currentHandler ?: return@subscribe) + } + + @Subscribe + fun onScreenChange(it: ScreenChangeEvent) { + if (lastStorageOverlay != null && it.new != null) { + shouldReturnToStorageOverlay = lastStorageOverlay + shouldReturnToStorageOverlayFrom = it.new + lastStorageOverlay = null + } else if (it.old === shouldReturnToStorageOverlayFrom) { + if (shouldReturnToStorageOverlay != null && it.new == null) + setScreenLater(shouldReturnToStorageOverlay) + shouldReturnToStorageOverlay = null + shouldReturnToStorageOverlayFrom = null } } diff --git a/src/main/kotlin/moe/nea/firmament/features/mining/PickaxeAbility.kt b/src/main/kotlin/moe/nea/firmament/features/mining/PickaxeAbility.kt index 956ffc3..8e62172 100644 --- a/src/main/kotlin/moe/nea/firmament/features/mining/PickaxeAbility.kt +++ b/src/main/kotlin/moe/nea/firmament/features/mining/PickaxeAbility.kt @@ -13,6 +13,7 @@ import net.minecraft.item.ItemStack import net.minecraft.util.DyeColor import net.minecraft.util.Hand import net.minecraft.util.Identifier +import moe.nea.firmament.annotations.Subscribe import moe.nea.firmament.events.HudRenderEvent import moe.nea.firmament.events.ProcessChatEvent import moe.nea.firmament.events.SlotClickEvent @@ -73,53 +74,57 @@ object PickaxeAbility : FirmamentFeature { return 1.0 } - override fun onLoad() { - HudRenderEvent.subscribe(this::renderHud) - WorldReadyEvent.subscribe { - lastUsage.clear() - lobbyJoinTime = TimeMark.now() - abilityOverride = null - } - ProcessChatEvent.subscribe { - abilityUsePattern.useMatch(it.unformattedString) { - lastUsage[group("name")] = TimeMark.now() - } - abilitySwitchPattern.useMatch(it.unformattedString) { - abilityOverride = group("ability") - } - } - DurabilityBarEvent.subscribe { - if (!TConfig.drillFuelBar) return@subscribe - val lore = it.item.loreAccordingToNbt - if (lore.lastOrNull()?.unformattedString?.contains("DRILL") != true) return@subscribe - val maxFuel = lore.firstNotNullOfOrNull { - fuelPattern.useMatch(it.unformattedString) { - parseShortNumber(group("maxFuel")) + @Subscribe + fun onSlotClick(it: SlotClickEvent) { + if (MC.screen?.title?.unformattedString == "Heart of the Mountain") { + val name = it.stack.displayNameAccordingToNbt?.unformattedString ?: return + val cooldown = it.stack.loreAccordingToNbt.firstNotNullOfOrNull { + cooldownPattern.useMatch(it.unformattedString) { + parseTimePattern(group("cooldown")) } - } ?: return@subscribe - val extra = it.item.extraAttributes - if (!extra.contains("drill_fuel")) return@subscribe - val fuel = extra.getInt