summaryrefslogtreecommitdiffstats
path: root/source/BlockArea.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--source/BlockArea.cpp122
1 files changed, 122 insertions, 0 deletions
diff --git a/source/BlockArea.cpp b/source/BlockArea.cpp
index 4f8de925c..cdabf0378 100644
--- a/source/BlockArea.cpp
+++ b/source/BlockArea.cpp
@@ -7,6 +7,8 @@
#include "Globals.h"
#include "BlockArea.h"
#include "World.h"
+#include "zlib.h"
+#include "WorldStorage/FastNBT.h"
@@ -188,6 +190,46 @@ void cBlockArea::DumpToRawFile(const AString & a_FileName)
+bool cBlockArea::LoadFromSchematicFile(const AString & a_FileName)
+{
+ // Un-GZip the contents:
+ AString Contents;
+ gzFile File = gzopen(a_FileName.c_str(), "rb");
+ if (File == NULL)
+ {
+ LOG("Cannot open the schematic file \"%s\".", a_FileName.c_str());
+ return false;
+ }
+ // Since the gzip format doesn't really support getting the uncompressed length, we need to read incrementally. Yuck!
+ int NumBytesRead = 0;
+ char Buffer[32 KiB];
+ while ((NumBytesRead = gzread(File, Buffer, sizeof(Buffer))) > 0)
+ {
+ Contents.append(Buffer, NumBytesRead);
+ }
+ if (NumBytesRead < 0)
+ {
+ LOG("Cannot read GZipped data in the schematic file \"%s\", error %d", a_FileName.c_str(), NumBytesRead);
+ gzclose(File);
+ return false;
+ }
+ gzclose(File);
+
+ // TODO: Parse the NBT:
+ cParsedNBT NBT(Contents.data(), Contents.size());
+ if (!NBT.IsValid())
+ {
+ LOG("Cannot parse the NBT in the schematic file \"%s\".", a_FileName.c_str());
+ return false;
+ }
+
+ return LoadFromSchematicNBT(NBT);
+}
+
+
+
+
+
void cBlockArea::Crop(int a_AddMinX, int a_SubMaxX, int a_AddMinY, int a_SubMaxY, int a_AddMinZ, int a_SubMaxZ)
{
if (HasBlockTypes())
@@ -799,3 +841,83 @@ void cBlockArea::CropNibbles(NIBBLEARRAY & a_Array, int a_AddMinX, int a_SubMaxX
+
+bool cBlockArea::LoadFromSchematicNBT(cParsedNBT & a_NBT)
+{
+ int TMaterials = a_NBT.FindChildByName(a_NBT.GetRoot(), "Materials");
+ if ((TMaterials > 0) && (a_NBT.GetType(TMaterials) == TAG_String))
+ {
+ AString Materials = a_NBT.GetString(TMaterials);
+ if (Materials.compare("Alpha") != 0)
+ {
+ LOG("Materials tag is present and \"%s\" instead of \"Alpha\". Possibly a wrong-format schematic file.", Materials.c_str());
+ return false;
+ }
+ }
+ int TSizeX = a_NBT.FindChildByName(a_NBT.GetRoot(), "Width");
+ int TSizeY = a_NBT.FindChildByName(a_NBT.GetRoot(), "Height");
+ int TSizeZ = a_NBT.FindChildByName(a_NBT.GetRoot(), "Length");
+ if (
+ (TSizeX < 0) || (TSizeY < 0) || (TSizeZ < 0) ||
+ (a_NBT.GetType(TSizeX) != TAG_Short) ||
+ (a_NBT.GetType(TSizeY) != TAG_Short) ||
+ (a_NBT.GetType(TSizeZ) != TAG_Short)
+ )
+ {
+ LOG("Dimensions are missing from the schematic file (%d, %d, %d), (%d, %d, %d)",
+ TSizeX, TSizeY, TSizeZ,
+ a_NBT.GetType(TSizeX), a_NBT.GetType(TSizeY), a_NBT.GetType(TSizeZ)
+ );
+ return false;
+ }
+
+ int SizeX = a_NBT.GetShort(TSizeX);
+ int SizeY = a_NBT.GetShort(TSizeY);
+ int SizeZ = a_NBT.GetShort(TSizeZ);
+ if ((SizeX < 1) || (SizeY < 1) || (SizeZ < 1))
+ {
+ LOG("Dimensions are invalid in the schematic file: %d, %d, %d", SizeX, SizeY, SizeZ);
+ return false;
+ }
+
+ int TBlockTypes = a_NBT.FindChildByName(a_NBT.GetRoot(), "Blocks");
+ int TBlockMetas = a_NBT.FindChildByName(a_NBT.GetRoot(), "Data");
+ if ((TBlockTypes < 0) || (a_NBT.GetType(TBlockTypes) != TAG_ByteArray))
+ {
+ LOG("BlockTypes are invalid in the schematic file: %d", TBlockTypes);
+ return false;
+ }
+ bool AreMetasPresent = (TBlockMetas > 0) && (a_NBT.GetType(TBlockMetas) == TAG_ByteArray);
+
+ SetSize(SizeX, SizeY, SizeZ, AreMetasPresent ? (baTypes | baMetas) : baTypes);
+
+ // Copy the block types and metas:
+ int NumBytes = m_SizeX * m_SizeY * m_SizeZ;
+ if (a_NBT.GetDataLength(TBlockTypes) < NumBytes)
+ {
+ LOG("BlockTypes truncated in the schematic file (exp %d, got %d bytes). Loading partial.",
+ NumBytes, a_NBT.GetDataLength(TBlockTypes)
+ );
+ NumBytes = a_NBT.GetDataLength(TBlockTypes);
+ }
+ memcpy(m_BlockTypes, a_NBT.GetData(TBlockTypes), NumBytes);
+
+ if (AreMetasPresent)
+ {
+ int NumBytes = m_SizeX * m_SizeY * m_SizeZ;
+ if (a_NBT.GetDataLength(TBlockMetas) < NumBytes)
+ {
+ LOG("BlockMetas truncated in the schematic file (exp %d, got %d bytes). Loading partial.",
+ NumBytes, a_NBT.GetDataLength(TBlockMetas)
+ );
+ NumBytes = a_NBT.GetDataLength(TBlockMetas);
+ }
+ memcpy(m_BlockMetas, a_NBT.GetData(TBlockMetas), NumBytes);
+ }
+
+ return true;
+}
+
+
+
+