1
0

Added cBlockArea serialization to string.

Fixes #665.
This commit is contained in:
madmaxoft 2014-03-07 09:17:13 +01:00
parent 3e80e63665
commit 97d803e34f
3 changed files with 202 additions and 38 deletions

View File

@ -2483,6 +2483,37 @@ static int tolua_cBlockArea_LoadFromSchematicFile(lua_State * tolua_S)
static int tolua_cBlockArea_LoadFromSchematicString(lua_State * tolua_S)
{
// function cBlockArea::LoadFromSchematicString
// Exported manually because function has been moved to SchematicFileSerilizer.cpp
cLuaState L(tolua_S);
if (
!L.CheckParamUserType(1, "cBlockArea") ||
!L.CheckParamString (2) ||
!L.CheckParamEnd (3)
)
{
return 0;
}
cBlockArea * self = (cBlockArea *)tolua_tousertype(tolua_S, 1, NULL);
if (self == NULL)
{
tolua_error(tolua_S, "invalid 'self' in function 'cBlockArea::LoadFromSchematicFile'", NULL);
return 0;
}
AString Data;
L.GetStackValue(2, Data);
bool res = cSchematicFileSerializer::LoadFromSchematicString(*self, Data);
tolua_pushboolean(tolua_S, res);
return 1;
}
static int tolua_cBlockArea_SaveToSchematicFile(lua_State * tolua_S)
{
// function cBlockArea::SaveToSchematicFile
@ -2512,6 +2543,34 @@ static int tolua_cBlockArea_SaveToSchematicFile(lua_State * tolua_S)
static int tolua_cBlockArea_SaveToSchematicString(lua_State * tolua_S)
{
// function cBlockArea::SaveToSchematicString
// Exported manually because function has been moved to SchematicFileSerilizer.cpp
cLuaState L(tolua_S);
if (
!L.CheckParamUserType(1, "cBlockArea") ||
!L.CheckParamEnd (2)
)
{
return 0;
}
cBlockArea * self = (cBlockArea *)tolua_tousertype(tolua_S, 1, NULL);
if (self == NULL)
{
tolua_error(tolua_S, "invalid 'self' in function 'cBlockArea::SaveToSchematicFile'", NULL);
return 0;
}
AString Data = cSchematicFileSerializer::SaveToSchematicString(*self);
L.Push(Data);
return 1;
}
static int tolua_cCompositeChat_AddRunCommandPart(lua_State * tolua_S)
{
// function cCompositeChat:AddRunCommandPart(Message, Command, [Style])
@ -2780,7 +2839,9 @@ void ManualBindings::Bind(lua_State * tolua_S)
tolua_function(tolua_S, "GetRelBlockTypeMeta", tolua_cBlockArea_GetRelBlockTypeMeta);
tolua_function(tolua_S, "GetSize", tolua_cBlockArea_GetSize);
tolua_function(tolua_S, "LoadFromSchematicFile", tolua_cBlockArea_LoadFromSchematicFile);
tolua_function(tolua_S, "LoadFromSchematicString", tolua_cBlockArea_LoadFromSchematicString);
tolua_function(tolua_S, "SaveToSchematicFile", tolua_cBlockArea_SaveToSchematicFile);
tolua_function(tolua_S, "SaveToSchematicString", tolua_cBlockArea_SaveToSchematicString);
tolua_endmodule(tolua_S);
tolua_beginmodule(tolua_S, "cCompositeChat");

View File

@ -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());
LOG("%s: Cannot unGZip the schematic data.", __FUNCTION__);
return false;
}
else
// Parse the NBT:
cParsedNBT NBT(UngzippedData.data(), UngzippedData.size());
if (!NBT.IsValid())
{
AString Dummy(a_BlockArea.GetBlockCount(), 0);
Writer.AddByteArray("Blocks", Dummy.data(), Dummy.size());
LOG("%s: Cannot parse the NBT in the schematic data.", __FUNCTION__);
return false;
}
if (a_BlockArea.HasBlockMetas())
return LoadFromSchematicNBT(a_BlockArea, NBT);
}
bool cSchematicFileSerializer::SaveToSchematicFile(const cBlockArea & a_BlockArea, const AString & a_FileName)
{
Writer.AddByteArray("Data", (const char *)a_BlockArea.m_BlockMetas, a_BlockArea.GetBlockCount());
}
else
// 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();
}

View File

@ -1,4 +1,12 @@
// SchematicFileSerializer.h
// Declares the cSchematicFileSerializer class representing the interface to load and save cBlockArea to a .schematic file
#pragma once
#include "../BlockArea.h"
@ -13,17 +21,34 @@ class cParsedNBT;
class cSchematicFileSerializer
{
public:
/// Loads an area from a .schematic file. Returns true if successful
/** Loads an area from a .schematic file. Returns true if successful. */
static bool LoadFromSchematicFile(cBlockArea & a_BlockArea, const AString & a_FileName);
/// Saves the area into a .schematic file. Returns true if successful
static bool SaveToSchematicFile(cBlockArea & a_BlockArea, const AString & a_FileName);
/** Loads an area from a string containing the .schematic file data. Returns true if successful. */
static bool LoadFromSchematicString(cBlockArea & a_BlockArea, const AString & a_SchematicData);
/** Saves the area into a .schematic file. Returns true if successful. */
static bool SaveToSchematicFile(const cBlockArea & a_BlockArea, const AString & a_FileName);
/** Saves the area into a string containing the .schematic file data.
Returns the data, or empty string if failed. */
static AString SaveToSchematicString(const cBlockArea & a_BlockArea);
private:
/// Loads the area from a schematic file uncompressed and parsed into a NBT tree. Returns true if successful.
/** Loads the area from a schematic file uncompressed and parsed into a NBT tree.
Returns true if successful. */
static bool LoadFromSchematicNBT(cBlockArea & a_BlockArea, cParsedNBT & a_NBT);
/** Saves the area into a NBT representation and returns the NBT data as a string.
Returns an empty string if failed. */
static AString SaveToSchematicNBT(const cBlockArea & a_BlockArea);
};