From 97d803e34f51470774a6bfc2232cae0b041a1aa0 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Fri, 7 Mar 2014 09:17:13 +0100 Subject: Added cBlockArea serialization to string. Fixes #665. --- src/WorldStorage/SchematicFileSerializer.cpp | 134 +++++++++++++++++++++------ 1 file changed, 106 insertions(+), 28 deletions(-) (limited to 'src/WorldStorage/SchematicFileSerializer.cpp') diff --git a/src/WorldStorage/SchematicFileSerializer.cpp b/src/WorldStorage/SchematicFileSerializer.cpp index 45fd967bd..a6ae8d8e0 100644 --- a/src/WorldStorage/SchematicFileSerializer.cpp +++ b/src/WorldStorage/SchematicFileSerializer.cpp @@ -1,10 +1,18 @@ +// SchematicFileSerializer.cpp + +// Implements the cSchematicFileSerializer class representing the interface to load and save cBlockArea to a .schematic file + #include "Globals.h" #include "OSSupport/GZipFile.h" #include "FastNBT.h" - #include "SchematicFileSerializer.h" +#include "../StringCompression.h" + + + + bool cSchematicFileSerializer::LoadFromSchematicFile(cBlockArea & a_BlockArea, const AString & a_FileName) { @@ -40,48 +48,51 @@ bool cSchematicFileSerializer::LoadFromSchematicFile(cBlockArea & a_BlockArea, c -bool cSchematicFileSerializer::SaveToSchematicFile(cBlockArea & a_BlockArea, const AString & a_FileName) +bool cSchematicFileSerializer::LoadFromSchematicString(cBlockArea & a_BlockArea, const AString & a_SchematicData) { - cFastNBTWriter Writer("Schematic"); - Writer.AddShort("Width", a_BlockArea.m_SizeX); - Writer.AddShort("Height", a_BlockArea.m_SizeY); - Writer.AddShort("Length", a_BlockArea.m_SizeZ); - Writer.AddString("Materials", "Alpha"); - if (a_BlockArea.HasBlockTypes()) + // Uncompress the data: + AString UngzippedData; + if (UncompressStringGZIP(a_SchematicData.data(), a_SchematicData.size(), UngzippedData) != Z_OK) { - Writer.AddByteArray("Blocks", (const char *)a_BlockArea.m_BlockTypes, a_BlockArea.GetBlockCount()); - } - else - { - AString Dummy(a_BlockArea.GetBlockCount(), 0); - Writer.AddByteArray("Blocks", Dummy.data(), Dummy.size()); + LOG("%s: Cannot unGZip the schematic data.", __FUNCTION__); + return false; } - if (a_BlockArea.HasBlockMetas()) + + // Parse the NBT: + cParsedNBT NBT(UngzippedData.data(), UngzippedData.size()); + if (!NBT.IsValid()) { - Writer.AddByteArray("Data", (const char *)a_BlockArea.m_BlockMetas, a_BlockArea.GetBlockCount()); + LOG("%s: Cannot parse the NBT in the schematic data.", __FUNCTION__); + return false; } - else + + return LoadFromSchematicNBT(a_BlockArea, NBT); +} + + + + + +bool cSchematicFileSerializer::SaveToSchematicFile(const cBlockArea & a_BlockArea, const AString & a_FileName) +{ + // Serialize into NBT data: + AString NBT = SaveToSchematicNBT(a_BlockArea); + if (NBT.empty()) { - AString Dummy(a_BlockArea.GetBlockCount(), 0); - Writer.AddByteArray("Data", Dummy.data(), Dummy.size()); + LOG("%s: Cannot serialize the area into an NBT representation for file \"%s\".", __FUNCTION__, a_FileName.c_str()); + return false; } - // TODO: Save entities and block entities - Writer.BeginList("Entities", TAG_Compound); - Writer.EndList(); - Writer.BeginList("TileEntities", TAG_Compound); - Writer.EndList(); - Writer.Finish(); // Save to file cGZipFile File; if (!File.Open(a_FileName, cGZipFile::fmWrite)) { - LOG("Cannot open file \"%s\" for writing.", a_FileName.c_str()); + LOG("%s: Cannot open file \"%s\" for writing.", __FUNCTION__, a_FileName.c_str()); return false; } - if (!File.Write(Writer.GetResult())) + if (!File.Write(NBT)) { - LOG("Cannot write data to file \"%s\".", a_FileName.c_str()); + LOG("%s: Cannot write data to file \"%s\".", __FUNCTION__, a_FileName.c_str()); return false; } return true; @@ -92,6 +103,31 @@ bool cSchematicFileSerializer::SaveToSchematicFile(cBlockArea & a_BlockArea, con +AString cSchematicFileSerializer::SaveToSchematicString(const cBlockArea & a_BlockArea) +{ + // Serialize into NBT data: + AString NBT = SaveToSchematicNBT(a_BlockArea); + if (NBT.empty()) + { + LOG("%s: Cannot serialize the area into an NBT representation.", __FUNCTION__); + return false; + } + + // Gzip the data: + AString Compressed; + int res = CompressStringGZIP(NBT.data(), NBT.size(), Compressed); + if (res != Z_OK) + { + LOG("%s: Cannot Gzip the area data NBT representation: %d", __FUNCTION__, res); + return false; + } + return Compressed; +} + + + + + bool cSchematicFileSerializer::LoadFromSchematicNBT(cBlockArea & a_BlockArea, cParsedNBT & a_NBT) { int TMaterials = a_NBT.FindChildByName(a_NBT.GetRoot(), "Materials"); @@ -170,3 +206,45 @@ bool cSchematicFileSerializer::LoadFromSchematicNBT(cBlockArea & a_BlockArea, cP } + + + +AString cSchematicFileSerializer::SaveToSchematicNBT(const cBlockArea & a_BlockArea) +{ + cFastNBTWriter Writer("Schematic"); + Writer.AddShort("Width", a_BlockArea.m_SizeX); + Writer.AddShort("Height", a_BlockArea.m_SizeY); + Writer.AddShort("Length", a_BlockArea.m_SizeZ); + Writer.AddString("Materials", "Alpha"); + if (a_BlockArea.HasBlockTypes()) + { + Writer.AddByteArray("Blocks", (const char *)a_BlockArea.m_BlockTypes, a_BlockArea.GetBlockCount()); + } + else + { + AString Dummy(a_BlockArea.GetBlockCount(), 0); + Writer.AddByteArray("Blocks", Dummy.data(), Dummy.size()); + } + if (a_BlockArea.HasBlockMetas()) + { + Writer.AddByteArray("Data", (const char *)a_BlockArea.m_BlockMetas, a_BlockArea.GetBlockCount()); + } + else + { + AString Dummy(a_BlockArea.GetBlockCount(), 0); + Writer.AddByteArray("Data", Dummy.data(), Dummy.size()); + } + + // TODO: Save entities and block entities + Writer.BeginList("Entities", TAG_Compound); + Writer.EndList(); + Writer.BeginList("TileEntities", TAG_Compound); + Writer.EndList(); + Writer.Finish(); + + return Writer.GetResult(); +} + + + + -- cgit v1.2.3 From ffdf5f2022cbeb568cb6ff28448aad98876334b1 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Fri, 7 Mar 2014 21:28:52 +0100 Subject: Fixed cBlockArea schematic string saving signature. --- src/WorldStorage/SchematicFileSerializer.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src/WorldStorage/SchematicFileSerializer.cpp') diff --git a/src/WorldStorage/SchematicFileSerializer.cpp b/src/WorldStorage/SchematicFileSerializer.cpp index a6ae8d8e0..b021aeb0c 100644 --- a/src/WorldStorage/SchematicFileSerializer.cpp +++ b/src/WorldStorage/SchematicFileSerializer.cpp @@ -103,7 +103,7 @@ bool cSchematicFileSerializer::SaveToSchematicFile(const cBlockArea & a_BlockAre -AString cSchematicFileSerializer::SaveToSchematicString(const cBlockArea & a_BlockArea) +bool cSchematicFileSerializer::SaveToSchematicString(const cBlockArea & a_BlockArea, AString & a_Out) { // Serialize into NBT data: AString NBT = SaveToSchematicNBT(a_BlockArea); @@ -114,14 +114,13 @@ AString cSchematicFileSerializer::SaveToSchematicString(const cBlockArea & a_Blo } // Gzip the data: - AString Compressed; - int res = CompressStringGZIP(NBT.data(), NBT.size(), Compressed); + int res = CompressStringGZIP(NBT.data(), NBT.size(), a_Out); if (res != Z_OK) { LOG("%s: Cannot Gzip the area data NBT representation: %d", __FUNCTION__, res); return false; } - return Compressed; + return true; } -- cgit v1.2.3 From 0cce0478d846114f49c4b8fe201aee7a1bb06b22 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Mon, 10 Mar 2014 17:07:46 +0100 Subject: This allows a blockarea to have an Offset. --- src/WorldStorage/SchematicFileSerializer.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'src/WorldStorage/SchematicFileSerializer.cpp') diff --git a/src/WorldStorage/SchematicFileSerializer.cpp b/src/WorldStorage/SchematicFileSerializer.cpp index b021aeb0c..0aea931eb 100644 --- a/src/WorldStorage/SchematicFileSerializer.cpp +++ b/src/WorldStorage/SchematicFileSerializer.cpp @@ -177,6 +177,25 @@ bool cSchematicFileSerializer::LoadFromSchematicNBT(cBlockArea & a_BlockArea, cP a_BlockArea.Clear(); a_BlockArea.SetSize(SizeX, SizeY, SizeZ, AreMetasPresent ? (cBlockArea::baTypes | cBlockArea::baMetas) : cBlockArea::baTypes); + int TOffsetX = a_NBT.FindChildByName(a_NBT.GetRoot(), "WEOffsetX"); + int TOffsetY = a_NBT.FindChildByName(a_NBT.GetRoot(), "WEOffsetY"); + int TOffsetZ = a_NBT.FindChildByName(a_NBT.GetRoot(), "WEOffsetZ"); + + if ( + (TOffsetX < 0) || (TOffsetY < 0) || (TOffsetZ < 0) || + (a_NBT.GetType(TOffsetX) != TAG_Int) || + (a_NBT.GetType(TOffsetY) != TAG_Int) || + (a_NBT.GetType(TOffsetZ) != TAG_Int) + ) + { + // Not every schematic file has an offset, so we shoudn't give a warn message. + a_BlockArea.SetOffset(0, 0, 0); + } + else + { + a_BlockArea.SetOffset(a_NBT.GetInt(TOffsetX), a_NBT.GetInt(TOffsetY), a_NBT.GetInt(TOffsetZ)); + } + // Copy the block types and metas: int NumBytes = a_BlockArea.m_SizeX * a_BlockArea.m_SizeY * a_BlockArea.m_SizeZ; if (a_NBT.GetDataLength(TBlockTypes) < NumBytes) @@ -234,6 +253,10 @@ AString cSchematicFileSerializer::SaveToSchematicNBT(const cBlockArea & a_BlockA Writer.AddByteArray("Data", Dummy.data(), Dummy.size()); } + Writer.AddInt("WEOffsetX", a_BlockArea.m_Offset.x); + Writer.AddInt("WEOffsetY", a_BlockArea.m_Offset.y); + Writer.AddInt("WEOffsetZ", a_BlockArea.m_Offset.z); + // TODO: Save entities and block entities Writer.BeginList("Entities", TAG_Compound); Writer.EndList(); -- cgit v1.2.3 From e213e5f9fcb3681a5f383546e17b9800d4a4804a Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Tue, 11 Mar 2014 18:23:21 +0100 Subject: Renamed m_Offset to m_WEOffset --- src/WorldStorage/SchematicFileSerializer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/WorldStorage/SchematicFileSerializer.cpp') diff --git a/src/WorldStorage/SchematicFileSerializer.cpp b/src/WorldStorage/SchematicFileSerializer.cpp index 0aea931eb..b899540df 100644 --- a/src/WorldStorage/SchematicFileSerializer.cpp +++ b/src/WorldStorage/SchematicFileSerializer.cpp @@ -253,9 +253,9 @@ AString cSchematicFileSerializer::SaveToSchematicNBT(const cBlockArea & a_BlockA Writer.AddByteArray("Data", Dummy.data(), Dummy.size()); } - Writer.AddInt("WEOffsetX", a_BlockArea.m_Offset.x); - Writer.AddInt("WEOffsetY", a_BlockArea.m_Offset.y); - Writer.AddInt("WEOffsetZ", a_BlockArea.m_Offset.z); + Writer.AddInt("WEOffsetX", a_BlockArea.m_WEOffset.x); + Writer.AddInt("WEOffsetY", a_BlockArea.m_WEOffset.y); + Writer.AddInt("WEOffsetZ", a_BlockArea.m_WEOffset.z); // TODO: Save entities and block entities Writer.BeginList("Entities", TAG_Compound); -- cgit v1.2.3 From 950614da7e700b8847f0dcc0bac9d76367801a3f Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Wed, 12 Mar 2014 07:46:14 +0100 Subject: Renamed cBlockArea Offset to WEOffset. Even in getters / setters. --- src/WorldStorage/SchematicFileSerializer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/WorldStorage/SchematicFileSerializer.cpp') diff --git a/src/WorldStorage/SchematicFileSerializer.cpp b/src/WorldStorage/SchematicFileSerializer.cpp index b899540df..ef67fdb13 100644 --- a/src/WorldStorage/SchematicFileSerializer.cpp +++ b/src/WorldStorage/SchematicFileSerializer.cpp @@ -189,11 +189,11 @@ bool cSchematicFileSerializer::LoadFromSchematicNBT(cBlockArea & a_BlockArea, cP ) { // Not every schematic file has an offset, so we shoudn't give a warn message. - a_BlockArea.SetOffset(0, 0, 0); + a_BlockArea.SetWEOffset(0, 0, 0); } else { - a_BlockArea.SetOffset(a_NBT.GetInt(TOffsetX), a_NBT.GetInt(TOffsetY), a_NBT.GetInt(TOffsetZ)); + a_BlockArea.SetWEOffset(a_NBT.GetInt(TOffsetX), a_NBT.GetInt(TOffsetY), a_NBT.GetInt(TOffsetZ)); } // Copy the block types and metas: -- cgit v1.2.3 From 87e0bd54b426bafb6b267725b0e1a94511a38f4e Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Tue, 25 Mar 2014 21:59:25 +0100 Subject: BlockArea: Switched internal coords to Vector3i. --- src/WorldStorage/SchematicFileSerializer.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/WorldStorage/SchematicFileSerializer.cpp') diff --git a/src/WorldStorage/SchematicFileSerializer.cpp b/src/WorldStorage/SchematicFileSerializer.cpp index ef67fdb13..d8531d965 100644 --- a/src/WorldStorage/SchematicFileSerializer.cpp +++ b/src/WorldStorage/SchematicFileSerializer.cpp @@ -197,7 +197,7 @@ bool cSchematicFileSerializer::LoadFromSchematicNBT(cBlockArea & a_BlockArea, cP } // Copy the block types and metas: - int NumBytes = a_BlockArea.m_SizeX * a_BlockArea.m_SizeY * a_BlockArea.m_SizeZ; + int NumBytes = a_BlockArea.GetBlockCount(); if (a_NBT.GetDataLength(TBlockTypes) < NumBytes) { LOG("BlockTypes truncated in the schematic file (exp %d, got %d bytes). Loading partial.", @@ -209,7 +209,7 @@ bool cSchematicFileSerializer::LoadFromSchematicNBT(cBlockArea & a_BlockArea, cP if (AreMetasPresent) { - int NumBytes = a_BlockArea.m_SizeX * a_BlockArea.m_SizeY * a_BlockArea.m_SizeZ; + int NumBytes = a_BlockArea.GetBlockCount(); if (a_NBT.GetDataLength(TBlockMetas) < NumBytes) { LOG("BlockMetas truncated in the schematic file (exp %d, got %d bytes). Loading partial.", @@ -230,9 +230,9 @@ bool cSchematicFileSerializer::LoadFromSchematicNBT(cBlockArea & a_BlockArea, cP AString cSchematicFileSerializer::SaveToSchematicNBT(const cBlockArea & a_BlockArea) { cFastNBTWriter Writer("Schematic"); - Writer.AddShort("Width", a_BlockArea.m_SizeX); - Writer.AddShort("Height", a_BlockArea.m_SizeY); - Writer.AddShort("Length", a_BlockArea.m_SizeZ); + Writer.AddShort("Width", a_BlockArea.m_Size.x); + Writer.AddShort("Height", a_BlockArea.m_Size.y); + Writer.AddShort("Length", a_BlockArea.m_Size.z); Writer.AddString("Materials", "Alpha"); if (a_BlockArea.HasBlockTypes()) { -- cgit v1.2.3 From bcd7f9669ba98f4ecb71ba728d72836ff14b3c0f Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Wed, 2 Apr 2014 11:56:27 +0200 Subject: Added schematic string serializer self-test. --- src/WorldStorage/SchematicFileSerializer.cpp | 33 ++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'src/WorldStorage/SchematicFileSerializer.cpp') diff --git a/src/WorldStorage/SchematicFileSerializer.cpp b/src/WorldStorage/SchematicFileSerializer.cpp index d8531d965..9d594a084 100644 --- a/src/WorldStorage/SchematicFileSerializer.cpp +++ b/src/WorldStorage/SchematicFileSerializer.cpp @@ -14,6 +14,39 @@ +#ifdef SELF_TEST + +static class cSchematicStringSelfTest +{ +public: + cSchematicStringSelfTest(void) + { + cBlockArea ba; + ba.Create(21, 256, 21); + ba.RelLine(0, 0, 0, 9, 8, 7, cBlockArea::baTypes | cBlockArea::baMetas, E_BLOCK_WOODEN_STAIRS, 1); + AString Schematic; + if (!cSchematicFileSerializer::SaveToSchematicString(ba, Schematic)) + { + assert_test(!"Schematic failed to save!"); + } + cBlockArea ba2; + if (!cSchematicFileSerializer::LoadFromSchematicString(ba2, Schematic)) + { + assert_test(!"Schematic failed to load!"); + } + } +} g_SelfTest; + +#endif + + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cSchematicFileSerializer: + bool cSchematicFileSerializer::LoadFromSchematicFile(cBlockArea & a_BlockArea, const AString & a_FileName) { // Un-GZip the contents: -- cgit v1.2.3