diff options
Diffstat (limited to 'Minecraft.World/NbtSlotFile.cpp')
| -rw-r--r-- | Minecraft.World/NbtSlotFile.cpp | 250 |
1 files changed, 250 insertions, 0 deletions
diff --git a/Minecraft.World/NbtSlotFile.cpp b/Minecraft.World/NbtSlotFile.cpp new file mode 100644 index 00000000..81880cfb --- /dev/null +++ b/Minecraft.World/NbtSlotFile.cpp @@ -0,0 +1,250 @@ +#include "stdafx.h" +#include "File.h" +#include "NbtSlotFile.h" + + +byteArray NbtSlotFile::READ_BUFFER(1024*1024); +__int64 NbtSlotFile::largest = 0; + +NbtSlotFile::NbtSlotFile(File file) +{ + totalFileSlots = 0; + fileSlotMapLength = ZonedChunkStorage::CHUNKS_PER_ZONE * ZonedChunkStorage::CHUNKS_PER_ZONE; + fileSlotMap = new vector<int> *[fileSlotMapLength]; + + if ( !file.exists() || file.length() ) + { + raf = CreateFile(wstringtofilename(file.getPath()), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + writeHeader(); + } + else + { + raf = CreateFile(wstringtofilename(file.getPath()), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + } + + readHeader(); + + for (int i = 0; i < fileSlotMapLength; i++) + { + fileSlotMap[i] = new vector<int>; + } + + DWORD numberofBytesRead; + for (int fileSlot = 0; fileSlot < totalFileSlots; fileSlot++) + { + seekSlotHeader(fileSlot); + short slot; + ReadFile(raf,&slot,2,&numberofBytesRead,NULL); + if (slot == 0) + { + freeFileSlots.push_back(fileSlot); + } else if (slot < 0) + { + fileSlotMap[(-slot) - 1]->push_back(fileSlot); + } else { + fileSlotMap[slot - 1]->push_back(fileSlot); + } + } +} + +void NbtSlotFile::readHeader() +{ + DWORD numberOfBytesRead; + SetFilePointer(raf,0,0,FILE_BEGIN); + int magic; + ReadFile(raf,&magic,4,&numberOfBytesRead,NULL); +// if (magic != MAGIC_NUMBER) throw new IOException("Bad magic number: " + magic); // 4J - TODO + short version; + ReadFile(raf,&version,2,&numberOfBytesRead,NULL); +// if (version != 0) throw new IOException("Bad version number: " + version); // 4J - TODO + ReadFile(raf,&totalFileSlots,4,&numberOfBytesRead,NULL); +} + +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); +} + +void NbtSlotFile::seekSlotHeader(int fileSlot) +{ + int target = FILE_HEADER_SIZE + fileSlot * (FILE_SLOT_SIZE + FILE_SLOT_HEADER_SIZE); + SetFilePointer(raf,target,0,FILE_BEGIN); +} + +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); +} + +vector<CompoundTag *> *NbtSlotFile::readAll(int slot) +{ + DWORD numberOfBytesRead; + vector<CompoundTag *> *tags = new vector<CompoundTag *>; + vector<int> *fileSlots = fileSlotMap[slot]; + int skipped = 0; + + AUTO_VAR(itEnd, fileSlots->end()); + for (AUTO_VAR(it, fileSlots->begin()); it != itEnd; it++) + { + int c = *it; //fileSlots->at(i); + + int pos = 0; + int continuesAt = -1; + int expectedSlot = slot + 1; + do + { + seekSlotHeader(c); + short oldSlot; + ReadFile(raf,&oldSlot,2,&numberOfBytesRead,NULL); + short size; + ReadFile(raf,&size,2,&numberOfBytesRead,NULL); + ReadFile(raf,&continuesAt,4,&numberOfBytesRead,NULL); + int lastSlot; + ReadFile(raf,&lastSlot,4,&numberOfBytesRead,NULL); + + seekSlot(c); + if (expectedSlot > 0 && oldSlot == -expectedSlot) + { + skipped++; + goto fileSlotLoop; // 4J - used to be continue fileSlotLoop, with for loop labelled as fileSlotLoop + } + +// if (oldSlot != expectedSlot) throw new IOException("Wrong slot! Got " + oldSlot + ", expected " + expectedSlot); // 4J - TODO + + ReadFile(raf,READ_BUFFER.data + pos,size,&numberOfBytesRead,NULL); + + if (continuesAt >= 0) + { + pos += size; + c = continuesAt; + expectedSlot = -slot - 1; + } + } while (continuesAt >= 0); + tags->push_back(NbtIo::decompress(READ_BUFFER)); +fileSlotLoop: + continue; + } + + return tags; + +} + +int NbtSlotFile::getFreeSlot() +{ int fileSlot; + +// 4J - removed - don't see how toReplace can ever have anything in here, and might not be initialised +// if (toReplace->size() > 0) +// { +// fileSlot = toReplace->back(); +// toReplace->pop_back(); +// } else + + if (freeFileSlots.size() > 0) + { + fileSlot = freeFileSlots.back(); + freeFileSlots.pop_back(); + } + else + { + fileSlot = totalFileSlots++; + writeHeader(); + } + + return fileSlot; + +} +void NbtSlotFile::replaceSlot(int slot, vector<CompoundTag *> *tags) +{ + DWORD numberOfBytesWritten; + toReplace = fileSlotMap[slot]; + fileSlotMap[slot] = new vector<int>(); + + AUTO_VAR(itEndTags, tags->end()); + for (AUTO_VAR(it, tags->begin()); it != itEndTags; it++) + { + CompoundTag *tag = *it; //tags->at(i); + byteArray compressed = NbtIo::compress(tag); + if (compressed.length > largest) + { + wchar_t buf[256]; + largest = compressed.length; +#ifndef _CONTENT_PACKAGE + swprintf(buf, 256, L"New largest: %I64d (%ls)\n",largest,tag->getString(L"id").c_str() ); + OutputDebugStringW(buf); +#endif + } + + int pos = 0; + int remaining = compressed.length; + if (remaining == 0) continue; + + int nextFileSlot = getFreeSlot(); + short currentSlot = slot + 1; + int lastFileSlot = -1; + + while (remaining > 0) + { + int fileSlot = nextFileSlot; + fileSlotMap[slot]->push_back(fileSlot); + + short toWrite = remaining; + if (toWrite > FILE_SLOT_SIZE) + { + toWrite = FILE_SLOT_SIZE; + } + + remaining -= toWrite; + if (remaining > 0) + { + nextFileSlot = getFreeSlot(); + } + else + { + nextFileSlot = -1; + } + + 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); + + seekSlot(fileSlot); + WriteFile(raf,compressed.data+pos,toWrite,&numberOfBytesWritten,NULL); + + if (remaining > 0) + { + lastFileSlot = fileSlot; + pos += toWrite; + currentSlot = -slot - 1; + } + } + delete[] compressed.data; + } + + AUTO_VAR(itEndToRep, toReplace->end()); + for (AUTO_VAR(it, toReplace->begin()); it != itEndToRep; it++) + { + int c = *it; //toReplace->at(i); + + freeFileSlots.push_back(c); + + seekSlotHeader(c); + short zero = 0; + WriteFile(raf,&zero,2,&numberOfBytesWritten,NULL); + } + + toReplace->clear(); + +} + +void NbtSlotFile::close() +{ + CloseHandle(raf); +} |
