blob: 56c63db393426ae674743f95488f29e0520edb74 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
package moe.nea.firmament.features.debug
import com.mojang.authlib.GameProfile
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.put
import kotlin.time.Duration.Companion.seconds
import net.minecraft.core.component.DataComponents
import net.minecraft.world.item.component.ResolvableProfile
import net.minecraft.world.entity.EquipmentSlot
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.phys.Vec3
import moe.nea.firmament.annotations.Subscribe
import moe.nea.firmament.events.EntityUpdateEvent
import moe.nea.firmament.events.IsSlotProtectedEvent
import moe.nea.firmament.util.ClipboardUtils
import moe.nea.firmament.util.MC
import moe.nea.firmament.util.TimeMark
import moe.nea.firmament.util.extraAttributes
import moe.nea.firmament.util.json.toJsonArray
import moe.nea.firmament.util.math.GChainReconciliation.shortenCycle
import moe.nea.firmament.util.mc.displayNameAccordingToNbt
import moe.nea.firmament.util.mc.loreAccordingToNbt
import moe.nea.firmament.util.rawSkyBlockId
import moe.nea.firmament.util.toTicks
import moe.nea.firmament.util.tr
object SkinPreviews {
// TODO: add pet support
@Subscribe
fun onEntityUpdate(event: EntityUpdateEvent) {
if (!isRecording) return
if (event.entity.position != pos)
return
val entity = event.entity as? LivingEntity ?: return
val stack = entity.getItemBySlot(EquipmentSlot.HEAD) ?: return
val profile = stack.get(DataComponents.PROFILE)?.partialProfile() ?: return
if (profile == animation.lastOrNull()) return
animation.add(profile)
val shortened = animation.shortenCycle()
if (shortened.size <= (animation.size / 2).coerceAtLeast(1) && lastDiscard.passedTime() > 2.seconds) {
val tickEstimation = (lastDiscard.passedTime() / animation.size).toTicks()
val skinName = if (skinColor != null) "${skinId}_${skinColor?.replace(" ", "_")?.uppercase()}" else skinId!!
val json =
buildJsonObject {
put("ticks", tickEstimation)
put(
"textures",
shortened.map {
it.id.toString() + ":" + it.properties()["textures"].first().value()
}.toJsonArray()
)
}
MC.sendChat(
tr(
"firmament.dev.skinpreviews.done",
"Observed a total of ${animation.size} elements, which could be shortened to a cycle of ${shortened.size}. Copying JSON array. Estimated ticks per frame: $tickEstimation."
)
)
isRecording = false
ClipboardUtils.setTextContent(JsonPrimitive(skinName).toString() + ":" + json.toString())
}
}
var animation = mutableListOf<GameProfile>()
var pos = Vec3(-1.0, 72.0, -101.25)
var isRecording = false
var skinColor: String? = null
var skinId: String? = null
var lastDiscard = TimeMark.farPast()
@Subscribe
fun onActivate(event: IsSlotProtectedEvent) {
if (!PowerUserTools.TConfig.autoCopyAnimatedSkins) return
val lastLine = event.itemStack.loreAccordingToNbt.lastOrNull()?.string
if (lastLine != "Right-click to preview!" && lastLine != "Click to preview!") return
lastDiscard = TimeMark.now()
val stackName = event.itemStack.displayNameAccordingToNbt.string
if (stackName == "FIRE SALE!") {
skinColor = null
skinId = event.itemStack.rawSkyBlockId
} else {
skinColor = stackName
}
animation.clear()
isRecording = true
MC.sendChat(tr("firmament.dev.skinpreviews.start", "Starting to observe items"))
}
}
|