aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/features/debug/AnimatedClothingScanner.kt
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/kotlin/features/debug/AnimatedClothingScanner.kt')
-rw-r--r--src/main/kotlin/features/debug/AnimatedClothingScanner.kt183
1 files changed, 133 insertions, 50 deletions
diff --git a/src/main/kotlin/features/debug/AnimatedClothingScanner.kt b/src/main/kotlin/features/debug/AnimatedClothingScanner.kt
index 47da7d6..9f9f135 100644
--- a/src/main/kotlin/features/debug/AnimatedClothingScanner.kt
+++ b/src/main/kotlin/features/debug/AnimatedClothingScanner.kt
@@ -2,13 +2,12 @@ package moe.nea.firmament.features.debug
import net.minecraft.command.argument.RegistryKeyArgumentType
import net.minecraft.component.ComponentType
-import net.minecraft.component.DataComponentTypes
import net.minecraft.entity.Entity
+import net.minecraft.entity.decoration.ArmorStandEntity
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NbtElement
import net.minecraft.nbt.NbtOps
import net.minecraft.registry.RegistryKeys
-import net.minecraft.util.Identifier
import moe.nea.firmament.annotations.Subscribe
import moe.nea.firmament.commands.get
import moe.nea.firmament.commands.thenArgument
@@ -16,16 +15,17 @@ import moe.nea.firmament.commands.thenExecute
import moe.nea.firmament.commands.thenLiteral
import moe.nea.firmament.events.CommandEvent
import moe.nea.firmament.events.EntityUpdateEvent
+import moe.nea.firmament.events.WorldReadyEvent
import moe.nea.firmament.util.ClipboardUtils
import moe.nea.firmament.util.MC
+import moe.nea.firmament.util.math.GChainReconciliation
+import moe.nea.firmament.util.math.GChainReconciliation.shortenCycle
import moe.nea.firmament.util.mc.NbtPrism
-import moe.nea.firmament.util.skyBlockId
import moe.nea.firmament.util.tr
object AnimatedClothingScanner {
- data class SubjectOfFashionTheft<T>(
- val observedEntity: Entity,
+ data class LensOfFashionTheft<T>(
val prism: NbtPrism,
val component: ComponentType<T>,
) {
@@ -36,75 +36,158 @@ object AnimatedClothingScanner {
}
}
- var subject: SubjectOfFashionTheft<*>? = null
+ var lens: LensOfFashionTheft<*>? = null
+ var subject: Entity? = null
+ var history: MutableList<String> = mutableListOf()
+ val metaHistory: MutableList<List<String>> = mutableListOf()
@OptIn(ExperimentalStdlibApi::class)
@Subscribe
fun onUpdate(event: EntityUpdateEvent) {
val s = subject ?: return
- if (event.entity != s.observedEntity) return
+ if (event.entity != s) return
+ val l = lens ?: return
if (event is EntityUpdateEvent.EquipmentUpdate) {
- val lines = mutableListOf<String>()
event.newEquipment.forEach {
- val formatted = (s.observe(it.second)).joinToString()
- lines.add(formatted)
- MC.sendChat(
- tr(
- "firmament.fitstealer.update",
- "[FIT CHECK][${MC.currentTick}] ${it.first.asString()} => $formatted"
- )
- )
- }
- if (lines.isNotEmpty()) {
- val contents = ClipboardUtils.getTextContents()
- if (contents.startsWith(EXPORT_WATERMARK))
- ClipboardUtils.setTextContent(
- contents + "\n" + lines.joinToString("\n")
- )
+ val formatted = (l.observe(it.second)).joinToString()
+ history.add(formatted)
+ // TODO: add a slot filter
}
}
}
- val EXPORT_WATERMARK = "[CLOTHES EXPORT]"
+ fun reduceHistory(reducer: (List<String>, List<String>) -> List<String>): List<String> {
+ return metaHistory.fold(history, reducer).shortenCycle()
+ }
@Subscribe
fun onSubCommand(event: CommandEvent.SubCommand) {
event.subcommand("dev") {
thenLiteral("stealthisfit") {
- thenArgument(
- "component",
- RegistryKeyArgumentType.registryKey(RegistryKeys.DATA_COMPONENT_TYPE)
- ) { component ->
- thenArgument("path", NbtPrism.Argument) { path ->
+ thenLiteral("clear") {
+ thenExecute {
+ subject = null
+ metaHistory.clear()
+ history.clear()
+ MC.sendChat(tr("firmament.fitstealer.clear", "Cleared fit stealing history"))
+ }
+ }
+ thenLiteral("copy") {
+ thenExecute {
+ val history = reduceHistory { a, b -> a + b }
+ copyHistory(history)
+ MC.sendChat(tr("firmament.fitstealer.copied", "Copied the history"))
+ }
+ thenLiteral("deduplicated") {
thenExecute {
- subject =
- if (subject == null) run {
- val entity = MC.instance.targetedEntity ?: return@run null
- val clipboard = ClipboardUtils.getTextContents()
- if (!clipboard.startsWith(EXPORT_WATERMARK)) {
- ClipboardUtils.setTextContent(EXPORT_WATERMARK)
- } else {
- ClipboardUtils.setTextContent("$clipboard\n\n[NEW SCANNER]")
- }
- SubjectOfFashionTheft(
- entity,
- get(path),
- MC.unsafeGetRegistryEntry(get(component))!!,
- )
- } else null
-
+ val history = reduceHistory { a, b ->
+ (a.toMutableSet() + b).toList()
+ }
+ copyHistory(history)
MC.sendChat(
- subject?.let {
+ tr(
+ "firmament.fitstealer.copied.deduplicated",
+ "Copied the deduplicated history"
+ )
+ )
+ }
+ }
+ thenLiteral("merged") {
+ thenExecute {
+ val history = reduceHistory(GChainReconciliation::reconcileCycles)
+ copyHistory(history)
+ MC.sendChat(tr("firmament.fitstealer.copied.merged", "Copied the merged history"))
+ }
+ }
+ }
+ thenLiteral("target") {
+ thenLiteral("self") {
+ thenExecute {
+ toggleObserve(MC.player!!)
+ }
+ }
+ thenLiteral("pet") {
+ thenExecute {
+ source.sendFeedback(
+ tr(
+ "firmament.fitstealer.stealingpet",
+ "Observing nearest marker armourstand"
+ )
+ )
+ val p = MC.player!!
+ val nearestPet = p.world.getEntitiesByClass(
+ ArmorStandEntity::class.java,
+ p.boundingBox.expand(10.0),
+ { it.isMarker })
+ .minBy { it.squaredDistanceTo(p) }
+ toggleObserve(nearestPet)
+ }
+ }
+ thenExecute {
+ val ent = MC.instance.targetedEntity
+ if (ent == null) {
+ source.sendFeedback(
+ tr(
+ "firmament.fitstealer.notargetundercursor",
+ "No entity under cursor"
+ )
+ )
+ } else {
+ toggleObserve(ent)
+ }
+ }
+ }
+ thenLiteral("path") {
+ thenArgument(
+ "component",
+ RegistryKeyArgumentType.registryKey(RegistryKeys.DATA_COMPONENT_TYPE)
+ ) { component ->
+ thenArgument("path", NbtPrism.Argument) { path ->
+ thenExecute {
+ lens = LensOfFashionTheft(
+ get(path),
+ MC.unsafeGetRegistryEntry(get(component))!!,
+ )
+ source.sendFeedback(
tr(
- "firmament.fitstealer.targeted",
- "Observing the equipment of ${it.observedEntity.name}."
+ "firmament.fitstealer.lensset",
+ "Analyzing path ${get(path)} for component ${get(component).value}"
)
- } ?: tr("firmament.fitstealer.targetlost", "No longer logging equipment."),
- )
+ )
+ }
}
}
}
}
}
}
+
+ private fun copyHistory(toCopy: List<String>) {
+ ClipboardUtils.setTextContent(toCopy.joinToString("\n"))
+ }
+
+ @Subscribe
+ fun onWorldSwap(event: WorldReadyEvent) {
+ subject = null
+ if (history.isNotEmpty()) {
+ metaHistory.add(history)
+ history = mutableListOf()
+ }
+ }
+
+ private fun toggleObserve(entity: Entity?) {
+ subject = if (subject == null) entity else null
+ if (subject == null) {
+ metaHistory.add(history)
+ history = mutableListOf()
+ }
+ MC.sendChat(
+ subject?.let {
+ tr(
+ "firmament.fitstealer.targeted",
+ "Observing the equipment of ${it.name}."
+ )
+ } ?: tr("firmament.fitstealer.targetlost", "No longer logging equipment."),
+ )
+ }
}