From 22757b4b517ecc3dafa138922bf8fe6fa4052fe6 Mon Sep 17 00:00:00 2001 From: notmatthewbeshay <92357869+NotMachow@users.noreply.github.com> Date: Mon, 9 Mar 2026 23:57:50 +1100 Subject: [PATCH] Remove HANDLE from zoned chunk storage headers --- Minecraft.World/IO/NBT/NbtSlotFile.cpp | 100 ++++++++++++++------- Minecraft.World/IO/NBT/NbtSlotFile.h | 4 +- Minecraft.World/Level/Storage/ZoneFile.cpp | 32 ++++++- Minecraft.World/Level/Storage/ZoneFile.h | 4 +- Minecraft.World/Level/Storage/ZoneIO.cpp | 26 ++++-- Minecraft.World/Level/Storage/ZoneIO.h | 6 +- 6 files changed, 127 insertions(+), 45 deletions(-) diff --git a/Minecraft.World/IO/NBT/NbtSlotFile.cpp b/Minecraft.World/IO/NBT/NbtSlotFile.cpp index 3a7cceacf..a373667fe 100644 --- a/Minecraft.World/IO/NBT/NbtSlotFile.cpp +++ b/Minecraft.World/IO/NBT/NbtSlotFile.cpp @@ -2,6 +2,47 @@ #include "../Files/File.h" #include "NbtSlotFile.h" +namespace +{ + std::FILE *OpenBinaryFileForReadWrite(const File &file) + { +#if defined(_WIN32) + std::FILE *stream = _wfopen(file.getPath().c_str(), L"r+b"); + if (stream == NULL) + { + stream = _wfopen(file.getPath().c_str(), L"w+b"); + } +#else + const std::string nativePath = wstringtofilename(file.getPath()); + std::FILE *stream = std::fopen(nativePath.c_str(), "r+b"); + if (stream == NULL) + { + stream = std::fopen(nativePath.c_str(), "w+b"); + } +#endif + return stream; + } + + bool SeekFile(std::FILE *file, __int64 offset) + { +#if defined(_WIN32) + return _fseeki64(file, offset, SEEK_SET) == 0; +#else + return fseeko(file, static_cast(offset), SEEK_SET) == 0; +#endif + } + + bool ReadExact(std::FILE *file, void *buffer, std::size_t size) + { + return std::fread(buffer, 1, size, file) == size; + } + + bool WriteExact(std::FILE *file, const void *buffer, std::size_t size) + { + return std::fwrite(buffer, 1, size, file) == size; + } +} + byteArray NbtSlotFile::READ_BUFFER(1024*1024); __int64 NbtSlotFile::largest = 0; @@ -14,12 +55,12 @@ NbtSlotFile::NbtSlotFile(File file) if ( !file.exists() || file.length() ) { - raf = CreateFile(wstringtofilename(file.getPath()), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + raf = OpenBinaryFileForReadWrite(file); writeHeader(); } else { - raf = CreateFile(wstringtofilename(file.getPath()), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + raf = OpenBinaryFileForReadWrite(file); } readHeader(); @@ -29,12 +70,11 @@ NbtSlotFile::NbtSlotFile(File file) fileSlotMap[i] = new std::vector; } - DWORD numberofBytesRead; for (int fileSlot = 0; fileSlot < totalFileSlots; fileSlot++) { seekSlotHeader(fileSlot); short slot; - ReadFile(raf,&slot,2,&numberofBytesRead,NULL); + ReadExact(raf, &slot, sizeof(slot)); if (slot == 0) { freeFileSlots.push_back(fileSlot); @@ -49,42 +89,39 @@ NbtSlotFile::NbtSlotFile(File file) void NbtSlotFile::readHeader() { - DWORD numberOfBytesRead; - SetFilePointer(raf,0,0,FILE_BEGIN); + SeekFile(raf, 0); int magic; - ReadFile(raf,&magic,4,&numberOfBytesRead,NULL); + ReadExact(raf, &magic, sizeof(magic)); // if (magic != MAGIC_NUMBER) throw new IOException("Bad magic number: " + magic); // 4J - TODO short version; - ReadFile(raf,&version,2,&numberOfBytesRead,NULL); + ReadExact(raf, &version, sizeof(version)); // if (version != 0) throw new IOException("Bad version number: " + version); // 4J - TODO - ReadFile(raf,&totalFileSlots,4,&numberOfBytesRead,NULL); + ReadExact(raf, &totalFileSlots, sizeof(totalFileSlots)); } void NbtSlotFile::writeHeader() { - DWORD numberOfBytesWritten; short version = 0; - SetFilePointer(raf,0,0,FILE_BEGIN); - WriteFile(raf,&MAGIC_NUMBER,4,&numberOfBytesWritten,NULL); - WriteFile(raf,&version,2,&numberOfBytesWritten,NULL); - WriteFile(raf,&totalFileSlots,4,&numberOfBytesWritten,NULL); + SeekFile(raf, 0); + WriteExact(raf, &MAGIC_NUMBER, sizeof(MAGIC_NUMBER)); + WriteExact(raf, &version, sizeof(version)); + WriteExact(raf, &totalFileSlots, sizeof(totalFileSlots)); } void NbtSlotFile::seekSlotHeader(int fileSlot) { int target = FILE_HEADER_SIZE + fileSlot * (FILE_SLOT_SIZE + FILE_SLOT_HEADER_SIZE); - SetFilePointer(raf,target,0,FILE_BEGIN); + SeekFile(raf, target); } void NbtSlotFile::seekSlot(int fileSlot) { int target = FILE_HEADER_SIZE + fileSlot * (FILE_SLOT_SIZE + FILE_SLOT_HEADER_SIZE); - SetFilePointer(raf,target+FILE_SLOT_HEADER_SIZE,0,FILE_BEGIN); + SeekFile(raf, target + FILE_SLOT_HEADER_SIZE); } std::vector *NbtSlotFile::readAll(int slot) { - DWORD numberOfBytesRead; std::vector *tags = new std::vector; std::vector *fileSlots = fileSlotMap[slot]; int skipped = 0; @@ -101,12 +138,12 @@ std::vector *NbtSlotFile::readAll(int slot) { seekSlotHeader(c); short oldSlot; - ReadFile(raf,&oldSlot,2,&numberOfBytesRead,NULL); + ReadExact(raf, &oldSlot, sizeof(oldSlot)); short size; - ReadFile(raf,&size,2,&numberOfBytesRead,NULL); - ReadFile(raf,&continuesAt,4,&numberOfBytesRead,NULL); + ReadExact(raf, &size, sizeof(size)); + ReadExact(raf, &continuesAt, sizeof(continuesAt)); int lastSlot; - ReadFile(raf,&lastSlot,4,&numberOfBytesRead,NULL); + ReadExact(raf, &lastSlot, sizeof(lastSlot)); seekSlot(c); if (expectedSlot > 0 && oldSlot == -expectedSlot) @@ -117,7 +154,7 @@ std::vector *NbtSlotFile::readAll(int slot) // if (oldSlot != expectedSlot) throw new IOException("Wrong slot! Got " + oldSlot + ", expected " + expectedSlot); // 4J - TODO - ReadFile(raf,READ_BUFFER.data + pos,size,&numberOfBytesRead,NULL); + ReadExact(raf, READ_BUFFER.data + pos, size); if (continuesAt >= 0) { @@ -161,7 +198,6 @@ int NbtSlotFile::getFreeSlot() } void NbtSlotFile::replaceSlot(int slot, std::vector *tags) { - DWORD numberOfBytesWritten; toReplace = fileSlotMap[slot]; fileSlotMap[slot] = new std::vector(); @@ -210,13 +246,13 @@ void NbtSlotFile::replaceSlot(int slot, std::vector *tags) } seekSlotHeader(fileSlot); - WriteFile(raf,¤tSlot,2,&numberOfBytesWritten,NULL); - WriteFile(raf,&toWrite,2,&numberOfBytesWritten,NULL); - WriteFile(raf,&nextFileSlot,4,&numberOfBytesWritten,NULL); - WriteFile(raf,&lastFileSlot,4,&numberOfBytesWritten,NULL); + WriteExact(raf, ¤tSlot, sizeof(currentSlot)); + WriteExact(raf, &toWrite, sizeof(toWrite)); + WriteExact(raf, &nextFileSlot, sizeof(nextFileSlot)); + WriteExact(raf, &lastFileSlot, sizeof(lastFileSlot)); seekSlot(fileSlot); - WriteFile(raf,compressed.data+pos,toWrite,&numberOfBytesWritten,NULL); + WriteExact(raf, compressed.data + pos, toWrite); if (remaining > 0) { @@ -237,7 +273,7 @@ void NbtSlotFile::replaceSlot(int slot, std::vector *tags) seekSlotHeader(c); short zero = 0; - WriteFile(raf,&zero,2,&numberOfBytesWritten,NULL); + WriteExact(raf, &zero, sizeof(zero)); } toReplace->clear(); @@ -246,5 +282,9 @@ void NbtSlotFile::replaceSlot(int slot, std::vector *tags) void NbtSlotFile::close() { - CloseHandle(raf); + if (raf != NULL) + { + std::fclose(raf); + raf = NULL; + } } diff --git a/Minecraft.World/IO/NBT/NbtSlotFile.h b/Minecraft.World/IO/NBT/NbtSlotFile.h index 4c1f40b8e..0a613cab2 100644 --- a/Minecraft.World/IO/NBT/NbtSlotFile.h +++ b/Minecraft.World/IO/NBT/NbtSlotFile.h @@ -1,4 +1,6 @@ #pragma once +#include + #include "CompoundTag.h" #include "../../Level/Storage/ZonedChunkStorage.h" #include "../../Headers/com.mojang.nbt.h" @@ -14,7 +16,7 @@ private: static const int FILE_SLOT_HEADER_SIZE = 12; static const int FILE_SLOT_SIZE = 500; - HANDLE raf; + std::FILE *raf; std::vector **fileSlotMap; int fileSlotMapLength; std::vector freeFileSlots; diff --git a/Minecraft.World/Level/Storage/ZoneFile.cpp b/Minecraft.World/Level/Storage/ZoneFile.cpp index f90290683..fc60cc54c 100644 --- a/Minecraft.World/Level/Storage/ZoneFile.cpp +++ b/Minecraft.World/Level/Storage/ZoneFile.cpp @@ -3,6 +3,28 @@ #include "../../IO/Files/File.h" #include "ZoneFile.h" +namespace +{ + std::FILE *OpenBinaryFileForReadWrite(const File &file) + { +#if defined(_WIN32) + std::FILE *stream = _wfopen(file.getPath().c_str(), L"r+b"); + if (stream == NULL) + { + stream = _wfopen(file.getPath().c_str(), L"w+b"); + } +#else + const std::string nativePath = wstringtofilename(file.getPath()); + std::FILE *stream = std::fopen(nativePath.c_str(), "r+b"); + if (stream == NULL) + { + stream = std::fopen(nativePath.c_str(), "w+b"); + } +#endif + return stream; + } +} + const int ZoneFile::slotsLength = ZonedChunkStorage::CHUNKS_PER_ZONE * ZonedChunkStorage::CHUNKS_PER_ZONE; @@ -23,7 +45,7 @@ ZoneFile::ZoneFile(__int64 key, File file, File entityFile) : slots(slotsLength) // this.entityFile = new NbtSlotFile(entityFile); // } - channel = CreateFile(wstringtofilename(file.getPath()), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + channel = OpenBinaryFileForReadWrite(file); // 4J - try/catch removed // try { readHeader(); @@ -71,7 +93,11 @@ void ZoneFile::writeHeader() void ZoneFile::close() { - CloseHandle(channel); + if (channel != NULL) + { + std::fclose(channel); + channel = NULL; + } entityFile->close(); } @@ -89,4 +115,4 @@ ZoneIo *ZoneFile::getZoneIo(int slot) bool ZoneFile::containsSlot(int slot) { return slots[slot] > 0; -} \ No newline at end of file +} diff --git a/Minecraft.World/Level/Storage/ZoneFile.h b/Minecraft.World/Level/Storage/ZoneFile.h index bc055f25f..75e402918 100644 --- a/Minecraft.World/Level/Storage/ZoneFile.h +++ b/Minecraft.World/Level/Storage/ZoneFile.h @@ -1,4 +1,6 @@ #pragma once +#include + #include "ZonedChunkStorage.h" #include "../../IO/NBT/NbtSlotFile.h" #include "ZoneIO.h" @@ -20,7 +22,7 @@ public: __int64 lastUse; private: - HANDLE channel; + std::FILE *channel; public: __int64 key; diff --git a/Minecraft.World/Level/Storage/ZoneIO.cpp b/Minecraft.World/Level/Storage/ZoneIO.cpp index 8899fa76c..9789fae2b 100644 --- a/Minecraft.World/Level/Storage/ZoneIO.cpp +++ b/Minecraft.World/Level/Storage/ZoneIO.cpp @@ -2,7 +2,19 @@ #include "../../IO/Streams/ByteBuffer.h" #include "ZoneIO.h" -ZoneIo::ZoneIo(HANDLE channel, __int64 pos) +namespace +{ + bool SeekFile(std::FILE *file, __int64 offset) + { +#if defined(_WIN32) + return _fseeki64(file, offset, SEEK_SET) == 0; +#else + return fseeko(file, static_cast(offset), SEEK_SET) == 0; +#endif + } +} + +ZoneIo::ZoneIo(std::FILE *channel, __int64 pos) { this->channel = channel; this->pos = pos; @@ -21,23 +33,21 @@ void ZoneIo::write(byteArray bb, int size) void ZoneIo::write(ByteBuffer *bb, int size) { - DWORD numberOfBytesWritten; - SetFilePointer(channel,(int)pos,NULL,NULL); - WriteFile(channel,bb->getBuffer(), bb->getSize(),&numberOfBytesWritten,NULL); + SeekFile(channel, pos); + std::fwrite(bb->getBuffer(), 1, bb->getSize(), channel); pos += size; } ByteBuffer *ZoneIo::read(int size) { - DWORD numberOfBytesRead; byteArray bb = byteArray(size); - SetFilePointer(channel,(int)pos,NULL,NULL); + SeekFile(channel, pos); ByteBuffer *buff = ByteBuffer::wrap(bb); // 4J - to investigate - why is this buffer flipped before anything goes in it? buff->order(ZonedChunkStorage::BYTEORDER); buff->position(size); buff->flip(); - ReadFile(channel, buff->getBuffer(), buff->getSize(), &numberOfBytesRead, NULL); + std::fread(buff->getBuffer(), 1, buff->getSize(), channel); pos += size; return buff; } @@ -45,4 +55,4 @@ ByteBuffer *ZoneIo::read(int size) void ZoneIo::flush() { // 4J - was channel.force(false); -} \ No newline at end of file +} diff --git a/Minecraft.World/Level/Storage/ZoneIO.h b/Minecraft.World/Level/Storage/ZoneIO.h index 22473583a..6bf1dbd04 100644 --- a/Minecraft.World/Level/Storage/ZoneIO.h +++ b/Minecraft.World/Level/Storage/ZoneIO.h @@ -1,4 +1,6 @@ #pragma once +#include + #include "ZonedChunkStorage.h" class ByteBuffer; @@ -6,11 +8,11 @@ class ByteBuffer; class ZoneIo { private: - HANDLE channel; + std::FILE *channel; __int64 pos; public: - ZoneIo(HANDLE channel, __int64 pos); + ZoneIo(std::FILE *channel, __int64 pos); void write(byteArray bb, int size); void write(ByteBuffer *bb, int size); ByteBuffer *read(int size);