mirror of
https://github.com/4jcraft/4jcraft.git
synced 2026-05-12 03:17:13 +00:00
TU19: update NBT library
This commit is contained in:
parent
993617025b
commit
8df2c2bb47
|
|
@ -5,18 +5,24 @@
|
|||
class ByteArrayTag : public Tag {
|
||||
public:
|
||||
byteArray data;
|
||||
bool m_ownData;
|
||||
|
||||
ByteArrayTag(const std::wstring& name) : Tag(name) {}
|
||||
ByteArrayTag(const std::wstring& name, byteArray data) : Tag(name) {
|
||||
ByteArrayTag(const std::wstring& name) : Tag(name) { m_ownData = false; }
|
||||
ByteArrayTag(const std::wstring& name, byteArray data, bool ownData = false)
|
||||
: Tag(name) {
|
||||
this->data = data;
|
||||
m_ownData = ownData;
|
||||
} // 4J - added ownData param
|
||||
~ByteArrayTag() {
|
||||
if (m_ownData) delete[] data.data;
|
||||
}
|
||||
|
||||
void write(DataOutput* dos) {
|
||||
dos->writeInt(data.length);
|
||||
dos->write(data);
|
||||
}
|
||||
|
||||
void load(DataInput* dis) {
|
||||
void load(DataInput* dis, int tagDepth) {
|
||||
int length = dis->readInt();
|
||||
|
||||
if (data.data) delete[] data.data;
|
||||
|
|
@ -45,6 +51,6 @@ public:
|
|||
Tag* copy() {
|
||||
byteArray cp = byteArray(data.length);
|
||||
System::arraycopy(data, 0, &cp, 0, data.length);
|
||||
return new ByteArrayTag(getName(), cp);
|
||||
return new ByteArrayTag(getName(), cp, true);
|
||||
}
|
||||
};
|
||||
|
|
@ -10,7 +10,7 @@ public:
|
|||
}
|
||||
|
||||
void write(DataOutput* dos) { dos->writeByte(data); }
|
||||
void load(DataInput* dis) { data = dis->readByte(); }
|
||||
void load(DataInput* dis, int tagDepth) { data = dis->readByte(); }
|
||||
|
||||
uint8_t getId() { return TAG_Byte; }
|
||||
std::wstring toString() {
|
||||
|
|
|
|||
|
|
@ -28,7 +28,15 @@ public:
|
|||
dos->writeByte(Tag::TAG_End);
|
||||
}
|
||||
|
||||
void load(DataInput* dis) {
|
||||
void load(DataInput* dis, int tagDepth) {
|
||||
if (tagDepth > MAX_DEPTH) {
|
||||
#ifndef _CONTENT_PACKAGE
|
||||
printf("Tried to read NBT tag with too high complexity, depth > %d",
|
||||
MAX_DEPTH);
|
||||
__debugbreak();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
tags.clear();
|
||||
Tag* tag;
|
||||
while ((tag = Tag::readNamedTag(dis))->getId() != Tag::TAG_End) {
|
||||
|
|
@ -52,123 +60,121 @@ public:
|
|||
|
||||
uint8_t getId() { return TAG_Compound; }
|
||||
|
||||
void put(const wchar_t* name, Tag* tag) {
|
||||
tags[name] = tag->setName(std::wstring(name));
|
||||
void put(const std::wstring& name, Tag* tag) {
|
||||
tags[name] = tag->setName(name);
|
||||
}
|
||||
|
||||
void putByte(const wchar_t* name, uint8_t value) {
|
||||
void putByte(const std::wstring& name, uint8_t value) {
|
||||
tags[name] = (new ByteTag(name, value));
|
||||
}
|
||||
|
||||
void putShort(const wchar_t* name, short value) {
|
||||
void putShort(const std::wstring& name, short value) {
|
||||
tags[name] = (new ShortTag(name, value));
|
||||
}
|
||||
|
||||
void putInt(const wchar_t* name, int value) {
|
||||
void putInt(const std::wstring& name, int value) {
|
||||
tags[name] = (new IntTag(name, value));
|
||||
}
|
||||
|
||||
void putLong(const wchar_t* name, int64_t value) {
|
||||
void putLong(const std::wstring& name, int64_t value) {
|
||||
tags[name] = (new LongTag(name, value));
|
||||
}
|
||||
|
||||
void putFloat(const wchar_t* name, float value) {
|
||||
void putFloat(const std::wstring& name, float value) {
|
||||
tags[name] = (new FloatTag(name, value));
|
||||
}
|
||||
|
||||
void putDouble(const wchar_t* name, double value) {
|
||||
void putDouble(const std::wstring& name, double value) {
|
||||
tags[name] = (new DoubleTag(name, value));
|
||||
}
|
||||
|
||||
void putString(const wchar_t* name, const std::wstring& value) {
|
||||
void putString(const std::wstring& name, const std::wstring& value) {
|
||||
tags[name] = (new StringTag(name, value));
|
||||
}
|
||||
|
||||
void putByteArray(const wchar_t* name, byteArray value) {
|
||||
void putByteArray(const std::wstring& name, byteArray value) {
|
||||
tags[name] = (new ByteArrayTag(name, value));
|
||||
}
|
||||
|
||||
void putIntArray(const wchar_t* name, intArray value) {
|
||||
void putIntArray(const std::wstring& name, intArray value) {
|
||||
tags[name] = (new IntArrayTag(name, value));
|
||||
}
|
||||
|
||||
void putCompound(const wchar_t* name, CompoundTag* value) {
|
||||
void putCompound(const std::wstring& name, CompoundTag* value) {
|
||||
tags[name] = value->setName(std::wstring(name));
|
||||
}
|
||||
|
||||
void putBoolean(const wchar_t* string, bool val) {
|
||||
putByte(string,
|
||||
val ? static_cast<uint8_t>(1) : static_cast<uint8_t>(0));
|
||||
void putBoolean(const std::wstring& name, bool val) {
|
||||
putByte(name, val ? (uint8_t)1 : 0);
|
||||
}
|
||||
|
||||
Tag* get(const wchar_t* name) {
|
||||
Tag* get(const std::wstring& name) {
|
||||
AUTO_VAR(it, tags.find(name));
|
||||
if (it != tags.end()) return it->second;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool contains(const wchar_t* name) { return tags.find(name) != tags.end(); }
|
||||
bool contains(const std::wstring& name) {
|
||||
return tags.find(name) != tags.end();
|
||||
}
|
||||
|
||||
uint8_t getByte(const wchar_t* name) {
|
||||
uint8_t getByte(const std::wstring& name) {
|
||||
if (tags.find(name) == tags.end()) return (uint8_t)0;
|
||||
return ((ByteTag*)tags[name])->data;
|
||||
}
|
||||
|
||||
short getShort(const wchar_t* name) {
|
||||
short getShort(const std::wstring& name) {
|
||||
if (tags.find(name) == tags.end()) return (short)0;
|
||||
return ((ShortTag*)tags[name])->data;
|
||||
}
|
||||
|
||||
int getInt(const wchar_t* name) {
|
||||
int getInt(const std::wstring& name) {
|
||||
if (tags.find(name) == tags.end()) return (int)0;
|
||||
return ((IntTag*)tags[name])->data;
|
||||
}
|
||||
|
||||
int64_t getLong(const wchar_t* name) {
|
||||
int64_t getLong(const std::wstring& name) {
|
||||
if (tags.find(name) == tags.end()) return (int64_t)0;
|
||||
return ((LongTag*)tags[name])->data;
|
||||
}
|
||||
|
||||
float getFloat(const wchar_t* name) {
|
||||
float getFloat(const std::wstring& name) {
|
||||
if (tags.find(name) == tags.end()) return (float)0;
|
||||
return ((FloatTag*)tags[name])->data;
|
||||
}
|
||||
|
||||
double getDouble(const wchar_t* name) {
|
||||
double getDouble(const std::wstring& name) {
|
||||
if (tags.find(name) == tags.end()) return (double)0;
|
||||
return ((DoubleTag*)tags[name])->data;
|
||||
}
|
||||
|
||||
std::wstring getString(const wchar_t* name) {
|
||||
std::wstring getString(const std::wstring& name) {
|
||||
if (tags.find(name) == tags.end()) return std::wstring(L"");
|
||||
return ((StringTag*)tags[name])->data;
|
||||
}
|
||||
|
||||
byteArray getByteArray(const wchar_t* name) {
|
||||
byteArray getByteArray(const std::wstring& name) {
|
||||
if (tags.find(name) == tags.end()) return byteArray();
|
||||
return ((ByteArrayTag*)tags[name])->data;
|
||||
}
|
||||
|
||||
intArray getIntArray(const wchar_t* name) {
|
||||
if (tags.find(name) == tags.end()) return intArray(0);
|
||||
intArray getIntArray(const std::wstring& name) {
|
||||
if (tags.find(name) == tags.end()) return intArray();
|
||||
return ((IntArrayTag*)tags[name])->data;
|
||||
}
|
||||
|
||||
CompoundTag* getCompound(const wchar_t* name) {
|
||||
CompoundTag* getCompound(const std::wstring& name) {
|
||||
if (tags.find(name) == tags.end()) return new CompoundTag(name);
|
||||
return (CompoundTag*)tags[name];
|
||||
}
|
||||
|
||||
ListTag<Tag>* getList(const wchar_t* name) {
|
||||
// 4jcraft changed this function to not do a c style cast
|
||||
// of a templated class
|
||||
auto it = tags.find(name);
|
||||
if (it == tags.end()) return new ListTag<Tag>(name);
|
||||
return dynamic_cast<ListTag<Tag>*>(it->second);
|
||||
ListTag<Tag>* getList(const std::wstring& name) {
|
||||
if (tags.find(name) == tags.end()) return new ListTag<Tag>(name);
|
||||
return (ListTag<Tag>*)tags[name];
|
||||
}
|
||||
|
||||
bool getBoolean(const wchar_t* string) {
|
||||
return getByte(string) != static_cast<uint8_t>(0);
|
||||
bool getBoolean(const std::wstring& std::string) {
|
||||
return getByte(std::string) != 0;
|
||||
}
|
||||
|
||||
void remove(const std::wstring& name) {
|
||||
|
|
@ -186,21 +192,21 @@ public:
|
|||
|
||||
void print(char* prefix, std::ostream out) {
|
||||
/*
|
||||
Tag::print(prefix, out);
|
||||
out << prefix << "{" << std::endl;
|
||||
Tag::print(prefix, out);
|
||||
out << prefix << "{" << endl;
|
||||
|
||||
char *newPrefix = new char[ strlen(prefix) + 4 ];
|
||||
strcpy( newPrefix, prefix);
|
||||
strcat( newPrefix, " ");
|
||||
|
||||
AUTO_VAR(itEnd, tags.end());
|
||||
for( std::unordered_map<string, Tag *>::iterator it = tags.begin(); it
|
||||
!= itEnd; it++ )
|
||||
for( unordered_map<string, Tag *>::iterator it = tags.begin(); it !=
|
||||
itEnd; it++ )
|
||||
{
|
||||
it->second->print(newPrefix, out);
|
||||
it->second->print(newPrefix, out);
|
||||
}
|
||||
delete[] newPrefix;
|
||||
out << prefix << "}" << std::endl;
|
||||
out << prefix << "}" << endl;
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ public:
|
|||
}
|
||||
|
||||
void write(DataOutput* dos) { dos->writeDouble(data); }
|
||||
void load(DataInput* dis) { data = dis->readDouble(); }
|
||||
void load(DataInput* dis, int tagDepth) { data = dis->readDouble(); }
|
||||
|
||||
uint8_t getId() { return TAG_Double; }
|
||||
std::wstring toString() {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ public:
|
|||
EndTag() : Tag(L"") {}
|
||||
EndTag(const std::wstring& name) : Tag(name) {}
|
||||
|
||||
void load(DataInput* dis) {};
|
||||
void load(DataInput* dis, int tagDepth) {};
|
||||
void write(DataOutput* dos) {};
|
||||
|
||||
uint8_t getId() { return TAG_End; }
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ public:
|
|||
}
|
||||
|
||||
void write(DataOutput* dos) { dos->writeFloat(data); }
|
||||
void load(DataInput* dis) { data = dis->readFloat(); }
|
||||
void load(DataInput* dis, int tagDepth) { data = dis->readFloat(); }
|
||||
|
||||
uint8_t getId() { return TAG_Float; }
|
||||
std::wstring toString() {
|
||||
|
|
|
|||
|
|
@ -7,12 +7,14 @@ class IntArrayTag : public Tag {
|
|||
public:
|
||||
intArray data;
|
||||
|
||||
IntArrayTag(const std::wstring& name) : Tag(name) {}
|
||||
IntArrayTag(const std::wstring& name) : Tag(name) { data = intArray(); }
|
||||
|
||||
IntArrayTag(const std::wstring& name, intArray data) : Tag(name) {
|
||||
this->data = data;
|
||||
}
|
||||
|
||||
~IntArrayTag() { delete[] data.data; }
|
||||
|
||||
void write(DataOutput* dos) {
|
||||
dos->writeInt(data.length);
|
||||
for (unsigned int i = 0; i < data.length; i++) {
|
||||
|
|
@ -20,7 +22,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void load(DataInput* dis) {
|
||||
void load(DataInput* dis, int tagDepth) {
|
||||
int length = dis->readInt();
|
||||
|
||||
if (data.data) delete[] data.data;
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ public:
|
|||
}
|
||||
|
||||
void write(DataOutput* dos) { dos->writeInt(data); }
|
||||
void load(DataInput* dis) { data = dis->readInt(); }
|
||||
void load(DataInput* dis, int tagDepth) { data = dis->readInt(); }
|
||||
|
||||
uint8_t getId() { return TAG_Int; }
|
||||
std::wstring toString() {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
#pragma once
|
||||
|
||||
#include "Tag.h"
|
||||
|
||||
template <class T>
|
||||
|
|
@ -25,14 +24,22 @@ public:
|
|||
for (AUTO_VAR(it, list.begin()); it != itEnd; it++) (*it)->write(dos);
|
||||
}
|
||||
|
||||
void load(DataInput* dis) {
|
||||
void load(DataInput* dis, int tagDepth) {
|
||||
if (tagDepth > MAX_DEPTH) {
|
||||
#ifndef _CONTENT_PACKAGE
|
||||
printf("Tried to read NBT tag with too high complexity, depth > %d",
|
||||
MAX_DEPTH);
|
||||
__debugbreak();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
type = dis->readByte();
|
||||
int size = dis->readInt();
|
||||
|
||||
list.clear();
|
||||
for (int i = 0; i < size; i++) {
|
||||
Tag* tag = Tag::newTag(type, L"");
|
||||
tag->load(dis);
|
||||
tag->load(dis, tagDepth);
|
||||
list.push_back(tag);
|
||||
}
|
||||
}
|
||||
|
|
@ -55,9 +62,8 @@ public:
|
|||
strcpy(newPrefix, prefix);
|
||||
strcat(newPrefix, " ");
|
||||
AUTO_VAR(itEnd, list.end());
|
||||
for (AUTO_VAR(it, list.begin()); it != itEnd; it++) {
|
||||
for (AUTO_VAR(it, list.begin()); it != itEnd; it++)
|
||||
(*it)->print(newPrefix, out);
|
||||
}
|
||||
delete[] newPrefix;
|
||||
out << prefix << "}" << std::endl;
|
||||
}
|
||||
|
|
@ -65,7 +71,10 @@ public:
|
|||
void add(T* tag) {
|
||||
type = tag->getId();
|
||||
// 4J: List tag write/load doesn't preserve tag names so remove them so
|
||||
// we can safely do comparisons. This is the least invasive fix.
|
||||
// we can safely do comparisons There are a few ways I could have fixed
|
||||
// this but this seems the least invasive, most complete fix (covers
|
||||
// other items that also use list tags and require equality checks to
|
||||
// work) considering we can't change the write/load functions.
|
||||
tag->setName(L"");
|
||||
list.push_back(tag);
|
||||
}
|
||||
|
|
@ -100,8 +109,9 @@ public:
|
|||
if (list.size() == o->list.size()) {
|
||||
equal = true;
|
||||
AUTO_VAR(itEnd, list.end());
|
||||
// 4J Stu - Pretty inefficient method, but acceptable for
|
||||
// how small and infrequent these comparisons are.
|
||||
// 4J Stu - Pretty inefficient method, but I think we can
|
||||
// live with it give how often it will happen, and the small
|
||||
// sizes of the data sets
|
||||
for (AUTO_VAR(it, list.begin()); it != itEnd; ++it) {
|
||||
bool thisMatches = false;
|
||||
for (AUTO_VAR(it2, o->list.begin());
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ public:
|
|||
}
|
||||
|
||||
void write(DataOutput* dos) { dos->writeLong(data); }
|
||||
void load(DataInput* dis) { data = dis->readLong(); }
|
||||
void load(DataInput* dis, int tagDepth) { data = dis->readLong(); }
|
||||
|
||||
uint8_t getId() { return TAG_Long; }
|
||||
std::wstring toString() {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ public:
|
|||
}
|
||||
|
||||
void write(DataOutput* dos) { dos->writeShort(data); }
|
||||
void load(DataInput* dis) { data = dis->readShort(); }
|
||||
void load(DataInput* dis, int tagDepth) { data = dis->readShort(); }
|
||||
|
||||
uint8_t getId() { return TAG_Short; }
|
||||
std::wstring toString() {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ public:
|
|||
|
||||
void write(DataOutput* dos) { dos->writeUTF(data); }
|
||||
|
||||
void load(DataInput* dis) { data = dis->readUTF(); }
|
||||
void load(DataInput* dis, int tagDepth) { data = dis->readUTF(); }
|
||||
|
||||
uint8_t getId() { return TAG_String; }
|
||||
|
||||
|
|
|
|||
|
|
@ -61,7 +61,9 @@ Tag* Tag::setName(const std::wstring& name) {
|
|||
return this;
|
||||
}
|
||||
|
||||
Tag* Tag::readNamedTag(DataInput* dis) {
|
||||
Tag* Tag::readNamedTag(DataInput* dis) { return readNamedTag(dis, 0); }
|
||||
|
||||
Tag* Tag::readNamedTag(DataInput* dis, int tagDepth) {
|
||||
uint8_t type = dis->readByte();
|
||||
if (static_cast<int>(type) == 0) return new EndTag();
|
||||
|
||||
|
|
@ -82,7 +84,7 @@ Tag* Tag::readNamedTag(DataInput* dis) {
|
|||
// byte[] bytes = new uint8_t[length];
|
||||
// dis.readFully(bytes);
|
||||
|
||||
tag->load(dis);
|
||||
tag->load(dis, tagDepth);
|
||||
return tag;
|
||||
}
|
||||
|
||||
|
|
@ -156,4 +158,4 @@ const wchar_t* Tag::getTagName(uint8_t type) {
|
|||
return L"TAG_Compound";
|
||||
}
|
||||
return L"UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
|
@ -16,6 +16,7 @@ public:
|
|||
static const uint8_t TAG_List = static_cast<uint8_t>(9);
|
||||
static const uint8_t TAG_Compound = static_cast<uint8_t>(10);
|
||||
static const uint8_t TAG_Int_Array = static_cast<uint8_t>(11);
|
||||
static const int MAX_DEPTH = static_cast<uint8_t>(512);
|
||||
|
||||
private:
|
||||
std::wstring name;
|
||||
|
|
@ -25,7 +26,7 @@ protected:
|
|||
|
||||
public:
|
||||
virtual void write(DataOutput* dos) = 0;
|
||||
virtual void load(DataInput* dis) = 0;
|
||||
virtual void load(DataInput* dis, int tagDepth) = 0;
|
||||
virtual std::wstring toString() = 0;
|
||||
virtual uint8_t getId() = 0;
|
||||
void print(std::ostream out);
|
||||
|
|
@ -33,6 +34,7 @@ public:
|
|||
std::wstring getName();
|
||||
Tag* setName(const std::wstring& name);
|
||||
static Tag* readNamedTag(DataInput* dis);
|
||||
static Tag* readNamedTag(DataInput* dis, int tagDepth);
|
||||
static void writeNamedTag(Tag* tag, DataOutput* dos);
|
||||
static Tag* newTag(uint8_t type, const std::wstring& name);
|
||||
static const wchar_t* getTagName(uint8_t type);
|
||||
|
|
|
|||
Loading…
Reference in a new issue