tools/dumpnbt: Implement basic functionality.

FINALLY!!! :^)
Soda
BodgeMaster 2022-10-17 06:40:56 +02:00
parent df35243ee9
commit 92cf81c1b4
1 changed files with 270 additions and 1 deletions

View File

@ -16,6 +16,7 @@
#include <iostream>
#include <fstream>
#include <vector>
#include <tinyutf8/tinyutf8.h>
#include "../lib/nbt.hpp"
#include "../lib/cli.hpp"
@ -25,6 +26,265 @@
#define EXIT_USAGE 2
#define EXIT_UNIMPLEMENTED 3
void printTagTypeName(NBT::Tag::Generic* tag, uint64_t offsetBytes) {
std::cout << "[" << offsetBytes << ": ";
switch (tag->getTagType()) {
case NBT::TagType::END:
std::cout << "End";
break;
case NBT::TagType::INT8:
std::cout << "8 Bit Integer";
break;
case NBT::TagType::INT16:
std::cout << "16 Bit Integer";
break;
case NBT::TagType::INT32:
std::cout << "32 Bit Integer";
break;
case NBT::TagType::INT64:
std::cout << "64 Bit Integer";
break;
case NBT::TagType::FLOAT:
std::cout << "Float";
break;
case NBT::TagType::DOUBLE:
std::cout << "Double";
break;
case NBT::TagType::INT8_ARRAY:
std::cout << "Array of 8 Bit Integers";
break;
case NBT::TagType::STRING:
std::cout << "String";
break;
case NBT::TagType::LIST:
std::cout << "List";
break;
case NBT::TagType::COMPOUND:
std::cout << "Compound";
break;
case NBT::TagType::INT32_ARRAY:
std::cout << "Array of 32 Bit Integers";
break;
case NBT::TagType::INT64_ARRAY:
std::cout << "Array of 64 Bit Integers";
break;
default:
// WTF? How'd you even get here?
std::cout << "Unknown Type";
}
std::cout << "]";
if (tag->name == "") {
std::cout << ":";
} else {
std::cout << " " << tag->name << ":";
}
}
void printNBytes(uint64_t bytes) {
std::cout << bytes << (bytes==1? " byte":" bytes");
}
void drawTree(NBT::Tag::Generic* tag, tiny_utf8::string prefix, uint64_t offsetBytes, bool listMode=false) {
std::vector<uint8_t> serialized;
uint64_t headerSize = 0;
if (listMode) {
tag->serializeWithoutHeader(&serialized);
std::cout << prefix << "|Payload: ";
printNBytes(serialized.size());
std::cout << std::endl;
} else {
tag->serialize(&serialized);
if (tag->getTagType() == NBT::TagType::END) {
headerSize = 1;
} else {
headerSize = (uint64_t) NBT::Helper::readInt16(serialized.data(), serialized.size(), 1).value+3;
}
std::cout << prefix << "|Header: ";
printNBytes(headerSize);
std::cout << std::endl;
std::cout << prefix << "|Payload: ";
printNBytes(serialized.size() - headerSize);
std::cout << std::endl;
}
if (tag->getTagType() == NBT::TagType::END) {
std::cout << prefix << "'Total: ";
} else {
std::cout << prefix << "|Total: ";
}
printNBytes(serialized.size());
std::cout << std::endl;
switch (tag->getTagType()) {
case NBT::TagType::END:
break;
case NBT::TagType::INT8:
std::cout << prefix << "'Value: " << (int32_t) reinterpret_cast<NBT::Tag::Int8*>(tag)->getValue() << std::endl;
break;
case NBT::TagType::INT16:
std::cout << prefix << "'Value: " << (int32_t) reinterpret_cast<NBT::Tag::Int16*>(tag)->getValue() << std::endl;
break;
case NBT::TagType::INT32:
std::cout << prefix << "'Value: " << reinterpret_cast<NBT::Tag::Int32*>(tag)->getValue() << std::endl;
break;
case NBT::TagType::INT64:
std::cout << prefix << "'Value: " << reinterpret_cast<NBT::Tag::Int64*>(tag)->getValue() << std::endl;
break;
case NBT::TagType::FLOAT:
std::cout << prefix << "'Value: " << reinterpret_cast<NBT::Tag::Float*>(tag)->getValue() << std::endl;
break;
case NBT::TagType::DOUBLE:
std::cout << prefix << "'Value: " << reinterpret_cast<NBT::Tag::Double*>(tag)->getValue() << std::endl;
break;
case NBT::TagType::INT8_ARRAY: {
NBT::Tag::Int8Array* array = reinterpret_cast<NBT::Tag::Int8Array*>(tag);
std::cout << prefix << "|Length: " << array->length() << std::endl;
std::cout << prefix << "'Values: " << std::endl;
for (uint64_t i=0; i<array->length(); i++) {
if (i == array->length()-1) {
std::cout << prefix << " '" << (int64_t) array->getValue(i).value << std::endl;
} else {
std::cout << prefix << " |" << (int64_t) array->getValue(i).value << std::endl;
}
}
break;
}
case NBT::TagType::STRING:
std::cout << prefix << "'Value: " << reinterpret_cast<NBT::Tag::String*>(tag)->getValue() << std::endl;
break;
case NBT::TagType::LIST: {
NBT::Tag::List* list = reinterpret_cast<NBT::Tag::List*>(tag);
std::cout << prefix << "|Contained Type: ";
switch (list->getContainedType()) {
case NBT::TagType::END:
std::cout << "End";
break;
case NBT::TagType::INT8:
std::cout << "8 Bit Integer";
break;
case NBT::TagType::INT16:
std::cout << "16 Bit Integer";
break;
case NBT::TagType::INT32:
std::cout << "32 Bit Integer";
break;
case NBT::TagType::INT64:
std::cout << "64 Bit Integer";
break;
case NBT::TagType::FLOAT:
std::cout << "Float";
break;
case NBT::TagType::DOUBLE:
std::cout << "Double";
break;
case NBT::TagType::INT8_ARRAY:
std::cout << "Array of 8 Bit Integers";
break;
case NBT::TagType::STRING:
std::cout << "String";
break;
case NBT::TagType::LIST:
std::cout << "List";
break;
case NBT::TagType::COMPOUND:
std::cout << "Compound";
break;
case NBT::TagType::INT32_ARRAY:
std::cout << "Array of 32 Bit Integers";
break;
case NBT::TagType::INT64_ARRAY:
std::cout << "Array of 64 Bit Integers";
break;
default:
// WTF? How'd you even get here?
std::cout << "Unknown Type";
}
std::cout << std::endl;
std::cout << prefix << "|Length: " << list->length() << std::endl;
std::cout << prefix << "|" << std::endl;
offsetBytes = offsetBytes + headerSize + 5;
for (uint64_t i=0; i<list->length(); i++) {
if (i == list->length()-1) {
std::cout << prefix << "'";
printTagTypeName(list->getElementPointer(i).value, offsetBytes);
std::cout << std::endl;
drawTree(list->getElementPointer(i).value, prefix+" ", offsetBytes, true);
} else {
std::cout << prefix << "|";
printTagTypeName(list->getElementPointer(i).value, offsetBytes);
std::cout << std::endl;
drawTree(list->getElementPointer(i).value, prefix+"| ", offsetBytes, true);
}
std::vector<uint8_t> serializedElement;
list->getElementPointer(i).value->serializeWithoutHeader(&serializedElement);
offsetBytes += serializedElement.size();
}
break;
}
case NBT::TagType::COMPOUND: {
NBT::Tag::Compound* compound = reinterpret_cast<NBT::Tag::Compound*>(tag);
std::cout << prefix << "|Length: " << compound->length() << std::endl;
std::cout << prefix << "|" << std::endl;
offsetBytes = offsetBytes + headerSize;
for (uint64_t i=0; i<compound->length(); i++) {
if (i == compound->length()-1) {
std::cout << prefix << "'";
printTagTypeName(compound->getElementPointer(i).value, offsetBytes);
std::cout << std::endl;
drawTree(compound->getElementPointer(i).value, prefix+" ", offsetBytes);
} else {
std::cout << prefix << "|";
printTagTypeName(compound->getElementPointer(i).value, offsetBytes);
std::cout << std::endl;
drawTree(compound->getElementPointer(i).value, prefix+"| ", offsetBytes);
}
std::vector<uint8_t> serializedElement;
compound->getElementPointer(i).value->serialize(&serializedElement);
offsetBytes += serializedElement.size();
}
break;
}
case NBT::TagType::INT32_ARRAY: {
NBT::Tag::Int32Array* array = reinterpret_cast<NBT::Tag::Int32Array*>(tag);
std::cout << prefix << "|Length: " << array->length() << std::endl;
std::cout << prefix << "'Values: " << std::endl;
for (uint64_t i=0; i<array->length(); i++) {
if (i == array->length()-1) {
std::cout << prefix << " '" << array->getValue(i).value << std::endl;
} else {
std::cout << prefix << " |" << array->getValue(i).value << std::endl;
}
}
break;
}
case NBT::TagType::INT64_ARRAY: {
NBT::Tag::Int64Array* array = reinterpret_cast<NBT::Tag::Int64Array*>(tag);
std::cout << prefix << "|Length: " << array->length() << std::endl;
std::cout << prefix << "'Values: " << std::endl;
for (uint64_t i=0; i<array->length(); i++) {
if (i == array->length()-1) {
std::cout << prefix << " '" << array->getValue(i).value << std::endl;
} else {
std::cout << prefix << " |" << array->getValue(i).value << std::endl;
}
}
break;
}
default:
// WTF? How'd you even get here?
std::cout << prefix << "'???" << std::endl;
}
std::cout << prefix << std::endl;
}
int main(int argc, char* argv[]) {
std::vector<CLI::Flag> flags;
@ -93,7 +353,16 @@ int main(int argc, char* argv[]) {
return EXIT_RUNTIME;
}
//TODO: print things here
uint64_t offsetBytes = 0;
for (uint64_t i=0; i<tags.value.size(); i++) {
printTagTypeName(tags.value[i], offsetBytes);
std::cout << std::endl;
drawTree(tags.value[i], "", offsetBytes);
std::vector<uint8_t> serialized;
tags.value[i]->serialize(&serialized);
offsetBytes += serialized.size();
}
return EXIT_SUCCESS;
}