diff options
Diffstat (limited to 'src/main/kotlin/features/debug')
-rw-r--r-- | src/main/kotlin/features/debug/AnimatedClothingScanner.kt | 94 | ||||
-rw-r--r-- | src/main/kotlin/features/debug/DeveloperFeatures.kt | 43 | ||||
-rw-r--r-- | src/main/kotlin/features/debug/PowerUserTools.kt | 3 |
3 files changed, 122 insertions, 18 deletions
diff --git a/src/main/kotlin/features/debug/AnimatedClothingScanner.kt b/src/main/kotlin/features/debug/AnimatedClothingScanner.kt index 11b47a9..d0db252 100644 --- a/src/main/kotlin/features/debug/AnimatedClothingScanner.kt +++ b/src/main/kotlin/features/debug/AnimatedClothingScanner.kt @@ -1,49 +1,109 @@ 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.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 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.util.ClipboardUtils import moe.nea.firmament.util.MC +import moe.nea.firmament.util.mc.NbtPrism import moe.nea.firmament.util.skyBlockId import moe.nea.firmament.util.tr object AnimatedClothingScanner { - var observedEntity: Entity? = null + data class SubjectOfFashionTheft<T>( + val observedEntity: Entity, + val prism: NbtPrism, + val component: ComponentType<T>, + ) { + fun observe(itemStack: ItemStack): Collection<NbtElement> { + val x = itemStack.get(component) ?: return listOf() + val nbt = component.codecOrThrow.encodeStart(NbtOps.INSTANCE, x).orThrow + return prism.access(nbt) + } + } + + var subject: SubjectOfFashionTheft<*>? = null @OptIn(ExperimentalStdlibApi::class) @Subscribe fun onUpdate(event: EntityUpdateEvent) { - if (event.entity != observedEntity) return + val s = subject ?: return + if (event.entity != s.observedEntity) return if (event is EntityUpdateEvent.EquipmentUpdate) { + val lines = mutableListOf<String>() event.newEquipment.forEach { - val id = it.second.skyBlockId?.neuItem - val colour = it.second.get(DataComponentTypes.DYED_COLOR) - ?.rgb?.toHexString(HexFormat.UpperCase) - ?.let { " #$it" } ?: "" - MC.sendChat(tr("firmament.fitstealer.update", - "[FIT CHECK][${MC.currentTick}] ${it.first.asString()} => ${id}${colour}")) + 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 EXPORT_WATERMARK = "[CLOTHES EXPORT]" + @Subscribe fun onSubCommand(event: CommandEvent.SubCommand) { event.subcommand("dev") { thenLiteral("stealthisfit") { - thenExecute { - observedEntity = - if (observedEntity == null) MC.instance.targetedEntity else null - - MC.sendChat( - observedEntity?.let { - tr("firmament.fitstealer.targeted", "Observing the equipment of ${it.name}.") - } ?: tr("firmament.fitstealer.targetlost", "No longer logging equipment."), - ) + thenArgument( + "component", + RegistryKeyArgumentType.registryKey(RegistryKeys.DATA_COMPONENT_TYPE) + ) { component -> + thenArgument("path", NbtPrism.Argument) { path -> + thenExecute { + subject = + if (subject == null) run { + val entity = MC.instance.targetedEntity ?: return@run null + val clipboard = ClipboardUtils.getTextContents() + MC.instance.entit + 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 + + MC.sendChat( + subject?.let { + tr( + "firmament.fitstealer.targeted", + "Observing the equipment of ${it.observedEntity.name}." + ) + } ?: tr("firmament.fitstealer.targetlost", "No longer logging equipment."), + ) + } + } } } } diff --git a/src/main/kotlin/features/debug/DeveloperFeatures.kt b/src/main/kotlin/features/debug/DeveloperFeatures.kt index 8f0c25c..af1e92e 100644 --- a/src/main/kotlin/features/debug/DeveloperFeatures.kt +++ b/src/main/kotlin/features/debug/DeveloperFeatures.kt @@ -3,6 +3,10 @@ package moe.nea.firmament.features.debug import java.io.File import java.nio.file.Path import java.util.concurrent.CompletableFuture +import org.objectweb.asm.ClassReader +import org.objectweb.asm.Type +import org.objectweb.asm.tree.ClassNode +import org.spongepowered.asm.mixin.Mixin import kotlinx.serialization.json.encodeToStream import kotlin.io.path.absolute import kotlin.io.path.exists @@ -10,11 +14,14 @@ import net.minecraft.client.MinecraftClient import net.minecraft.text.Text import moe.nea.firmament.Firmament import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.events.DebugInstantiateEvent import moe.nea.firmament.events.TickEvent import moe.nea.firmament.features.FirmamentFeature import moe.nea.firmament.gui.config.ManagedConfig +import moe.nea.firmament.init.MixinPlugin import moe.nea.firmament.util.MC import moe.nea.firmament.util.TimeMark +import moe.nea.firmament.util.asm.AsmAnnotationUtil import moe.nea.firmament.util.iterate object DeveloperFeatures : FirmamentFeature { @@ -42,6 +49,42 @@ object DeveloperFeatures : FirmamentFeature { } @Subscribe + fun loadAllMixinClasses(event: DebugInstantiateEvent) { + val allMixinClasses = mutableSetOf<String>() + MixinPlugin.instances.forEach { plugin -> + val prefix = plugin.mixinPackage + "." + val classes = plugin.mixins.map { prefix + it } + allMixinClasses.addAll(classes) + for (cls in classes) { + val targets = javaClass.classLoader.getResourceAsStream("${cls.replace(".", "/")}.class").use { + val node = ClassNode() + ClassReader(it).accept(node, 0) + val mixins = mutableListOf<Mixin>() + (node.visibleAnnotations.orEmpty() + node.invisibleAnnotations.orEmpty()).forEach { + val annotationType = Type.getType(it.desc) + val mixinType = Type.getType(Mixin::class.java) + if (mixinType == annotationType) { + mixins.add(AsmAnnotationUtil.createProxy(Mixin::class.java, it)) + } + } + mixins.flatMap { it.targets.toList() } + mixins.flatMap { it.value.map { it.java.name } } + } + for (target in targets) + try { + Firmament.logger.debug("Loading ${target} to force instantiate ${cls}") + Class.forName(target, true, javaClass.classLoader) + } catch (ex: Throwable) { + Firmament.logger.error("Could not load class ${target} that has been mixind by $cls", ex) + } + } + } + Firmament.logger.info("Forceloaded all Firmament mixins:") + val applied = MixinPlugin.instances.flatMap { it.appliedMixins }.toSet() + applied.forEach { Firmament.logger.info(" - ${it}") } + require(allMixinClasses == applied) + } + + @Subscribe fun dumpMissingTranslations(tickEvent: TickEvent) { val toDump = missingTranslations ?: return missingTranslations = null diff --git a/src/main/kotlin/features/debug/PowerUserTools.kt b/src/main/kotlin/features/debug/PowerUserTools.kt index 8be5d5d..251fc8b 100644 --- a/src/main/kotlin/features/debug/PowerUserTools.kt +++ b/src/main/kotlin/features/debug/PowerUserTools.kt @@ -43,6 +43,7 @@ import moe.nea.firmament.util.mc.IntrospectableItemModelManager import moe.nea.firmament.util.mc.SNbtFormatter import moe.nea.firmament.util.mc.SNbtFormatter.Companion.toPrettyString import moe.nea.firmament.util.mc.displayNameAccordingToNbt +import moe.nea.firmament.util.mc.iterableArmorItems import moe.nea.firmament.util.mc.loreAccordingToNbt import moe.nea.firmament.util.skyBlockId @@ -108,7 +109,7 @@ object PowerUserTools : FirmamentFeature { MC.sendChat(Text.stringifiedTranslatable("firmament.poweruser.entity.position", target.pos)) if (target is LivingEntity) { MC.sendChat(Text.translatable("firmament.poweruser.entity.armor")) - for (armorItem in target.armorItems) { + for ((slot, armorItem) in target.iterableArmorItems) { MC.sendChat(Text.translatable("firmament.poweruser.entity.armor.item", debugFormat(armorItem))) } } |