mirror of
https://github.com/neocturne/MinedMap.git
synced 2025-03-05 17:44:52 +01:00
NBT: rework type system
This commit is contained in:
parent
315bb38444
commit
f1f783877f
17 changed files with 162 additions and 228 deletions
|
@ -40,12 +40,16 @@ private:
|
|||
const uint8_t *value;
|
||||
|
||||
public:
|
||||
static const MakeType<ByteArrayTag> Type;
|
||||
|
||||
|
||||
ByteArrayTag(Buffer *buffer) {
|
||||
len = buffer->get32();
|
||||
value = buffer->get(len);
|
||||
}
|
||||
virtual Type getType() const {
|
||||
return Type::ByteArray;
|
||||
|
||||
virtual const TagType & getType() const {
|
||||
return Type;
|
||||
}
|
||||
|
||||
virtual void print(std::ostream& os, const std::string &indent) const {
|
||||
|
|
|
@ -37,12 +37,15 @@ private:
|
|||
uint8_t value;
|
||||
|
||||
public:
|
||||
static const MakeType<ByteTag> Type;
|
||||
|
||||
|
||||
ByteTag(Buffer *buffer) {
|
||||
value = buffer->get8();
|
||||
}
|
||||
|
||||
virtual Type getType() const {
|
||||
return Type::Byte;
|
||||
virtual const TagType & getType() const {
|
||||
return Type;
|
||||
}
|
||||
|
||||
virtual void print(std::ostream& os, const std::string &) const {
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "EndTag.hpp"
|
||||
#include "Tag.hpp"
|
||||
|
||||
#include <string>
|
||||
|
@ -37,18 +38,21 @@ namespace NBT {
|
|||
|
||||
class CompoundTag : public Tag, public std::unordered_map<std::string, std::shared_ptr<const Tag>> {
|
||||
public:
|
||||
static const MakeType<CompoundTag> Type;
|
||||
|
||||
|
||||
CompoundTag(Buffer *buffer) {
|
||||
while (true) {
|
||||
std::pair<std::string, std::shared_ptr<const Tag>> v = Tag::readNamedTag(buffer);
|
||||
if (v.second->getType() == Type::End)
|
||||
if (v.second->getType() == EndTag::Type)
|
||||
break;
|
||||
|
||||
insert(std::move(v));
|
||||
}
|
||||
}
|
||||
|
||||
virtual Type getType() const {
|
||||
return Type::Compound;
|
||||
virtual const TagType & getType() const {
|
||||
return Type;
|
||||
}
|
||||
|
||||
virtual void print(std::ostream& os, const std::string &indent) const {
|
||||
|
|
|
@ -37,12 +37,15 @@ private:
|
|||
const uint8_t *ptr;
|
||||
|
||||
public:
|
||||
static const MakeType<DoubleTag> Type;
|
||||
|
||||
|
||||
DoubleTag(Buffer *buffer) {
|
||||
ptr = buffer->get(8);
|
||||
}
|
||||
|
||||
virtual Type getType() const {
|
||||
return Type::Double;
|
||||
virtual const TagType & getType() const {
|
||||
return Type;
|
||||
}
|
||||
|
||||
virtual void print(std::ostream& os, const std::string &) const {
|
||||
|
|
|
@ -34,10 +34,13 @@ namespace NBT {
|
|||
|
||||
class EndTag : public Tag {
|
||||
public:
|
||||
EndTag() {}
|
||||
static const MakeType<EndTag> Type;
|
||||
|
||||
virtual Type getType() const {
|
||||
return Type::End;
|
||||
|
||||
EndTag(Buffer *) {}
|
||||
|
||||
virtual const TagType & getType() const {
|
||||
return Type;
|
||||
}
|
||||
|
||||
virtual void print(std::ostream&, const std::string &) const {
|
||||
|
|
|
@ -36,12 +36,15 @@ class FloatTag : public Tag {
|
|||
const uint8_t *ptr;
|
||||
|
||||
public:
|
||||
static const MakeType<FloatTag> Type;
|
||||
|
||||
|
||||
FloatTag(Buffer *buffer) {
|
||||
ptr = buffer->get(4);
|
||||
}
|
||||
|
||||
virtual Type getType() const {
|
||||
return Type::Float;
|
||||
virtual const TagType & getType() const {
|
||||
return Type;
|
||||
}
|
||||
|
||||
virtual void print(std::ostream& os, const std::string &) const {
|
||||
|
|
|
@ -40,13 +40,16 @@ private:
|
|||
const uint8_t *ptr;
|
||||
|
||||
public:
|
||||
static const MakeType<IntArrayTag> Type;
|
||||
|
||||
|
||||
IntArrayTag(Buffer *buffer) {
|
||||
len = buffer->get32();
|
||||
ptr = buffer->get(4*len);
|
||||
}
|
||||
|
||||
virtual Type getType() const {
|
||||
return Type::IntArray;
|
||||
virtual const TagType & getType() const {
|
||||
return Type;
|
||||
}
|
||||
|
||||
virtual void print(std::ostream& os, const std::string &indent) const {
|
||||
|
|
|
@ -37,12 +37,15 @@ private:
|
|||
const uint8_t *ptr;
|
||||
|
||||
public:
|
||||
static const MakeType<IntTag> Type;
|
||||
|
||||
|
||||
IntTag(Buffer *buffer) {
|
||||
ptr = buffer->get(4);
|
||||
}
|
||||
|
||||
virtual Type getType() const {
|
||||
return Type::Int;
|
||||
virtual const TagType & getType() const {
|
||||
return Type;
|
||||
}
|
||||
|
||||
virtual void print(std::ostream& os, const std::string &) const {
|
||||
|
|
|
@ -34,34 +34,29 @@
|
|||
namespace MinedMap {
|
||||
namespace NBT {
|
||||
|
||||
|
||||
class ListTagBase : public Tag {
|
||||
public:
|
||||
virtual Type getType() const {
|
||||
return Type::List;
|
||||
}
|
||||
|
||||
virtual Type getSubtype() const = 0;
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
class ListTag : public ListTagBase, public std::vector<std::shared_ptr<const T>> {
|
||||
class ListTag : public Tag, public std::vector<std::shared_ptr<const Tag>> {
|
||||
private:
|
||||
Type type;
|
||||
const TagType *subtype;
|
||||
|
||||
public:
|
||||
ListTag(Type type0, Buffer *buffer) : type(type0) {
|
||||
static const MakeType<ListTag> Type;
|
||||
|
||||
|
||||
ListTag(Buffer *buffer) {
|
||||
subtype = &getTypeById(buffer->get8());
|
||||
|
||||
uint32_t len = buffer->get32();
|
||||
|
||||
this->resize(len);
|
||||
|
||||
for (uint32_t i = 0; i < len; i++)
|
||||
(*this)[i] = std::static_pointer_cast<const T>(Tag::readTag(type, buffer));
|
||||
push_back(subtype->read(buffer));
|
||||
}
|
||||
|
||||
virtual Type getSubtype() const {
|
||||
return type;
|
||||
virtual const TagType & getType() const {
|
||||
return Type;
|
||||
}
|
||||
|
||||
virtual const TagType & getSubtype() const {
|
||||
return *subtype;
|
||||
}
|
||||
|
||||
virtual void print(std::ostream& os, const std::string &indent) const {
|
||||
|
|
|
@ -40,13 +40,16 @@ private:
|
|||
const uint8_t *ptr;
|
||||
|
||||
public:
|
||||
static const MakeType<LongArrayTag> Type;
|
||||
|
||||
|
||||
LongArrayTag(Buffer *buffer) {
|
||||
len = buffer->get32();
|
||||
ptr = buffer->get(8*len);
|
||||
}
|
||||
|
||||
virtual Type getType() const {
|
||||
return Type::LongArray;
|
||||
virtual const TagType & getType() const {
|
||||
return Type;
|
||||
}
|
||||
|
||||
virtual void print(std::ostream& os, const std::string &indent) const {
|
||||
|
|
|
@ -37,12 +37,15 @@ private:
|
|||
const uint8_t *ptr;
|
||||
|
||||
public:
|
||||
static const MakeType<LongTag> Type;
|
||||
|
||||
|
||||
LongTag(Buffer *buffer) {
|
||||
ptr = buffer->get(8);
|
||||
}
|
||||
|
||||
virtual Type getType() const {
|
||||
return Type::Long;
|
||||
virtual const TagType & getType() const {
|
||||
return Type;
|
||||
}
|
||||
|
||||
virtual void print(std::ostream& os, const std::string &) const {
|
||||
|
|
|
@ -37,12 +37,15 @@ private:
|
|||
const uint8_t *ptr;
|
||||
|
||||
public:
|
||||
static const MakeType<ShortTag> Type;
|
||||
|
||||
|
||||
ShortTag(Buffer *buffer) {
|
||||
ptr = buffer->get(2);
|
||||
}
|
||||
|
||||
virtual Type getType() const {
|
||||
return Type::Short;
|
||||
virtual const TagType & getType() const {
|
||||
return Type;
|
||||
}
|
||||
|
||||
virtual void print(std::ostream& os, const std::string &) const {
|
||||
|
|
|
@ -38,13 +38,16 @@ private:
|
|||
const uint8_t *ptr;
|
||||
|
||||
public:
|
||||
static const MakeType<StringTag> Type;
|
||||
|
||||
|
||||
StringTag(Buffer *buffer) {
|
||||
len = buffer->get16();
|
||||
ptr = buffer->get(len);
|
||||
}
|
||||
|
||||
virtual Type getType() const {
|
||||
return Type::String;
|
||||
virtual const TagType & getType() const {
|
||||
return Type;
|
||||
}
|
||||
|
||||
virtual void print(std::ostream& os, const std::string &) const {
|
||||
|
|
190
src/NBT/Tag.cpp
190
src/NBT/Tag.cpp
|
@ -41,176 +41,50 @@
|
|||
#include "LongArrayTag.hpp"
|
||||
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
|
||||
namespace MinedMap {
|
||||
namespace NBT {
|
||||
|
||||
std::shared_ptr<const Tag> Tag::readTag(Type type, Buffer *buffer) {
|
||||
switch (type) {
|
||||
case Type::End:
|
||||
return std::make_shared<EndTag>();
|
||||
const Tag::MakeType<EndTag> EndTag::Type("End");
|
||||
const Tag::MakeType<ByteTag> ByteTag::Type("Byte");
|
||||
const Tag::MakeType<ShortTag> ShortTag::Type("Short");
|
||||
const Tag::MakeType<IntTag> IntTag::Type("Int");
|
||||
const Tag::MakeType<LongTag> LongTag::Type("Long");
|
||||
const Tag::MakeType<FloatTag> FloatTag::Type("Float");
|
||||
const Tag::MakeType<DoubleTag> DoubleTag::Type("Double");
|
||||
const Tag::MakeType<ByteArrayTag> ByteArrayTag::Type("ByteArray");
|
||||
const Tag::MakeType<StringTag> StringTag::Type("String");
|
||||
const Tag::MakeType<ListTag> ListTag::Type("List");
|
||||
const Tag::MakeType<CompoundTag> CompoundTag::Type("Compound");
|
||||
const Tag::MakeType<IntArrayTag> IntArrayTag::Type("IntArray");
|
||||
const Tag::MakeType<LongArrayTag> LongArrayTag::Type("LongArray");
|
||||
|
||||
case Type::Byte:
|
||||
return std::make_shared<ByteTag>(buffer);
|
||||
|
||||
case Type::Short:
|
||||
return std::make_shared<ShortTag>(buffer);
|
||||
const std::vector<const TagType *> Tag::types = {
|
||||
&EndTag::Type,
|
||||
&ByteTag::Type,
|
||||
&ShortTag::Type,
|
||||
&IntTag::Type,
|
||||
&LongTag::Type,
|
||||
&FloatTag::Type,
|
||||
&DoubleTag::Type,
|
||||
&ByteArrayTag::Type,
|
||||
&StringTag::Type,
|
||||
&ListTag::Type,
|
||||
&CompoundTag::Type,
|
||||
&IntArrayTag::Type,
|
||||
&LongArrayTag::Type,
|
||||
};
|
||||
|
||||
case Type::Int:
|
||||
return std::make_shared<IntTag>(buffer);
|
||||
|
||||
case Type::Long:
|
||||
return std::make_shared<LongTag>(buffer);
|
||||
|
||||
case Type::Float:
|
||||
return std::make_shared<FloatTag>(buffer);
|
||||
|
||||
case Type::Double:
|
||||
return std::make_shared<DoubleTag>(buffer);
|
||||
|
||||
case Type::ByteArray:
|
||||
return std::make_shared<ByteArrayTag>(buffer);
|
||||
|
||||
case Type::String:
|
||||
return std::make_shared<StringTag>(buffer);
|
||||
|
||||
case Type::List:
|
||||
return readList(buffer);
|
||||
|
||||
case Type::Compound:
|
||||
return std::make_shared<CompoundTag>(buffer);
|
||||
|
||||
case Type::IntArray:
|
||||
return std::make_shared<IntArrayTag>(buffer);
|
||||
|
||||
case Type::LongArray:
|
||||
return std::make_shared<LongArrayTag>(buffer);
|
||||
|
||||
default:
|
||||
throw std::runtime_error("Tag::readTag: unknown tag type");
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<const Tag> Tag::readList(Buffer *buffer) {
|
||||
Type type = static_cast<Type>(buffer->get8());
|
||||
|
||||
switch (type) {
|
||||
case Type::End:
|
||||
return std::make_shared<ListTag<EndTag>>(type, buffer);
|
||||
|
||||
case Type::Byte:
|
||||
return std::make_shared<ListTag<ByteTag>>(type, buffer);
|
||||
|
||||
case Type::Short:
|
||||
return std::make_shared<ListTag<ShortTag>>(type, buffer);
|
||||
|
||||
case Type::Int:
|
||||
return std::make_shared<ListTag<IntTag>>(type, buffer);
|
||||
|
||||
case Type::Long:
|
||||
return std::make_shared<ListTag<LongTag>>(type, buffer);
|
||||
|
||||
case Type::Float:
|
||||
return std::make_shared<ListTag<FloatTag>>(type, buffer);
|
||||
|
||||
case Type::Double:
|
||||
return std::make_shared<ListTag<DoubleTag>>(type, buffer);
|
||||
|
||||
case Type::ByteArray:
|
||||
return std::make_shared<ListTag<ByteArrayTag>>(type, buffer);
|
||||
|
||||
case Type::String:
|
||||
return std::make_shared<ListTag<StringTag>>(type, buffer);
|
||||
|
||||
case Type::List:
|
||||
return std::make_shared<ListTag<ListTagBase>>(type, buffer);
|
||||
|
||||
case Type::Compound:
|
||||
return std::make_shared<ListTag<CompoundTag>>(type, buffer);
|
||||
|
||||
case Type::IntArray:
|
||||
return std::make_shared<ListTag<IntArrayTag>>(type, buffer);
|
||||
|
||||
case Type::LongArray:
|
||||
return std::make_shared<ListTag<LongArrayTag>>(type, buffer);
|
||||
|
||||
default:
|
||||
throw std::runtime_error("Tag::readList: unknown tag type");
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<std::string, std::shared_ptr<const Tag>> Tag::readNamedTag(Buffer *buffer) {
|
||||
Type type = static_cast<Type>(buffer->get8());
|
||||
if (type == Type::End)
|
||||
return std::make_pair("", std::shared_ptr<EndTag>(new EndTag()));
|
||||
const TagType &type = getTypeById(buffer->get8());
|
||||
if (type == EndTag::Type)
|
||||
return std::make_pair("", std::make_shared<EndTag>(buffer));
|
||||
|
||||
uint16_t len = buffer->get16();
|
||||
std::string name(reinterpret_cast<const char*>(buffer->get(len)), len);
|
||||
|
||||
return std::make_pair(name, readTag(type, buffer));
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, Tag::Type type) {
|
||||
switch (type) {
|
||||
case Tag::Type::End:
|
||||
os << "End";
|
||||
break;
|
||||
|
||||
case Tag::Type::Byte:
|
||||
os << "Byte";
|
||||
break;
|
||||
|
||||
case Tag::Type::Short:
|
||||
os << "Short";
|
||||
break;
|
||||
|
||||
case Tag::Type::Int:
|
||||
os << "Int";
|
||||
break;
|
||||
|
||||
case Tag::Type::Long:
|
||||
os << "Long";
|
||||
break;
|
||||
|
||||
case Tag::Type::Float:
|
||||
os << "Float";
|
||||
break;
|
||||
|
||||
case Tag::Type::Double:
|
||||
os << "Double";
|
||||
break;
|
||||
|
||||
case Tag::Type::ByteArray:
|
||||
os << "ByteArray";
|
||||
break;
|
||||
|
||||
case Tag::Type::String:
|
||||
os << "String";
|
||||
break;
|
||||
|
||||
case Tag::Type::List:
|
||||
os << "List";
|
||||
break;
|
||||
|
||||
case Tag::Type::Compound:
|
||||
os << "Compound";
|
||||
break;
|
||||
|
||||
case Tag::Type::IntArray:
|
||||
os << "IntArray";
|
||||
break;
|
||||
|
||||
case Tag::Type::LongArray:
|
||||
os << "LongArray";
|
||||
break;
|
||||
|
||||
default:
|
||||
os.setstate(std::ios_base::failbit);
|
||||
}
|
||||
|
||||
return os;
|
||||
return std::make_pair(name, type.read(buffer));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <vector>
|
||||
|
||||
#include "../Buffer.hpp"
|
||||
|
||||
|
@ -36,37 +37,61 @@
|
|||
namespace MinedMap {
|
||||
namespace NBT {
|
||||
|
||||
class Tag;
|
||||
|
||||
class TagType {
|
||||
public:
|
||||
TagType() = default;
|
||||
TagType(const TagType&) = delete;
|
||||
TagType & operator=(const TagType&) = delete;
|
||||
|
||||
virtual const char * getName() const = 0;
|
||||
virtual std::shared_ptr<const Tag> read(Buffer *buffer) const = 0;
|
||||
|
||||
bool operator==(const TagType &type) const {
|
||||
return this == &type;
|
||||
}
|
||||
};
|
||||
|
||||
class Tag {
|
||||
private:
|
||||
static std::shared_ptr<const Tag> readList(Buffer *buffer);
|
||||
static const std::vector<const TagType *> types;
|
||||
|
||||
public:
|
||||
enum class Type {
|
||||
End = 0,
|
||||
Byte = 1,
|
||||
Short = 2,
|
||||
Int = 3,
|
||||
Long = 4,
|
||||
Float = 5,
|
||||
Double = 6,
|
||||
ByteArray = 7,
|
||||
String = 8,
|
||||
List = 9,
|
||||
Compound = 10,
|
||||
IntArray = 11,
|
||||
LongArray = 12,
|
||||
protected:
|
||||
template<typename T>
|
||||
class MakeType : public TagType {
|
||||
private:
|
||||
const char *name;
|
||||
|
||||
public:
|
||||
MakeType(const char *name0) : name(name0) {}
|
||||
|
||||
virtual const char * getName() const {
|
||||
return name;
|
||||
}
|
||||
|
||||
virtual std::shared_ptr<const Tag> read(Buffer *buffer) const {
|
||||
return std::make_shared<T>(buffer);
|
||||
}
|
||||
};
|
||||
|
||||
static std::shared_ptr<const Tag> readTag(Type type, Buffer *buffer);
|
||||
|
||||
static const TagType & getTypeById(uint8_t id) {
|
||||
return *types.at(id);
|
||||
}
|
||||
|
||||
public:
|
||||
static std::pair<std::string, std::shared_ptr<const Tag>> readNamedTag(Buffer *buffer);
|
||||
|
||||
virtual Type getType() const = 0;
|
||||
virtual const TagType & getType() const = 0;
|
||||
virtual void print(std::ostream& os, const std::string &indent) const = 0;
|
||||
|
||||
virtual ~Tag() {}
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, Tag::Type type);
|
||||
static inline std::ostream& operator<<(std::ostream& os, const TagType &type) {
|
||||
return os << type.getName();
|
||||
}
|
||||
|
||||
static inline std::ostream& operator<<(std::ostream& os, const Tag &tag) {
|
||||
os << tag.getType() << " ";
|
||||
|
|
|
@ -44,8 +44,9 @@ Chunk::Chunk(const ChunkData *data) {
|
|||
std::shared_ptr<const NBT::ByteTag> lightPopulatedTag = level->get<NBT::ByteTag>("LightPopulated");
|
||||
bool lightPopulated = lightPopulatedTag && lightPopulatedTag->getValue();
|
||||
|
||||
sections = assertValue(level->get<NBT::ListTag<NBT::CompoundTag>>("Sections"));
|
||||
maxY = (assertValue(sections->back()->get<NBT::ByteTag>("Y"))->getValue() + 1) * SIZE;
|
||||
sections = assertValue(level->get<NBT::ListTag>("Sections"));
|
||||
const NBT::CompoundTag *lastSection = assertValue(dynamic_cast<const NBT::CompoundTag *>(sections->back().get()));
|
||||
maxY = (assertValue(lastSection->get<NBT::ByteTag>("Y"))->getValue() + 1) * SIZE;
|
||||
|
||||
|
||||
std::shared_ptr<const NBT::ByteArrayTag> biomeTag = assertValue(level->get<NBT::ByteArrayTag>("Biomes"));
|
||||
|
@ -65,7 +66,8 @@ Chunk::Chunk(const ChunkData *data) {
|
|||
std::memset(blockBlockLight.get(), 0, maxY * SIZE * SIZE / 2);
|
||||
|
||||
|
||||
for (auto §ion : *sections) {
|
||||
for (auto §ionTag : *sections) {
|
||||
const NBT::CompoundTag *section = assertValue(dynamic_cast<const NBT::CompoundTag *>(sectionTag.get()));
|
||||
std::shared_ptr<const NBT::ByteArrayTag> blocks = assertValue(section->get<NBT::ByteArrayTag>("Blocks"));
|
||||
std::shared_ptr<const NBT::ByteArrayTag> data = assertValue(section->get<NBT::ByteArrayTag>("Data"));
|
||||
size_t Y = assertValue(section->get<NBT::ByteTag>("Y"))->getValue();
|
||||
|
|
|
@ -52,7 +52,7 @@ public:
|
|||
|
||||
private:
|
||||
std::shared_ptr<const NBT::CompoundTag> level;
|
||||
std::shared_ptr<const NBT::ListTag<NBT::CompoundTag>> sections;
|
||||
std::shared_ptr<const NBT::ListTag> sections;
|
||||
|
||||
|
||||
unsigned maxY;
|
||||
|
@ -107,7 +107,7 @@ public:
|
|||
return *level;
|
||||
}
|
||||
|
||||
const NBT::ListTag<NBT::CompoundTag> & getSections() const {
|
||||
const NBT::ListTag & getSections() const {
|
||||
return *sections;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue