diff options
Diffstat (limited to 'src/main/kotlin/util/mc/SNbtFormatter.kt')
-rw-r--r-- | src/main/kotlin/util/mc/SNbtFormatter.kt | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/src/main/kotlin/util/mc/SNbtFormatter.kt b/src/main/kotlin/util/mc/SNbtFormatter.kt new file mode 100644 index 0000000..e773927 --- /dev/null +++ b/src/main/kotlin/util/mc/SNbtFormatter.kt @@ -0,0 +1,138 @@ +package moe.nea.firmament.util.mc + +import net.minecraft.nbt.NbtByte +import net.minecraft.nbt.NbtByteArray +import net.minecraft.nbt.NbtCompound +import net.minecraft.nbt.NbtDouble +import net.minecraft.nbt.NbtElement +import net.minecraft.nbt.NbtEnd +import net.minecraft.nbt.NbtFloat +import net.minecraft.nbt.NbtInt +import net.minecraft.nbt.NbtIntArray +import net.minecraft.nbt.NbtList +import net.minecraft.nbt.NbtLong +import net.minecraft.nbt.NbtLongArray +import net.minecraft.nbt.NbtShort +import net.minecraft.nbt.NbtString +import net.minecraft.nbt.visitor.NbtElementVisitor + +class SNbtFormatter private constructor() : NbtElementVisitor { + private val result = StringBuilder() + private var indent = 0 + private fun writeIndent() { + result.append("\t".repeat(indent)) + } + + private fun pushIndent() { + indent++ + } + + private fun popIndent() { + indent-- + } + + fun apply(element: NbtElement): StringBuilder { + element.accept(this) + return result + } + + + override fun visitString(element: NbtString) { + result.append(NbtString.escape(element.asString())) + } + + override fun visitByte(element: NbtByte) { + result.append(element.numberValue()).append("b") + } + + override fun visitShort(element: NbtShort) { + result.append(element.shortValue()).append("s") + } + + override fun visitInt(element: NbtInt) { + result.append(element.intValue()) + } + + override fun visitLong(element: NbtLong) { + result.append(element.longValue()).append("L") + } + + override fun visitFloat(element: NbtFloat) { + result.append(element.floatValue()).append("f") + } + + override fun visitDouble(element: NbtDouble) { + result.append(element.doubleValue()).append("d") + } + + private fun visitArrayContents(array: List<NbtElement>) { + array.forEachIndexed { index, element -> + writeIndent() + element.accept(this) + if (array.size != index + 1) { + result.append(",") + } + result.append("\n") + } + } + + private fun writeArray(arrayTypeTag: String, array: List<NbtElement>) { + result.append("[").append(arrayTypeTag).append("\n") + pushIndent() + visitArrayContents(array) + popIndent() + writeIndent() + result.append("]") + + } + + override fun visitByteArray(element: NbtByteArray) { + writeArray("B;", element) + } + + override fun visitIntArray(element: NbtIntArray) { + writeArray("I;", element) + } + + override fun visitLongArray(element: NbtLongArray) { + writeArray("L;", element) + } + + override fun visitList(element: NbtList) { + writeArray("", element) + } + + override fun visitCompound(compound: NbtCompound) { + result.append("{\n") + pushIndent() + val keys = compound.keys.sorted() + keys.forEachIndexed { index, key -> + writeIndent() + val element = compound[key] ?: error("Key '$key' found but not present in compound: $compound") + val escapedName = if (key.matches(SIMPLE_NAME)) key else NbtString.escape(key) + result.append(escapedName).append(": ") + element.accept(this) + if (keys.size != index + 1) { + result.append(",") + } + result.append("\n") + } + popIndent() + writeIndent() + result.append("}") + } + + override fun visitEnd(element: NbtEnd) { + result.append("END") + } + + companion object { + fun prettify(nbt: NbtElement): String { + return SNbtFormatter().apply(nbt).toString() + } + + fun NbtElement.toPrettyString() = prettify(this) + + private val SIMPLE_NAME = "[A-Za-z0-9._+-]+".toRegex() + } +} |