feat(internal): Add a tab list api
This commit is contained in:
@@ -0,0 +1,31 @@
|
|||||||
|
package moe.nea.firmament.mixins.accessor;
|
||||||
|
|
||||||
|
import net.minecraft.client.gui.hud.PlayerListHud;
|
||||||
|
import net.minecraft.client.network.PlayerListEntry;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Mixin(PlayerListHud.class)
|
||||||
|
public interface AccessorPlayerListHud {
|
||||||
|
|
||||||
|
@Accessor("ENTRY_ORDERING")
|
||||||
|
static Comparator<PlayerListEntry> getEntryOrdering() {
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Invoker("collectPlayerEntries")
|
||||||
|
List<PlayerListEntry> collectPlayerEntries_firmament();
|
||||||
|
|
||||||
|
@Accessor("footer")
|
||||||
|
@Nullable Text getFooter_firmament();
|
||||||
|
|
||||||
|
@Accessor("header")
|
||||||
|
@Nullable Text getHeader_firmament();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -12,6 +12,7 @@ import moe.nea.firmament.apis.UrsaManager
|
|||||||
import moe.nea.firmament.events.CommandEvent
|
import moe.nea.firmament.events.CommandEvent
|
||||||
import moe.nea.firmament.events.FirmamentEventBus
|
import moe.nea.firmament.events.FirmamentEventBus
|
||||||
import moe.nea.firmament.features.debug.DebugLogger
|
import moe.nea.firmament.features.debug.DebugLogger
|
||||||
|
import moe.nea.firmament.features.debug.DeveloperFeatures
|
||||||
import moe.nea.firmament.features.debug.PowerUserTools
|
import moe.nea.firmament.features.debug.PowerUserTools
|
||||||
import moe.nea.firmament.features.inventory.buttons.InventoryButtons
|
import moe.nea.firmament.features.inventory.buttons.InventoryButtons
|
||||||
import moe.nea.firmament.features.inventory.storageoverlay.StorageOverlayScreen
|
import moe.nea.firmament.features.inventory.storageoverlay.StorageOverlayScreen
|
||||||
@@ -202,7 +203,7 @@ fun firmamentCommand() = literal("firmament") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
thenLiteral("dev") {
|
thenLiteral(DeveloperFeatures.DEVELOPER_SUBCOMMAND) {
|
||||||
thenLiteral("simulate") {
|
thenLiteral("simulate") {
|
||||||
thenArgument("message", RestArgumentType) { message ->
|
thenArgument("message", RestArgumentType) { message ->
|
||||||
thenExecute {
|
thenExecute {
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ object AnimatedClothingScanner {
|
|||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
fun onSubCommand(event: CommandEvent.SubCommand) {
|
fun onSubCommand(event: CommandEvent.SubCommand) {
|
||||||
event.subcommand("dev") {
|
event.subcommand(DeveloperFeatures.DEVELOPER_SUBCOMMAND) {
|
||||||
thenLiteral("stealthisfit") {
|
thenLiteral("stealthisfit") {
|
||||||
thenLiteral("clear") {
|
thenLiteral("clear") {
|
||||||
thenExecute {
|
thenExecute {
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import moe.nea.firmament.util.asm.AsmAnnotationUtil
|
|||||||
import moe.nea.firmament.util.iterate
|
import moe.nea.firmament.util.iterate
|
||||||
|
|
||||||
object DeveloperFeatures : FirmamentFeature {
|
object DeveloperFeatures : FirmamentFeature {
|
||||||
|
val DEVELOPER_SUBCOMMAND: String = "dev"
|
||||||
override val identifier: String
|
override val identifier: String
|
||||||
get() = "developer"
|
get() = "developer"
|
||||||
override val config: TConfig
|
override val config: TConfig
|
||||||
@@ -103,9 +104,12 @@ object DeveloperFeatures : FirmamentFeature {
|
|||||||
MC.sendChat(Text.translatable("firmament.dev.resourcerebuild.start"))
|
MC.sendChat(Text.translatable("firmament.dev.resourcerebuild.start"))
|
||||||
val startTime = TimeMark.now()
|
val startTime = TimeMark.now()
|
||||||
process.toHandle().onExit().thenApply {
|
process.toHandle().onExit().thenApply {
|
||||||
MC.sendChat(Text.stringifiedTranslatable(
|
MC.sendChat(
|
||||||
|
Text.stringifiedTranslatable(
|
||||||
"firmament.dev.resourcerebuild.done",
|
"firmament.dev.resourcerebuild.done",
|
||||||
startTime.passedTime()))
|
startTime.passedTime()
|
||||||
|
)
|
||||||
|
)
|
||||||
Unit
|
Unit
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ object SoundVisualizer {
|
|||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
fun onSubCommand(event: CommandEvent.SubCommand) {
|
fun onSubCommand(event: CommandEvent.SubCommand) {
|
||||||
event.subcommand("dev") {
|
event.subcommand(DeveloperFeatures.DEVELOPER_SUBCOMMAND) {
|
||||||
thenLiteral("sounds") {
|
thenLiteral("sounds") {
|
||||||
thenExecute {
|
thenExecute {
|
||||||
showSounds = !showSounds
|
showSounds = !showSounds
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import moe.nea.firmament.commands.thenExecute
|
|||||||
import moe.nea.firmament.commands.thenLiteral
|
import moe.nea.firmament.commands.thenLiteral
|
||||||
import moe.nea.firmament.events.CommandEvent
|
import moe.nea.firmament.events.CommandEvent
|
||||||
import moe.nea.firmament.events.HandledScreenKeyPressedEvent
|
import moe.nea.firmament.events.HandledScreenKeyPressedEvent
|
||||||
|
import moe.nea.firmament.features.debug.DeveloperFeatures
|
||||||
import moe.nea.firmament.features.debug.ExportedTestConstantMeta
|
import moe.nea.firmament.features.debug.ExportedTestConstantMeta
|
||||||
import moe.nea.firmament.features.debug.PowerUserTools
|
import moe.nea.firmament.features.debug.PowerUserTools
|
||||||
import moe.nea.firmament.repo.RepoDownloadManager
|
import moe.nea.firmament.repo.RepoDownloadManager
|
||||||
@@ -97,7 +98,7 @@ object ItemExporter {
|
|||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
fun onCommand(event: CommandEvent.SubCommand) {
|
fun onCommand(event: CommandEvent.SubCommand) {
|
||||||
event.subcommand("dev") {
|
event.subcommand(DeveloperFeatures.DEVELOPER_SUBCOMMAND) {
|
||||||
thenLiteral("reexportlore") {
|
thenLiteral("reexportlore") {
|
||||||
thenArgument("itemid", StringArgumentType.string()) { itemid ->
|
thenArgument("itemid", StringArgumentType.string()) { itemid ->
|
||||||
suggestsList { RepoManager.neuRepo.items.items.keys }
|
suggestsList { RepoManager.neuRepo.items.items.keys }
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ object StringUtil {
|
|||||||
return string.replace(",", "").toInt()
|
return string.replace(",", "").toInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun String.title() = replaceFirstChar { it.titlecase() }
|
||||||
|
|
||||||
fun Iterable<String>.unwords() = joinToString(" ")
|
fun Iterable<String>.unwords() = joinToString(" ")
|
||||||
fun nextLexicographicStringOfSameLength(string: String): String {
|
fun nextLexicographicStringOfSameLength(string: String): String {
|
||||||
val next = StringBuilder(string)
|
val next = StringBuilder(string)
|
||||||
|
|||||||
96
src/main/kotlin/util/mc/MCTabListAPI.kt
Normal file
96
src/main/kotlin/util/mc/MCTabListAPI.kt
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
package moe.nea.firmament.util.mc
|
||||||
|
|
||||||
|
import com.mojang.serialization.Codec
|
||||||
|
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||||
|
import java.util.Optional
|
||||||
|
import org.jetbrains.annotations.TestOnly
|
||||||
|
import net.minecraft.client.gui.hud.PlayerListHud
|
||||||
|
import net.minecraft.nbt.NbtOps
|
||||||
|
import net.minecraft.scoreboard.Team
|
||||||
|
import net.minecraft.text.Text
|
||||||
|
import net.minecraft.text.TextCodecs
|
||||||
|
import moe.nea.firmament.annotations.Subscribe
|
||||||
|
import moe.nea.firmament.commands.thenExecute
|
||||||
|
import moe.nea.firmament.commands.thenLiteral
|
||||||
|
import moe.nea.firmament.events.CommandEvent
|
||||||
|
import moe.nea.firmament.events.TickEvent
|
||||||
|
import moe.nea.firmament.features.debug.DeveloperFeatures
|
||||||
|
import moe.nea.firmament.features.debug.ExportedTestConstantMeta
|
||||||
|
import moe.nea.firmament.mixins.accessor.AccessorPlayerListHud
|
||||||
|
import moe.nea.firmament.util.ClipboardUtils
|
||||||
|
import moe.nea.firmament.util.MC
|
||||||
|
import moe.nea.firmament.util.intoOptional
|
||||||
|
import moe.nea.firmament.util.mc.SNbtFormatter.Companion.toPrettyString
|
||||||
|
|
||||||
|
object MCTabListAPI {
|
||||||
|
|
||||||
|
fun PlayerListHud.cast() = this as AccessorPlayerListHud
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
fun onTick(event: TickEvent) {
|
||||||
|
_currentTabList = null
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
fun devCommand(event: CommandEvent.SubCommand) {
|
||||||
|
event.subcommand(DeveloperFeatures.DEVELOPER_SUBCOMMAND) {
|
||||||
|
thenLiteral("copytablist") {
|
||||||
|
thenExecute {
|
||||||
|
currentTabList.body.forEach {
|
||||||
|
MC.sendChat(Text.literal(TextCodecs.CODEC.encodeStart(NbtOps.INSTANCE, it).orThrow.toString()))
|
||||||
|
}
|
||||||
|
var compound = CurrentTabList.CODEC.encodeStart(NbtOps.INSTANCE, currentTabList).orThrow
|
||||||
|
compound = ExportedTestConstantMeta.SOURCE_CODEC.encode(
|
||||||
|
ExportedTestConstantMeta.current,
|
||||||
|
NbtOps.INSTANCE,
|
||||||
|
compound
|
||||||
|
).orThrow
|
||||||
|
ClipboardUtils.setTextContent(
|
||||||
|
compound.toPrettyString()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@get:TestOnly
|
||||||
|
@set:TestOnly
|
||||||
|
var _currentTabList: CurrentTabList? = null
|
||||||
|
|
||||||
|
val currentTabList get() = _currentTabList ?: getTabListNow().also { _currentTabList = it }
|
||||||
|
|
||||||
|
data class CurrentTabList(
|
||||||
|
val header: Optional<Text>,
|
||||||
|
val footer: Optional<Text>,
|
||||||
|
val body: List<Text>,
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
val CODEC: Codec<CurrentTabList> = RecordCodecBuilder.create {
|
||||||
|
it.group(
|
||||||
|
TextCodecs.CODEC.optionalFieldOf("header").forGetter(CurrentTabList::header),
|
||||||
|
TextCodecs.CODEC.optionalFieldOf("footer").forGetter(CurrentTabList::footer),
|
||||||
|
TextCodecs.CODEC.listOf().fieldOf("body").forGetter(CurrentTabList::body),
|
||||||
|
).apply(it, ::CurrentTabList)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getTabListNow(): CurrentTabList {
|
||||||
|
// This is a precondition for PlayerListHud.collectEntries to be valid
|
||||||
|
MC.networkHandler ?: return CurrentTabList(Optional.empty(), Optional.empty(), emptyList())
|
||||||
|
val hud = MC.inGameHud.playerListHud.cast()
|
||||||
|
val entries = hud.collectPlayerEntries_firmament()
|
||||||
|
.map {
|
||||||
|
it.displayName ?: run {
|
||||||
|
val team = it.scoreboardTeam
|
||||||
|
val name = it.profile.name
|
||||||
|
Team.decorateName(team, Text.literal(name))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CurrentTabList(
|
||||||
|
header = hud.header_firmament.intoOptional(),
|
||||||
|
footer = hud.footer_firmament.intoOptional(),
|
||||||
|
body = entries,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
41
src/main/kotlin/util/skyblock/TabListAPI.kt
Normal file
41
src/main/kotlin/util/skyblock/TabListAPI.kt
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
package moe.nea.firmament.util.skyblock
|
||||||
|
|
||||||
|
import org.intellij.lang.annotations.Language
|
||||||
|
import net.minecraft.text.Text
|
||||||
|
import moe.nea.firmament.util.StringUtil.title
|
||||||
|
import moe.nea.firmament.util.StringUtil.unwords
|
||||||
|
import moe.nea.firmament.util.mc.MCTabListAPI
|
||||||
|
import moe.nea.firmament.util.unformattedString
|
||||||
|
|
||||||
|
object TabListAPI {
|
||||||
|
|
||||||
|
fun getWidgetLines(widgetName: WidgetName, includeTitle: Boolean = false, from: MCTabListAPI.CurrentTabList = MCTabListAPI.currentTabList): List<Text> {
|
||||||
|
return from.body
|
||||||
|
.dropWhile { !widgetName.matchesTitle(it) }
|
||||||
|
.takeWhile { it.string.isNotBlank() && !it.string.startsWith(" ") }
|
||||||
|
.let { if (includeTitle) it else it.drop(1) }
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class WidgetName(regex: Regex?) {
|
||||||
|
COMMISSIONS,
|
||||||
|
SKILLS("Skills:( .*)?"),
|
||||||
|
PROFILE("Profile: (.*)"),
|
||||||
|
COLLECTION,
|
||||||
|
ESSENCE,
|
||||||
|
PET
|
||||||
|
;
|
||||||
|
|
||||||
|
fun matchesTitle(it: Text): Boolean {
|
||||||
|
return regex.matches(it.unformattedString)
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor() : this(null)
|
||||||
|
constructor(@Language("RegExp") regex: String) : this(Regex(regex))
|
||||||
|
|
||||||
|
val label =
|
||||||
|
name.split("_").map { it.lowercase().title() }.unwords()
|
||||||
|
val regex = regex ?: Regex.fromLiteral("$label:")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -2,7 +2,9 @@ accessWidener v2 named
|
|||||||
accessible class net/minecraft/client/render/RenderLayer$MultiPhase
|
accessible class net/minecraft/client/render/RenderLayer$MultiPhase
|
||||||
accessible class net/minecraft/client/render/RenderLayer$MultiPhaseParameters
|
accessible class net/minecraft/client/render/RenderLayer$MultiPhaseParameters
|
||||||
accessible class net/minecraft/client/font/TextRenderer$Drawer
|
accessible class net/minecraft/client/font/TextRenderer$Drawer
|
||||||
|
|
||||||
accessible field net/minecraft/client/gui/hud/InGameHud SCOREBOARD_ENTRY_COMPARATOR Ljava/util/Comparator;
|
accessible field net/minecraft/client/gui/hud/InGameHud SCOREBOARD_ENTRY_COMPARATOR Ljava/util/Comparator;
|
||||||
|
|
||||||
accessible field net/minecraft/client/network/ClientPlayNetworkHandler combinedDynamicRegistries Lnet/minecraft/registry/DynamicRegistryManager$Immutable;
|
accessible field net/minecraft/client/network/ClientPlayNetworkHandler combinedDynamicRegistries Lnet/minecraft/registry/DynamicRegistryManager$Immutable;
|
||||||
accessible method net/minecraft/registry/RegistryOps <init> (Lcom/mojang/serialization/DynamicOps;Lnet/minecraft/registry/RegistryOps$RegistryInfoGetter;)V
|
accessible method net/minecraft/registry/RegistryOps <init> (Lcom/mojang/serialization/DynamicOps;Lnet/minecraft/registry/RegistryOps$RegistryInfoGetter;)V
|
||||||
accessible class net/minecraft/registry/RegistryOps$CachedRegistryInfoGetter
|
accessible class net/minecraft/registry/RegistryOps$CachedRegistryInfoGetter
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
package moe.nea.firmament.test.testutil
|
package moe.nea.firmament.test.testutil
|
||||||
|
|
||||||
import com.mojang.datafixers.DSL
|
import com.mojang.datafixers.DSL
|
||||||
import com.mojang.datafixers.DataFixUtils
|
|
||||||
import com.mojang.datafixers.types.templates.Named
|
|
||||||
import com.mojang.serialization.Dynamic
|
import com.mojang.serialization.Dynamic
|
||||||
import com.mojang.serialization.JsonOps
|
import com.mojang.serialization.JsonOps
|
||||||
import net.minecraft.SharedConstants
|
import net.minecraft.SharedConstants
|
||||||
@@ -20,6 +18,7 @@ import net.minecraft.text.TextCodecs
|
|||||||
import moe.nea.firmament.features.debug.ExportedTestConstantMeta
|
import moe.nea.firmament.features.debug.ExportedTestConstantMeta
|
||||||
import moe.nea.firmament.test.FirmTestBootstrap
|
import moe.nea.firmament.test.FirmTestBootstrap
|
||||||
import moe.nea.firmament.util.MC
|
import moe.nea.firmament.util.MC
|
||||||
|
import moe.nea.firmament.util.mc.MCTabListAPI
|
||||||
|
|
||||||
object ItemResources {
|
object ItemResources {
|
||||||
init {
|
init {
|
||||||
@@ -36,11 +35,12 @@ object ItemResources {
|
|||||||
fun loadSNbt(path: String): NbtCompound {
|
fun loadSNbt(path: String): NbtCompound {
|
||||||
return StringNbtReader.readCompound(loadString(path))
|
return StringNbtReader.readCompound(loadString(path))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getNbtOps(): RegistryOps<NbtElement> = MC.currentOrDefaultRegistries.getOps(NbtOps.INSTANCE)
|
fun getNbtOps(): RegistryOps<NbtElement> = MC.currentOrDefaultRegistries.getOps(NbtOps.INSTANCE)
|
||||||
|
|
||||||
fun tryMigrateNbt(
|
fun tryMigrateNbt(
|
||||||
nbtCompound: NbtCompound,
|
nbtCompound: NbtCompound,
|
||||||
typ: DSL.TypeReference,
|
typ: DSL.TypeReference?,
|
||||||
): NbtElement {
|
): NbtElement {
|
||||||
val source = nbtCompound.get("source", ExportedTestConstantMeta.CODEC)
|
val source = nbtCompound.get("source", ExportedTestConstantMeta.CODEC)
|
||||||
nbtCompound.remove("source")
|
nbtCompound.remove("source")
|
||||||
@@ -49,10 +49,12 @@ object ItemResources {
|
|||||||
// Per 1.21.5 text components are wrapped in a string, which firmament unwrapped in the snbt files
|
// Per 1.21.5 text components are wrapped in a string, which firmament unwrapped in the snbt files
|
||||||
NbtString.of(
|
NbtString.of(
|
||||||
NbtOps.INSTANCE.convertTo(JsonOps.INSTANCE, nbtCompound)
|
NbtOps.INSTANCE.convertTo(JsonOps.INSTANCE, nbtCompound)
|
||||||
.toString())
|
.toString()
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
nbtCompound
|
nbtCompound
|
||||||
}
|
}
|
||||||
|
if (typ != null) {
|
||||||
return Schemas.getFixer()
|
return Schemas.getFixer()
|
||||||
.update(
|
.update(
|
||||||
typ,
|
typ,
|
||||||
@@ -60,10 +62,20 @@ object ItemResources {
|
|||||||
source.get().dataVersion,
|
source.get().dataVersion,
|
||||||
SharedConstants.getGameVersion().saveVersion.id
|
SharedConstants.getGameVersion().saveVersion.id
|
||||||
).value
|
).value
|
||||||
|
} else {
|
||||||
|
wrappedNbtSource
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nbtCompound
|
return nbtCompound
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun loadTablist(name: String): MCTabListAPI.CurrentTabList {
|
||||||
|
return MCTabListAPI.CurrentTabList.CODEC.parse(
|
||||||
|
getNbtOps(),
|
||||||
|
tryMigrateNbt(loadSNbt("testdata/tablist/$name.snbt"), null),
|
||||||
|
).getOrThrow { IllegalStateException("Could not load tablist '$name': $it") }
|
||||||
|
}
|
||||||
|
|
||||||
fun loadText(name: String): Text {
|
fun loadText(name: String): Text {
|
||||||
return TextCodecs.CODEC.parse(
|
return TextCodecs.CODEC.parse(
|
||||||
getNbtOps(),
|
getNbtOps(),
|
||||||
|
|||||||
48
src/test/kotlin/util/skyblock/TabListAPITest.kt
Normal file
48
src/test/kotlin/util/skyblock/TabListAPITest.kt
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
package moe.nea.firmament.test.util.skyblock
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Assertions
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import moe.nea.firmament.test.testutil.ItemResources
|
||||||
|
import moe.nea.firmament.util.skyblock.TabListAPI
|
||||||
|
|
||||||
|
class TabListAPITest {
|
||||||
|
val tablist = ItemResources.loadTablist("dungeon_hub")
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun checkWithTitle() {
|
||||||
|
Assertions.assertEquals(
|
||||||
|
listOf(
|
||||||
|
"Profile: Strawberry",
|
||||||
|
" SB Level: [210] 26/100 XP",
|
||||||
|
" Bank: 1.4B",
|
||||||
|
" Interest: 12 Hours (689.1k)",
|
||||||
|
),
|
||||||
|
TabListAPI.getWidgetLines(TabListAPI.WidgetName.PROFILE, includeTitle = true, from = tablist).map { it.string })
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun checkEndOfColumn() {
|
||||||
|
Assertions.assertEquals(
|
||||||
|
listOf(
|
||||||
|
" Bonzo IV: 110/150",
|
||||||
|
" Scarf II: 25/50",
|
||||||
|
" The Professor IV: 141/150",
|
||||||
|
" Thorn I: 29/50",
|
||||||
|
" Livid II: 91/100",
|
||||||
|
" Sadan V: 388/500",
|
||||||
|
" Necron VI: 531/750",
|
||||||
|
),
|
||||||
|
TabListAPI.getWidgetLines(TabListAPI.WidgetName.COLLECTION, from = tablist).map { it.string }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun checkWithoutTitle() {
|
||||||
|
Assertions.assertEquals(
|
||||||
|
listOf(
|
||||||
|
" Undead: 1,907",
|
||||||
|
" Wither: 318",
|
||||||
|
),
|
||||||
|
TabListAPI.getWidgetLines(TabListAPI.WidgetName.ESSENCE, from = tablist).map { it.string })
|
||||||
|
}
|
||||||
|
}
|
||||||
1170
src/test/resources/testdata/tablist/dungeon_hub.snbt
vendored
Normal file
1170
src/test/resources/testdata/tablist/dungeon_hub.snbt
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user