aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/moe/nea/firmament
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/kotlin/moe/nea/firmament')
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/subscription/Subscription.kt5
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/FirmamentFeature.kt4
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/chat/AutoCompletions.kt43
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/chat/ChatLinks.kt131
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/chat/QuickCommands.kt48
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/debug/DeveloperFeatures.kt4
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/debug/MinorTrolling.kt18
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/debug/PowerUserTools.kt175
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/diana/AncestralSpadeSolver.kt13
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/diana/DianaWaypoints.kt11
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/diana/NearbyBurrowsSolver.kt12
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/fixes/CompatibliltyFeatures.kt18
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/fixes/Fixes.kt44
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/inventory/CraftingOverlay.kt62
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/inventory/ItemRarityCosmetics.kt25
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/inventory/PriceData.kt5
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/inventory/SaveCursorPosition.kt4
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/inventory/SlotLocking.kt143
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/inventory/buttons/InventoryButtons.kt56
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/inventory/storageoverlay/StorageOverlay.kt51
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/mining/PickaxeAbility.kt94
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/mining/PristineProfitTracker.kt32
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/texturepack/CustomSkyBlockTextures.kt24
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/world/FairySouls.kt87
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/world/Waypoints.kt334
25 files changed, 745 insertions, 698 deletions
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<T : FirmamentEvent>(
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() ?: "<empty>"
- 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() ?: "<empty>"
+ 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<Float>()
@@ -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<BlockPos, TimeMark> = mutableMapWithMaxSize(20)
@@ -32,6 +35,7 @@ object NearbyBurrowsSolver {
val burrows = mutableMapOf<BlockPos, BurrowType>()
+ @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<Double, Double>? = 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<Data>(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("drill_fuel")
- val percentage = fuel / maxFuel.toFloat()
- it.barOverride = DurabilityBarEvent.DurabilityBar(
- lerp(
- DyeColor.RED.toShedaniel(),
- DyeColor.GREEN.toShedaniel(),
- percentage
- ), percentage
- )
+ } ?: return
+ defaultAbilityDurations[name] = cooldown
}
- SlotClickEvent.subscribe {
- if (MC.screen?.title?.unformattedString == "Heart of the Mountain") {
- val name = it.stack.displayNameAccordingToNbt?.unformattedString ?: return@subscribe
- val cooldown = it.stack.loreAccordingToNbt.firstNotNullOfOrNull {
- cooldownPattern.useMatch(it.unformattedString) {
- parseTimePattern(group("cooldown"))
- }
- } ?: return@subscribe
- defaultAbilityDurations[name] = cooldown
+ }
+
+ @Subscribe
+ fun onDurabilityBar(it: DurabilityBarEvent) {
+ if (!TConfig.drillFuelBar) return
+ val lore = it.item.loreAccordingToNbt
+ if (lore.lastOrNull()?.unformattedString?.contains("DRILL") != true) return
+ val maxFuel = lore.firstNotNullOfOrNull {
+ fuelPattern.useMatch(it.unformattedString) {
+ parseShortNumber(group("maxFuel"))
}
+ } ?: return
+ val extra = it.item.extraAttributes
+ if (!extra.contains("drill_fuel")) return
+ val fuel = extra.getInt("drill_fuel")
+ val percentage = fuel / maxFuel.toFloat()
+ it.barOverride = DurabilityBarEvent.DurabilityBar(
+ lerp(
+ DyeColor.RED.toShedaniel(),
+ DyeColor.GREEN.toShedaniel(),
+ percentage
+ ), percentage
+ )
+ }
+
+ @Subscribe
+ fun onChatMessage(it: ProcessChatEvent) {
+ abilityUsePattern.useMatch(it.unformattedString) {
+ lastUsage[group("name")] = TimeMark.now()
}
+ abilitySwitchPattern.useMatch(it.unformattedString) {
+ abilityOverride = group("ability")
+ }
+ }
+
+ @Subscribe
+ fun onWorldReady(event: WorldReadyEvent) {
+ lastUsage.clear()
+ lobbyJoinTime = TimeMark.now()
+ abilityOverride = null
}
val abilityUsePattern = Pattern.compile("You used your (?<name>.*) Pickaxe Ability!")
@@ -154,7 +159,8 @@ object PickaxeAbility : FirmamentFeature {
Pattern.compile("You selected (?<ability>.*) as your Pickaxe Ability\\. This ability will apply to all of your pickaxes!")
- private fun renderHud(event: HudRenderEvent) {
+ @Subscribe
+ fun renderHud(event: HudRenderEvent) {
if (!TConfig.cooldownEnabled) return
var ability = getCooldownFromLore(MC.player?.getStackInHand(Hand.MAIN_HAND) ?: return) ?: return
defaultAbilityDurations[ability.name] = ability.cooldown
diff --git a/src/main/kotlin/moe/nea/firmament/features/mining/PristineProfitTracker.kt b/src/main/kotlin/moe/nea/firmament/features/mining/PristineProfitTracker.kt
index 89ef264..1597501 100644
--- a/src/main/kotlin/moe/nea/firmament/features/mining/PristineProfitTracker.kt
+++ b/src/main/kotlin/moe/nea/firmament/features/mining/PristineProfitTracker.kt
@@ -12,6 +12,7 @@ import kotlinx.serialization.Serializable
import kotlinx.serialization.serializer
import kotlin.time.Duration.Companion.seconds
import net.minecraft.text.Text
+import moe.nea.firmament.annotations.Subscribe
import moe.nea.firmament.events.ProcessChatEvent
import moe.nea.firmament.features.FirmamentFeature
import moe.nea.firmament.gui.config.ManagedConfig
@@ -62,7 +63,7 @@ object PristineProfitTracker : FirmamentFeature {
val pristineRegex =
"PRISTINE! You found . Flawed (?<kind>${
- GemstoneKind.values().joinToString("|") { it.label }
+ GemstoneKind.entries.joinToString("|") { it.label }
}) Gemstone x(?<count>[0-9,]+)!".toPattern()
val collectionHistogram = Histogram<Double>(10000, 180.seconds)
@@ -97,9 +98,13 @@ object PristineProfitTracker : FirmamentFeature {
val moneyPerSecond = moneyHistogram.averagePer({ it }, 1.seconds)
if (collectionPerSecond == null || moneyPerSecond == null) return
ProfitHud.collectionCurrent = collectionPerSecond
- ProfitHud.collectionText = Text.stringifiedTranslatable("firmament.pristine-profit.collection", formatCurrency(collectionPerSecond * SECONDS_PER_HOUR, 1)).formattedString()
+ ProfitHud.collectionText = Text.stringifiedTranslatable("firmament.pristine-profit.collection",
+ formatCurrency(collectionPerSecond * SECONDS_PER_HOUR,
+ 1)).formattedString()
ProfitHud.moneyCurrent = moneyPerSecond
- ProfitHud.moneyText = Text.stringifiedTranslatable("firmament.pristine-profit.money", formatCurrency(moneyPerSecond * SECONDS_PER_HOUR, 1)).formattedString()
+ ProfitHud.moneyText = Text.stringifiedTranslatable("firmament.pristine-profit.money",
+ formatCurrency(moneyPerSecond * SECONDS_PER_HOUR, 1))
+ .formattedString()
val data = DConfig.data
if (data != null) {
if (data.maxCollectionPerSecond < collectionPerSecond && collectionHistogram.oldestUpdate()
@@ -118,17 +123,16 @@ object PristineProfitTracker : FirmamentFeature {
}
- override fun onLoad() {
- ProcessChatEvent.subscribe {
- pristineRegex.useMatch(it.unformattedString) {
- val gemstoneKind = GemstoneKind.valueOf(group("kind").uppercase())
- val flawedCount = parseIntWithComma(group("count"))
- val moneyAmount = sellingStrategy.getSellPrice(gemstoneKind.flawedId) * flawedCount
- moneyHistogram.record(moneyAmount)
- val collectionAmount = flawedCount * ROUGHS_PER_FLAWED
- collectionHistogram.record(collectionAmount.toDouble())
- updateUi()
- }
+ @Subscribe
+ fun onMessage(it: ProcessChatEvent) {
+ pristineRegex.useMatch(it.unformattedString) {
+ val gemstoneKind = GemstoneKind.valueOf(group("kind").uppercase())
+ val flawedCount = parseIntWithComma(group("count"))
+ val moneyAmount = sellingStrategy.getSellPrice(gemstoneKind.flawedId) * flawedCount
+ moneyHistogram.record(moneyAmount)
+ val collectionAmount = flawedCount * ROUGHS_PER_FLAWED
+ collectionHistogram.record(collectionAmount.toDouble())
+ updateUi()
}
}
}
diff --git a/src/main/kotlin/moe/nea/firmament/features/texturepack/CustomSkyBlockTextures.kt b/src/main/kotlin/moe/nea/firmament/features/texturepack/CustomSkyBlockTextures.kt
index 9c2eafc..e66a24a 100644
--- a/src/main/kotlin/moe/nea/firmament/features/texturepack/CustomSkyBlockTextures.kt
+++ b/src/main/kotlin/moe/nea/firmament/features/texturepack/CustomSkyBlockTextures.kt
@@ -16,6 +16,7 @@ import net.minecraft.client.render.RenderLayer
import net.minecraft.client.util.ModelIdentifier
import net.minecraft.component.type.ProfileComponent
import net.minecraft.util.Identifier
+import moe.nea.firmament.annotations.Subscribe
import moe.nea.firmament.events.CustomItemModelEvent
import moe.nea.firmament.events.TickEvent
import moe.nea.firmament.features.FirmamentFeature
@@ -38,20 +39,21 @@ object CustomSkyBlockTextures : FirmamentFeature {
override val config: ManagedConfig
get() = TConfig
- override fun onLoad() {
- CustomItemModelEvent.subscribe {
- if (!TConfig.enabled) return@subscribe
- val id = it.itemStack.skyBlockId ?: return@subscribe
- it.overrideModel = ModelIdentifier("firmskyblock", id.identifier.path, "inventory")
- }
- TickEvent.subscribe {
- if (TConfig.cacheDuration < 1 || it.tickCount % TConfig.cacheDuration == 0) {
- CustomItemModelEvent.clearCache()
- skullTextureCache.clear()
- }
+ @Subscribe
+ fun onTick(it: TickEvent) {
+ if (TConfig.cacheDuration < 1 || it.tickCount % TConfig.cacheDuration == 0) {
+ CustomItemModelEvent.clearCache()
+ skullTextureCache.clear()
}
}
+ @Subscribe
+ fun onCustomModelId(it: CustomItemModelEvent) {
+ if (!TConfig.enabled) return
+ val id = it.itemStack.skyBlockId ?: return
+ it.overrideModel = ModelIdentifier("firmskyblock", id.identifier.path, "inventory")
+ }
+
private val skullTextureCache = mutableMapOf<IdentityCharacteristics<ProfileComponent>, Any>()
private val sentinelPresentInvalid = Object()
diff --git a/src/main/kotlin/moe/nea/firmament/features/world/FairySouls.kt b/src/main/kotlin/moe/nea/firmament/features/world/FairySouls.kt
index 462325e..2cce041 100644
--- a/src/main/kotlin/moe/nea/firmament/features/world/FairySouls.kt
+++ b/src/main/kotlin/moe/nea/firmament/features/world/FairySouls.kt
@@ -9,15 +9,10 @@ package moe.nea.firmament.features.world
import io.github.moulberry.repo.data.Coordinate
import kotlinx.serialization.Serializable
import kotlinx.serialization.serializer
-import net.minecraft.client.render.RenderLayer
-import net.minecraft.client.render.RenderLayer.ALWAYS_DEPTH_TEST
-import net.minecraft.client.render.RenderLayer.MultiPhaseParameters
-import net.minecraft.client.render.RenderPhase
-import net.minecraft.client.render.VertexFormat
-import net.minecraft.client.render.VertexFormats
import net.minecraft.text.Text
import net.minecraft.util.math.Vec3d
-import moe.nea.firmament.events.AllowChatEvent
+import moe.nea.firmament.annotations.Subscribe
+import moe.nea.firmament.events.ProcessChatEvent
import moe.nea.firmament.events.SkyblockServerUpdateEvent
import moe.nea.firmament.events.WorldRenderLastEvent
import moe.nea.firmament.features.FirmamentFeature
@@ -102,53 +97,43 @@ object FairySouls : FirmamentFeature {
updateMissingSouls()
}
- val NODEPTH: RenderLayer = RenderLayer.of(
- "firmamentnodepth",
- VertexFormats.POSITION_COLOR_TEXTURE,
- VertexFormat.DrawMode.QUADS,
- 256,
- true,
- true,
- MultiPhaseParameters.builder()
- .program(RenderPhase.COLOR_PROGRAM)
- .writeMaskState(RenderPhase.COLOR_MASK)
- .depthTest(ALWAYS_DEPTH_TEST)
- .cull(RenderPhase.DISABLE_CULLING)
- .layering(RenderLayer.VIEW_OFFSET_Z_LAYERING)
- .target(RenderPhase.MAIN_TARGET)
- .build(true)
- )
-
- override fun onLoad() {
- SkyblockServerUpdateEvent.subscribe {
- currentLocationName = it.newLocraw?.skyblockLocation
- updateWorldSouls()
- updateMissingSouls()
- }
- AllowChatEvent.subscribe {
- when (it.text.unformattedString) {
- "You have already found that Fairy Soul!" -> {
- markNearestSoul()
- }
-
- "SOUL! You found a Fairy Soul!" -> {
- markNearestSoul()
- }
+ @Subscribe
+ fun onWorldRender(it: WorldRenderLastEvent) {
+ if (!TConfig.displaySouls) return
+ renderInWorld(it) {
+ text(Vec3d(0.0, 0.0, 0.0),
+ Text.literal("Test String"),
+ Text.literal("Short"),
+ Text.literal("just lik"),
+ verticalAlign = RenderInWorldContext.VerticalAlign.BOTTOM)
+ color(1F, 1F, 0F, 0.8F)
+ currentMissingSouls.forEach {
+ block(it.blockPos)
+ }
+ color(1f, 0f, 1f, 1f)
+ currentLocationSouls.forEach {
+ wireframeCube(it.blockPos)
}
}
- WorldRenderLastEvent.subscribe {
- if (!TConfig.displaySouls) return@subscribe
- renderInWorld(it) {
- text(Vec3d(0.0, 0.0, 0.0), Text.literal("Test String") , Text.literal("Short"), Text.literal("just lik"), verticalAlign = RenderInWorldContext.VerticalAlign.BOTTOM)
- color(1F, 1F, 0F, 0.8F)
- currentMissingSouls.forEach {
- block(it.blockPos)
- }
- color(1f, 0f, 1f, 1f)
- currentLocationSouls.forEach {
- wireframeCube(it.blockPos)
- }
+ }
+
+ @Subscribe
+ fun onProcessChat(it: ProcessChatEvent) {
+ when (it.text.unformattedString) {
+ "You have already found that Fairy Soul!" -> {
+ markNearestSoul()
+ }
+
+ "SOUL! You found a Fairy Soul!" -> {
+ markNearestSoul()
}
}
}
+
+ @Subscribe
+ fun onLocationChange(it: SkyblockServerUpdateEvent) {
+ currentLocationName = it.newLocraw?.skyblockLocation
+ updateWorldSouls()
+ updateMissingSouls()
+ }
}
diff --git a/src/main/kotlin/moe/nea/firmament/features/world/Waypoints.kt b/src/main/kotlin/moe/nea/firmament/features/world/Waypoints.kt
index bad82b0..dcb3014 100644
--- a/src/main/kotlin/moe/nea/firmament/features/world/Waypoints.kt
+++ b/src/main/kotlin/moe/nea/firmament/features/world/Waypoints.kt
@@ -22,6 +22,7 @@ import net.minecraft.text.Text
import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.Vec3d
import moe.nea.firmament.Firmament
+import moe.nea.firmament.annotations.Subscribe
import moe.nea.firmament.commands.get
import moe.nea.firmament.commands.thenArgument
import moe.nea.firmament.commands.thenExecute
@@ -73,195 +74,204 @@ object Waypoints : FirmamentFeature {
val b: Int = 0,
)
- override fun onLoad() {
- WorldRenderLastEvent.subscribe { event ->
- temporaryPlayerWaypointList.entries.removeIf { it.value.postedAt.passedTime() > TConfig.tempWaypointDuration }
- if (temporaryPlayerWaypointList.isNotEmpty())
- RenderInWorldContext.renderInWorld(event) {
- color(1f, 1f, 0f, 1f)
- temporaryPlayerWaypointList.forEach { (player, waypoint) ->
- block(waypoint.pos)
- }
+ @Subscribe
+ fun onRenderOrderedWaypoints(event: WorldRenderLastEvent) {
+ if (waypoints.isEmpty()) return
+ RenderInWorldContext.renderInWorld(event) {
+ if (!ordered) {
+ waypoints.withIndex().forEach {
+ color(0f, 0.3f, 0.7f, 0.5f)
+ block(it.value)
color(1f, 1f, 1f, 1f)
- temporaryPlayerWaypointList.forEach { (player, waypoint) ->
- val skin =
- MC.networkHandler?.listedPlayerListEntries?.find { it.profile.name == player }
- ?.skinTextures
- ?.texture
- withFacingThePlayer(waypoint.pos.toCenterPos()) {
- waypoint(waypoint.pos, Text.stringifiedTranslatable("firmament.waypoint.temporary", player))
- if (skin != null) {
- matrixStack.translate(0F, -20F, 0F)
- // Head front
- texture(
- skin, 16, 16,
- 1 / 8f, 1 / 8f,
- 2 / 8f, 2 / 8f,
- )
- // Head overlay
- texture(
- skin, 16, 16,
- 5 / 8f, 1 / 8f,
- 6 / 8f, 2 / 8f,
- )
- }
+ if (TConfig.showIndex)
+ withFacingThePlayer(it.value.toCenterPos()) {
+ text(Text.literal(it.index.toString()))
}
- }
}
+ } else {
+ orderedIndex %= waypoints.size
+ val firstColor = Color.ofRGBA(0, 200, 40, 180)
+ color(firstColor)
+ tracer(waypoints[orderedIndex].toCenterPos(), lineWidth = 3f)
+ waypoints.withIndex().toList()
+ .wrappingWindow(orderedIndex, 3)
+ .zip(
+ listOf(
+ firstColor,
+ Color.ofRGBA(180, 200, 40, 150),
+ Color.ofRGBA(180, 80, 20, 140),
+ )
+ )
+ .reversed()
+ .forEach { (waypoint, col) ->
+ val (index, pos) = waypoint
+ color(col)
+ block(pos)
+ color(1f, 1f, 1f, 1f)
+ if (TConfig.showIndex)
+ withFacingThePlayer(pos.toCenterPos()) {
+ text(Text.literal(index.toString()))
+ }
+ }
+ }
}
- WorldReadyEvent.subscribe {
- temporaryPlayerWaypointList.clear()
+ }
+
+ @Subscribe
+ fun onTick(event: TickEvent) {
+ if (waypoints.isEmpty() || !ordered) return
+ orderedIndex %= waypoints.size
+ val p = MC.player?.pos ?: return
+ if (TConfig.skipToNearest) {
+ orderedIndex =
+ (waypoints.withIndex().minBy { it.value.getSquaredDistance(p) }.index + 1) % waypoints.size
+ } else {
+ if (waypoints[orderedIndex].isWithinDistance(p, 3.0)) {
+ orderedIndex = (orderedIndex + 1) % waypoints.size
+ }
}
- CommandEvent.SubCommand.subscribe { event ->
- event.subcommand("waypoint") {
- thenArgument("pos", BlockPosArgumentType.blockPos()) { pos ->
- thenExecute {
- val position = pos.get(this).toAbsoluteBlockPos(source.asFakeServer())
- waypoints.add(position)
- source.sendFeedback(
- Text.stringifiedTranslatable(
- "firmament.command.waypoint.added",
- position.x,
- position.y,
- position.z
- )
+ }
+
+ @Subscribe
+ fun onProcessChat(it: ProcessChatEvent) {
+ val matcher = temporaryPlayerWaypointMatcher.matcher(it.unformattedString)
+ if (it.nameHeuristic != null && TConfig.tempWaypointDuration > 0.seconds && matcher.find()) {
+ temporaryPlayerWaypointList[it.nameHeuristic] = TemporaryWaypoint(
+ BlockPos(
+ matcher.group(1).toInt(),
+ matcher.group(2).toInt(),
+ matcher.group(3).toInt(),
+ ),
+ TimeMark.now()
+ )
+ }
+ }
+
+ @Subscribe
+ fun onCommand(event: CommandEvent.SubCommand) {
+ event.subcommand("waypoint") {
+ thenArgument("pos", BlockPosArgumentType.blockPos()) { pos ->
+ thenExecute {
+ val position = pos.get(this).toAbsoluteBlockPos(source.asFakeServer())
+ waypoints.add(position)
+ source.sendFeedback(
+ Text.stringifiedTranslatable(
+ "firmament.command.waypoint.added",
+ position.x,
+ position.y,
+ position.z
)
- }
+ )
}
}
- event.subcommand("waypoints") {
- thenLiteral("clear") {
- thenExecute {
- waypoints.clear()
- source.sendFeedback(Text.translatable("firmament.command.waypoint.clear"))
- }
- }
- thenLiteral("toggleordered") {
- thenExecute {
- ordered = !ordered
- if (ordered) {
- val p = MC.player?.pos ?: Vec3d.ZERO
- orderedIndex =
- waypoints.withIndex().minByOrNull { it.value.getSquaredDistance(p) }?.index ?: 0
- }
- source.sendFeedback(Text.translatable("firmament.command.waypoint.ordered.toggle.$ordered"))
- }
+ }
+ event.subcommand("waypoints") {
+ thenLiteral("clear") {
+ thenExecute {
+ waypoints.clear()
+ source.sendFeedback(Text.translatable("firmament.command.waypoint.clear"))
}
- thenLiteral("skip") {
- thenExecute {
- if (ordered && waypoints.isNotEmpty()) {
- orderedIndex = (orderedIndex + 1) % waypoints.size
- source.sendFeedback(Text.translatable("firmament.command.waypoint.skip"))
- } else {
- source.sendError(Text.translatable("firmament.command.waypoint.skip.error"))
- }
+ }
+ thenLiteral("toggleordered") {
+ thenExecute {
+ ordered = !ordered
+ if (ordered) {
+ val p = MC.player?.pos ?: Vec3d.ZERO
+ orderedIndex =
+ waypoints.withIndex().minByOrNull { it.value.getSquaredDistance(p) }?.index ?: 0
}
+ source.sendFeedback(Text.translatable("firmament.command.waypoint.ordered.toggle.$ordered"))
}
- thenLiteral("remove") {
- thenArgument("index", IntegerArgumentType.integer(0)) { indexArg ->
- thenExecute {
- val index = get(indexArg)
- if (index in waypoints.indices) {
- waypoints.removeAt(index)
- source.sendFeedback(Text.stringifiedTranslatable(
- "firmament.command.waypoint.remove",
- index))
- } else {
- source.sendError(Text.stringifiedTranslatable("firmament.command.waypoint.remove.error"))
- }
- }
+ }
+ thenLiteral("skip") {
+ thenExecute {
+ if (ordered && waypoints.isNotEmpty()) {
+ orderedIndex = (orderedIndex + 1) % waypoints.size
+ source.sendFeedback(Text.translatable("firmament.command.waypoint.skip"))
+ } else {
+ source.sendError(Text.translatable("firmament.command.waypoint.skip.error"))
}
}
- thenLiteral("import") {
+ }
+ thenLiteral("remove") {
+ thenArgument("index", IntegerArgumentType.integer(0)) { indexArg ->
thenExecute {
- val contents = ClipboardUtils.getTextContents()
- val data = try {
- Firmament.json.decodeFromString<List<ColeWeightWaypoint>>(contents)
- } catch (ex: Exception) {
- Firmament.logger.error("Could not load waypoints from clipboard", ex)
- source.sendError(Text.translatable("firmament.command.waypoint.import.error"))
- return@thenExecute
+ val index = get(indexArg)
+ if (index in waypoints.indices) {
+ waypoints.removeAt(index)
+ source.sendFeedback(Text.stringifiedTranslatable(
+ "firmament.command.waypoint.remove",
+ index))
+ } else {
+ source.sendError(Text.stringifiedTranslatable("firmament.command.waypoint.remove.error"))
}
- waypoints.clear()
- data.mapTo(waypoints) { BlockPos(it.x, it.y, it.z) }
- source.sendFeedback(
- Text.stringifiedTranslatable(
- "firmament.command.waypoint.import",
- data.size
- )
- )
}
}
}
- }
- WorldRenderLastEvent.subscribe { event ->
- if (waypoints.isEmpty()) return@subscribe
- RenderInWorldContext.renderInWorld(event) {
- if (!ordered) {
- waypoints.withIndex().forEach {
- color(0f, 0.3f, 0.7f, 0.5f)
- block(it.value)
- color(1f, 1f, 1f, 1f)
- if (TConfig.showIndex)
- withFacingThePlayer(it.value.toCenterPos()) {
- text(Text.literal(it.index.toString()))
- }
+ thenLiteral("import") {
+ thenExecute {
+ val contents = ClipboardUtils.getTextContents()
+ val data = try {
+ Firmament.json.decodeFromString<List<ColeWeightWaypoint>>(contents)
+ } catch (ex: Exception) {
+ Firmament.logger.error("Could not load waypoints from clipboard", ex)
+ source.sendError(Text.translatable("firmament.command.waypoint.import.error"))
+ return@thenExecute
}
- } else {
- orderedIndex %= waypoints.size
- val firstColor = Color.ofRGBA(0, 200, 40, 180)
- color(firstColor)
- tracer(waypoints[orderedIndex].toCenterPos(), lineWidth = 3f)
- waypoints.withIndex().toList()
- .wrappingWindow(orderedIndex, 3)
- .zip(
- listOf(
- firstColor,
- Color.ofRGBA(180, 200, 40, 150),
- Color.ofRGBA(180, 80, 20, 140),
- )
+ waypoints.clear()
+ data.mapTo(waypoints) { BlockPos(it.x, it.y, it.z) }
+ source.sendFeedback(
+ Text.stringifiedTranslatable(
+ "firmament.command.waypoint.import",
+ data.size
)
- .reversed()
- .forEach { (waypoint, col) ->
- val (index, pos) = waypoint
- color(col)
- block(pos)
- color(1f, 1f, 1f, 1f)
- if (TConfig.showIndex)
- withFacingThePlayer(pos.toCenterPos()) {
- text(Text.literal(index.toString()))
- }
- }
+ )
}
}
}
- TickEvent.subscribe {
- if (waypoints.isEmpty() || !ordered) return@subscribe
- orderedIndex %= waypoints.size
- val p = MC.player?.pos ?: return@subscribe
- if (TConfig.skipToNearest) {
- orderedIndex =
- (waypoints.withIndex().minBy { it.value.getSquaredDistance(p) }.index + 1) % waypoints.size
- } else {
- if (waypoints[orderedIndex].isWithinDistance(p, 3.0)) {
- orderedIndex = (orderedIndex + 1) % waypoints.size
- }
+ }
+
+ @Subscribe
+ fun onRenderTemporaryWaypoints(event: WorldRenderLastEvent) {
+ temporaryPlayerWaypointList.entries.removeIf { it.value.postedAt.passedTime() > TConfig.tempWaypointDuration }
+ if (temporaryPlayerWaypointList.isEmpty()) return
+ RenderInWorldContext.renderInWorld(event) {
+ color(1f, 1f, 0f, 1f)
+ temporaryPlayerWaypointList.forEach { (player, waypoint) ->
+ block(waypoint.pos)
}
- }
- ProcessChatEvent.subscribe {
- val matcher = temporaryPlayerWaypointMatcher.matcher(it.unformattedString)
- if (it.nameHeuristic != null && TConfig.tempWaypointDuration > 0.seconds && matcher.find()) {
- temporaryPlayerWaypointList[it.nameHeuristic] = TemporaryWaypoint(
- BlockPos(
- matcher.group(1).toInt(),
- matcher.group(2).toInt(),
- matcher.group(3).toInt(),
- ),
- TimeMark.now()
- )
+ color(1f, 1f, 1f, 1f)
+ temporaryPlayerWaypointList.forEach { (player, waypoint) ->
+ val skin =
+ MC.networkHandler?.listedPlayerListEntries?.find { it.profile.name == player }
+ ?.skinTextures
+ ?.texture
+ withFacingThePlayer(waypoint.pos.toCenterPos()) {
+ waypoint(waypoint.pos, Text.stringifiedTranslatable("firmament.waypoint.temporary", player))
+ if (skin != null) {
+ matrixStack.translate(0F, -20F, 0F)
+ // Head front
+ texture(
+ skin, 16, 16,
+ 1 / 8f, 1 / 8f,
+ 2 / 8f, 2 / 8f,
+ )
+ // Head overlay
+ texture(
+ skin, 16, 16,
+ 5 / 8f, 1 / 8f,
+ 6 / 8f, 2 / 8f,
+ )
+ }
+ }
}
}
}
+
+ @Subscribe
+ fun onWorldReady(event: WorldReadyEvent) {
+ temporaryPlayerWaypointList.clear()
+ }
}
fun <E> List<E>.wrappingWindow(startIndex: Int, windowSize: Int): List<E> {