aboutsummaryrefslogtreecommitdiff
path: root/Minecraft.World/NbtSlotFile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Minecraft.World/NbtSlotFile.cpp')
-rw-r--r--Minecraft.World/NbtSlotFile.cpp250
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,&currentSlot,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);
+}