From 993617025bf30cece943de87f4db610e7b0e4d75 Mon Sep 17 00:00:00 2001 From: MatthewBeshay <92357869+MatthewBeshay@users.noreply.github.com> Date: Sun, 22 Mar 2026 10:05:26 +1100 Subject: [PATCH] TU19: merge Minecraft.World/IO --- Minecraft.World/IO/Files/FileHeader.h | 6 ++ Minecraft.World/IO/NBT/IntArrayTag.h | 3 +- Minecraft.World/IO/NBT/ListTag.h | 83 +++++++++---------- .../IO/Streams/DataInputStream.cpp | 11 +++ Minecraft.World/IO/Streams/DataInputStream.h | 5 +- .../IO/Streams/DataOutputStream.cpp | 11 +++ Minecraft.World/IO/Streams/DataOutputStream.h | 1 + Minecraft.World/IO/Streams/InputStream.cpp | 3 +- 8 files changed, 76 insertions(+), 47 deletions(-) diff --git a/Minecraft.World/IO/Files/FileHeader.h b/Minecraft.World/IO/Files/FileHeader.h index dd1633ba0..2e3e23854 100644 --- a/Minecraft.World/IO/Files/FileHeader.h +++ b/Minecraft.World/IO/Files/FileHeader.h @@ -37,6 +37,12 @@ enum ESaveVersions { // the compressed storage formats SAVE_FILE_VERSION_COMPRESSED_CHUNK_STORAGE, + // This is the version at which we added inhabited time to chunk (1.6.4) + SAVE_FILE_VERSION_CHUNK_INHABITED_TIME, + + // 4J Stu - If you add a new version here, the save conversion tool will + // also need updated to be able to read this new format + SAVE_FILE_VERSION_NEXT, }; diff --git a/Minecraft.World/IO/NBT/IntArrayTag.h b/Minecraft.World/IO/NBT/IntArrayTag.h index 9bce4b741..7b3a9c22f 100644 --- a/Minecraft.World/IO/NBT/IntArrayTag.h +++ b/Minecraft.World/IO/NBT/IntArrayTag.h @@ -43,7 +43,8 @@ public: IntArrayTag* o = (IntArrayTag*)obj; return ((data.data == NULL && o->data.data == NULL) || (data.data != NULL && data.length == o->data.length && - memcmp(data.data, o->data.data, data.length) == 0)); + memcmp(data.data, o->data.data, + data.length * sizeof(int)) == 0)); } return false; } diff --git a/Minecraft.World/IO/NBT/ListTag.h b/Minecraft.World/IO/NBT/ListTag.h index 611aadb0a..133c59c61 100644 --- a/Minecraft.World/IO/NBT/ListTag.h +++ b/Minecraft.World/IO/NBT/ListTag.h @@ -24,6 +24,7 @@ public: AUTO_VAR(itEnd, list.end()); for (AUTO_VAR(it, list.begin()); it != itEnd; it++) (*it)->write(dos); } + void load(DataInput* dis) { type = dis->readByte(); int size = dis->readInt(); @@ -46,7 +47,7 @@ public: } void print(char* prefix, std::ostream out) { - printf(prefix); + Tag::print(prefix, out); out << prefix << "{" << std::endl; @@ -54,13 +55,18 @@ public: strcpy(newPrefix, prefix); strcat(newPrefix, " "); AUTO_VAR(itEnd, list.end()); - for (AUTO_VAR(it, list.begin()); it != itEnd; it++) printf(newPrefix); + for (AUTO_VAR(it, list.begin()); it != itEnd; it++) { + (*it)->print(newPrefix, out); + } delete[] newPrefix; out << prefix << "}" << std::endl; } 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. + tag->setName(L""); list.push_back(tag); } @@ -75,7 +81,7 @@ public: } } - Tag* copy() { + virtual Tag* copy() { ListTag* res = new ListTag(getName()); res->type = type; AUTO_VAR(itEnd, list.end()); @@ -86,44 +92,35 @@ public: return res; } -#if 0 - bool equals(Object obj) - { - if (Tag::equals(obj)) - { - ListTag *o = (ListTag *) obj; - if (type == o->type) - { - bool equal = false; - if(list.size() == o->list.size()) - { - equal = true; - AUTO_VAR(itEnd, list.end()); - // 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()); it != o->list.end(); ++it2) - { - if((*it)->equals(*it2)) - { - thisMatches = true; - break; - } - } - if(!thisMatches) - { - equal = false; - break; - } - } - } + virtual bool equals(Tag* obj) { + if (Tag::equals(obj)) { + ListTag* o = (ListTag*)obj; + if (type == o->type) { + bool equal = false; + 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. + for (AUTO_VAR(it, list.begin()); it != itEnd; ++it) { + bool thisMatches = false; + for (AUTO_VAR(it2, o->list.begin()); + it2 != o->list.end(); ++it2) { + if ((*it)->equals(*it2)) { + thisMatches = true; + break; + } + } + if (!thisMatches) { + equal = false; + break; + } + } + } - //return list->equals(o->list); - return equal; - } - } - return false; - } -#endif -}; + return equal; + } + } + return false; + } +}; \ No newline at end of file diff --git a/Minecraft.World/IO/Streams/DataInputStream.cpp b/Minecraft.World/IO/Streams/DataInputStream.cpp index b63620c0b..bb2def07c 100644 --- a/Minecraft.World/IO/Streams/DataInputStream.cpp +++ b/Minecraft.World/IO/Streams/DataInputStream.cpp @@ -323,6 +323,17 @@ short DataInputStream::readShort() { return (short)((a << 8) | (b & 0xff)); } +unsigned short DataInputStream::readUnsignedShort() { + if (stream == NULL) { + app.DebugPrintf( + "DataInputStream::readUnsignedShort() but underlying stream is NULL\n"); + return 0; + } + int a = stream->read(); + int b = stream->read(); + return static_cast(((a & 0xff) << 8) | (b & 0xff)); +} + // Reads in a string that has been encoded using a modified UTF-8 format. The // general contract of readUTF is that it reads a representation of a Unicode // character string encoded in modified UTF-8 format; this string of characters diff --git a/Minecraft.World/IO/Streams/DataInputStream.h b/Minecraft.World/IO/Streams/DataInputStream.h index f5365cc79..c4cdd8901 100644 --- a/Minecraft.World/IO/Streams/DataInputStream.h +++ b/Minecraft.World/IO/Streams/DataInputStream.h @@ -24,12 +24,13 @@ public: virtual double readDouble(); virtual float readFloat(); virtual int readInt(); - virtual int64_t readLong(); + virtual __int64 readLong(); virtual short readShort(); + virtual unsigned short readUnsignedShort(); virtual std::wstring readUTF(); void deleteChildStream(); virtual int readUTFChar(); virtual PlayerUID readPlayerUID(); // 4J Added - virtual int64_t skip(int64_t n); + virtual __int64 skip(__int64 n); virtual int skipBytes(int n); }; \ No newline at end of file diff --git a/Minecraft.World/IO/Streams/DataOutputStream.cpp b/Minecraft.World/IO/Streams/DataOutputStream.cpp index b763c7331..c51a666c4 100644 --- a/Minecraft.World/IO/Streams/DataOutputStream.cpp +++ b/Minecraft.World/IO/Streams/DataOutputStream.cpp @@ -146,6 +146,17 @@ void DataOutputStream::writeShort(short a) { written += 2; } +void DataOutputStream::writeUnsignedShort(unsigned short a) { + if (stream == NULL) { + app.DebugPrintf( + "DataOutputStream::writeUnsignedShort() but underlying stream is NULL\n"); + return; + } + stream->write(static_cast((a >> 8) & 0xff)); + stream->write(static_cast(a & 0xff)); + written += 2; +} + // Writes a char to the underlying output stream as a 2-byte value, high byte // first. If no exception is thrown, the counter written is incremented by 2. // Parameters: diff --git a/Minecraft.World/IO/Streams/DataOutputStream.h b/Minecraft.World/IO/Streams/DataOutputStream.h index 113ae561a..a261113ee 100644 --- a/Minecraft.World/IO/Streams/DataOutputStream.h +++ b/Minecraft.World/IO/Streams/DataOutputStream.h @@ -29,6 +29,7 @@ public: virtual void writeInt(int a); virtual void writeLong(int64_t a); virtual void writeShort(short a); + virtual void writeUnsignedShort(unsigned short a); virtual void writeChar(wchar_t a); virtual void writeChars(const std::wstring& a); virtual void writeBoolean(bool b); diff --git a/Minecraft.World/IO/Streams/InputStream.cpp b/Minecraft.World/IO/Streams/InputStream.cpp index 5fd4f06d2..28a732662 100644 --- a/Minecraft.World/IO/Streams/InputStream.cpp +++ b/Minecraft.World/IO/Streams/InputStream.cpp @@ -4,5 +4,6 @@ #include "InputStream.h" InputStream* InputStream::getResourceAsStream(const std::wstring& fileName) { - return new FileInputStream(File(fileName)); + File file(fileName); + return file.exists() ? new FileInputStream(file) : NULL; } \ No newline at end of file