mirror of
https://github.com/neocturne/MinedMap.git
synced 2025-03-05 17:44:52 +01:00
More convenient tag access
This commit is contained in:
parent
cbe6461882
commit
a6a2a62812
8 changed files with 103 additions and 19 deletions
|
@ -40,5 +40,11 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
World::Region region(argv[1]);
|
World::Region region(argv[1]);
|
||||||
|
|
||||||
|
const World::Chunk &chunk = *region(0, 0);
|
||||||
|
|
||||||
|
for (auto &entry : std::dynamic_pointer_cast<const NBT::CompoundTag>(chunk->get("Level"))->getValues()) {
|
||||||
|
std::cout << entry.first << " " << entry.second->getType() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,15 +39,15 @@ class CompoundTag : public Tag {
|
||||||
private:
|
private:
|
||||||
friend class Tag;
|
friend class Tag;
|
||||||
|
|
||||||
std::unordered_map<std::string, std::shared_ptr<Tag>> value;
|
std::unordered_map<std::string, std::shared_ptr<const Tag>> values;
|
||||||
|
|
||||||
CompoundTag(Buffer *buffer) {
|
CompoundTag(Buffer *buffer) {
|
||||||
while (true) {
|
while (true) {
|
||||||
std::pair<std::string, std::shared_ptr<Tag>> v = Tag::readNamedTag(buffer);
|
std::pair<std::string, std::shared_ptr<const Tag>> v = Tag::readNamedTag(buffer);
|
||||||
if (v.second->getType() == Type::End)
|
if (v.second->getType() == Type::End)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
value.insert(std::move(v));
|
values.insert(std::move(v));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,6 +55,22 @@ public:
|
||||||
virtual Type getType() const {
|
virtual Type getType() const {
|
||||||
return Type::Compound;
|
return Type::Compound;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::unordered_map<std::string, std::shared_ptr<const Tag>> & getValues() const {
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::shared_ptr<const Tag> & get(const std::string &key) const {
|
||||||
|
return values.at(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Args> const std::shared_ptr<const Tag> & get(const std::string &key, const Args &...args) const {
|
||||||
|
std::shared_ptr<const CompoundTag> tag = std::dynamic_pointer_cast<const CompoundTag>(get(key));
|
||||||
|
if (!tag)
|
||||||
|
return std::shared_ptr<Tag>(nullptr);
|
||||||
|
|
||||||
|
tag->get(args...);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ class ListTag : public Tag {
|
||||||
private:
|
private:
|
||||||
friend class Tag;
|
friend class Tag;
|
||||||
|
|
||||||
std::vector<std::shared_ptr<Tag>> value;
|
std::vector<std::shared_ptr<const Tag>> value;
|
||||||
|
|
||||||
|
|
||||||
ListTag(Buffer *buffer) {
|
ListTag(Buffer *buffer) {
|
||||||
|
|
|
@ -49,6 +49,10 @@ public:
|
||||||
virtual Type getType() const {
|
virtual Type getType() const {
|
||||||
return Type::String;
|
return Type::String;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string & getValue() const {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@
|
||||||
namespace MinedMap {
|
namespace MinedMap {
|
||||||
namespace NBT {
|
namespace NBT {
|
||||||
|
|
||||||
std::shared_ptr<Tag> Tag::readTag(Type type, Buffer *buffer) {
|
std::shared_ptr<const Tag> Tag::readTag(Type type, Buffer *buffer) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Type::End:
|
case Type::End:
|
||||||
return std::shared_ptr<EndTag>(new EndTag());
|
return std::shared_ptr<EndTag>(new EndTag());
|
||||||
|
@ -89,7 +89,7 @@ std::shared_ptr<Tag> Tag::readTag(Type type, Buffer *buffer) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<std::string, std::shared_ptr<Tag>> Tag::readNamedTag(Buffer *buffer) {
|
std::pair<std::string, std::shared_ptr<const Tag>> Tag::readNamedTag(Buffer *buffer) {
|
||||||
Type type = static_cast<Type>(buffer->get());
|
Type type = static_cast<Type>(buffer->get());
|
||||||
if (type == Type::End)
|
if (type == Type::End)
|
||||||
return std::make_pair("", std::shared_ptr<EndTag>(new EndTag()));
|
return std::make_pair("", std::shared_ptr<EndTag>(new EndTag()));
|
||||||
|
@ -101,5 +101,62 @@ std::pair<std::string, std::shared_ptr<Tag>> Tag::readNamedTag(Buffer *buffer) {
|
||||||
return std::make_pair(name, readTag(type, buffer));
|
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;
|
||||||
|
|
||||||
|
default:
|
||||||
|
os.setstate(std::ios_base::failbit);
|
||||||
|
}
|
||||||
|
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
#include "../Buffer.hpp"
|
#include "../Buffer.hpp"
|
||||||
|
|
||||||
|
@ -52,14 +53,16 @@ public:
|
||||||
IntArray = 11,
|
IntArray = 11,
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::shared_ptr<Tag> readTag(Type type, Buffer *buffer);
|
static std::shared_ptr<const Tag> readTag(Type type, Buffer *buffer);
|
||||||
|
|
||||||
static std::pair<std::string, std::shared_ptr<Tag>> readNamedTag(Buffer *buffer);
|
static std::pair<std::string, std::shared_ptr<const Tag>> readNamedTag(Buffer *buffer);
|
||||||
|
|
||||||
virtual Type getType() const = 0;
|
virtual Type getType() const = 0;
|
||||||
|
|
||||||
virtual ~Tag() {}
|
virtual ~Tag() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& os, Tag::Type type);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
namespace MinedMap {
|
namespace MinedMap {
|
||||||
namespace World {
|
namespace World {
|
||||||
|
|
||||||
std::tuple<UniqueCPtr<uint8_t[]>, size_t> Chunk::inflateChunk(uint8_t *data, size_t len) {
|
std::pair<UniqueCPtr<uint8_t[]>, size_t> Chunk::inflateChunk(uint8_t *data, size_t len) {
|
||||||
size_t outlen = 0;
|
size_t outlen = 0;
|
||||||
uint8_t *output = nullptr;
|
uint8_t *output = nullptr;
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ std::tuple<UniqueCPtr<uint8_t[]>, size_t> Chunk::inflateChunk(uint8_t *data, siz
|
||||||
|
|
||||||
inflateEnd(&stream);
|
inflateEnd(&stream);
|
||||||
|
|
||||||
return std::make_tuple(UniqueCPtr<uint8_t[]>(output), stream.total_out);
|
return std::make_pair(UniqueCPtr<uint8_t[]>(output), stream.total_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
Chunk::Chunk(uint8_t *buffer, size_t buflen) {
|
Chunk::Chunk(uint8_t *buffer, size_t buflen) {
|
||||||
|
@ -89,12 +89,12 @@ Chunk::Chunk(uint8_t *buffer, size_t buflen) {
|
||||||
std::cerr << "Chunk has size " << size << " (" << len << " inflated)" << std::endl;
|
std::cerr << "Chunk has size " << size << " (" << len << " inflated)" << std::endl;
|
||||||
|
|
||||||
Buffer nbt(data.get(), len);
|
Buffer nbt(data.get(), len);
|
||||||
|
std::pair<std::string, std::shared_ptr<const NBT::Tag>> tag = NBT::Tag::readNamedTag(&nbt);
|
||||||
|
|
||||||
std::pair<std::string, std::shared_ptr<NBT::Tag>> tag = NBT::Tag::readNamedTag(&nbt);
|
std::shared_ptr<const NBT::CompoundTag>::operator=(std::dynamic_pointer_cast<const NBT::CompoundTag>(tag.second));
|
||||||
if (tag.first != "")
|
|
||||||
throw std::invalid_argument("non-empty root tag");
|
|
||||||
|
|
||||||
content = std::move(tag.second);
|
if (!(*this) || tag.first != "")
|
||||||
|
throw std::invalid_argument("invalid root tag");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
|
|
||||||
|
|
||||||
#include "../UniqueCPtr.hpp"
|
#include "../UniqueCPtr.hpp"
|
||||||
#include "../NBT/Tag.hpp"
|
#include "../NBT/CompoundTag.hpp"
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
@ -37,14 +37,12 @@
|
||||||
namespace MinedMap {
|
namespace MinedMap {
|
||||||
namespace World {
|
namespace World {
|
||||||
|
|
||||||
class Chunk {
|
class Chunk : public std::shared_ptr<const NBT::CompoundTag> {
|
||||||
public:
|
public:
|
||||||
static const size_t SIZE = 16;
|
static const size_t SIZE = 16;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static std::tuple<UniqueCPtr<uint8_t[]>, size_t> inflateChunk(uint8_t *data, size_t len);
|
static std::pair<UniqueCPtr<uint8_t[]>, size_t> inflateChunk(uint8_t *data, size_t len);
|
||||||
|
|
||||||
std::shared_ptr<NBT::Tag> content;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Chunk(uint8_t *buffer, size_t buflen);
|
Chunk(uint8_t *buffer, size_t buflen);
|
||||||
|
|
Loading…
Add table
Reference in a new issue