Moved Schematic file methods to seperate class
This commit is contained in:
parent
613f238ab6
commit
4f09e8df6e
@ -7,7 +7,6 @@
|
||||
#include "Globals.h"
|
||||
#include "BlockArea.h"
|
||||
#include "OSSupport/GZipFile.h"
|
||||
#include "WorldStorage/FastNBT.h"
|
||||
#include "Blocks/BlockHandler.h"
|
||||
|
||||
|
||||
@ -447,85 +446,12 @@ void cBlockArea::DumpToRawFile(const AString & a_FileName)
|
||||
|
||||
|
||||
|
||||
bool cBlockArea::LoadFromSchematicFile(const AString & a_FileName)
|
||||
{
|
||||
// Un-GZip the contents:
|
||||
AString Contents;
|
||||
cGZipFile File;
|
||||
if (!File.Open(a_FileName, cGZipFile::fmRead))
|
||||
{
|
||||
LOG("Cannot open the schematic file \"%s\".", a_FileName.c_str());
|
||||
return false;
|
||||
}
|
||||
int NumBytesRead = File.ReadRestOfFile(Contents);
|
||||
if (NumBytesRead < 0)
|
||||
{
|
||||
LOG("Cannot read GZipped data in the schematic file \"%s\", error %d", a_FileName.c_str(), NumBytesRead);
|
||||
return false;
|
||||
}
|
||||
File.Close();
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cBlockArea::SaveToSchematicFile(const AString & a_FileName)
|
||||
{
|
||||
cFastNBTWriter Writer("Schematic");
|
||||
Writer.AddShort("Width", m_SizeX);
|
||||
Writer.AddShort("Height", m_SizeY);
|
||||
Writer.AddShort("Length", m_SizeZ);
|
||||
Writer.AddString("Materials", "Alpha");
|
||||
if (HasBlockTypes())
|
||||
{
|
||||
Writer.AddByteArray("Blocks", (const char *)m_BlockTypes, GetBlockCount());
|
||||
}
|
||||
else
|
||||
{
|
||||
AString Dummy(GetBlockCount(), 0);
|
||||
Writer.AddByteArray("Blocks", Dummy.data(), Dummy.size());
|
||||
}
|
||||
if (HasBlockMetas())
|
||||
{
|
||||
Writer.AddByteArray("Data", (const char *)m_BlockMetas, GetBlockCount());
|
||||
}
|
||||
else
|
||||
{
|
||||
AString Dummy(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();
|
||||
|
||||
// Save to file
|
||||
cGZipFile File;
|
||||
if (!File.Open(a_FileName, cGZipFile::fmWrite))
|
||||
{
|
||||
LOG("Cannot open file \"%s\" for writing.", a_FileName.c_str());
|
||||
return false;
|
||||
}
|
||||
if (!File.Write(Writer.GetResult()))
|
||||
{
|
||||
LOG("Cannot write data to file \"%s\".", a_FileName.c_str());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -2017,89 +1943,6 @@ void cBlockArea::ExpandNibbles(NIBBLEARRAY & a_Array, int a_SubMinX, int a_AddMa
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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);
|
||||
|
||||
Clear();
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void cBlockArea::RelSetData(
|
||||
int a_RelX, int a_RelY, int a_RelZ,
|
||||
int a_DataTypes, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta,
|
||||
|
@ -15,14 +15,6 @@
|
||||
#include "ForEachChunkProvider.h"
|
||||
|
||||
|
||||
|
||||
// fwd: FastNBT.h
|
||||
class cParsedNBT;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// tolua_begin
|
||||
class cBlockArea
|
||||
{
|
||||
@ -82,12 +74,6 @@ public:
|
||||
/// For testing purposes only, dumps the area into a file.
|
||||
void DumpToRawFile(const AString & a_FileName);
|
||||
|
||||
/// Loads an area from a .schematic file. Returns true if successful
|
||||
bool LoadFromSchematicFile(const AString & a_FileName);
|
||||
|
||||
/// Saves the area into a .schematic file. Returns true if successful
|
||||
bool SaveToSchematicFile(const AString & a_FileName);
|
||||
|
||||
/// Crops the internal contents by the specified amount of blocks from each border.
|
||||
void Crop(int a_AddMinX, int a_SubMaxX, int a_AddMinY, int a_SubMaxY, int a_AddMinZ, int a_SubMaxZ);
|
||||
|
||||
@ -230,6 +216,7 @@ public:
|
||||
|
||||
protected:
|
||||
friend class cChunkDesc;
|
||||
friend class cSchematicFileSerializer;
|
||||
|
||||
class cChunkReader :
|
||||
public cChunkDataCallback
|
||||
@ -289,9 +276,6 @@ protected:
|
||||
void ExpandBlockTypes(int a_SubMinX, int a_AddMaxX, int a_SubMinY, int a_AddMaxY, int a_SubMinZ, int a_AddMaxZ);
|
||||
void ExpandNibbles (NIBBLEARRAY & a_Array, int a_SubMinX, int a_AddMaxX, int a_SubMinY, int a_AddMaxY, int a_SubMinZ, int a_AddMaxZ);
|
||||
|
||||
/// Loads the area from a schematic file uncompressed and parsed into a NBT tree. Returns true if successful.
|
||||
bool LoadFromSchematicNBT(cParsedNBT & a_NBT);
|
||||
|
||||
/// Sets the specified datatypes at the specified location.
|
||||
void RelSetData(
|
||||
int a_RelX, int a_RelY, int a_RelZ,
|
||||
|
155
src/WorldStorage/SchematicFileSerilizer.cpp
Normal file
155
src/WorldStorage/SchematicFileSerilizer.cpp
Normal file
@ -0,0 +1,155 @@
|
||||
|
||||
bool cSchematicFileSerializer::LoadFromSchematicFile(const AString & a_FileName)
|
||||
{
|
||||
// Un-GZip the contents:
|
||||
AString Contents;
|
||||
cGZipFile File;
|
||||
if (!File.Open(a_FileName, cGZipFile::fmRead))
|
||||
{
|
||||
LOG("Cannot open the schematic file \"%s\".", a_FileName.c_str());
|
||||
return false;
|
||||
}
|
||||
int NumBytesRead = File.ReadRestOfFile(Contents);
|
||||
if (NumBytesRead < 0)
|
||||
{
|
||||
LOG("Cannot read GZipped data in the schematic file \"%s\", error %d", a_FileName.c_str(), NumBytesRead);
|
||||
return false;
|
||||
}
|
||||
File.Close();
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
bool cSchematicFileSerializer::SaveToSchematicFile(const AString & a_FileName)
|
||||
{
|
||||
cFastNBTWriter Writer("Schematic");
|
||||
Writer.AddShort("Width", m_SizeX);
|
||||
Writer.AddShort("Height", m_SizeY);
|
||||
Writer.AddShort("Length", m_SizeZ);
|
||||
Writer.AddString("Materials", "Alpha");
|
||||
if (HasBlockTypes())
|
||||
{
|
||||
Writer.AddByteArray("Blocks", (const char *)m_BlockTypes, GetBlockCount());
|
||||
}
|
||||
else
|
||||
{
|
||||
AString Dummy(GetBlockCount(), 0);
|
||||
Writer.AddByteArray("Blocks", Dummy.data(), Dummy.size());
|
||||
}
|
||||
if (HasBlockMetas())
|
||||
{
|
||||
Writer.AddByteArray("Data", (const char *)m_BlockMetas, GetBlockCount());
|
||||
}
|
||||
else
|
||||
{
|
||||
AString Dummy(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();
|
||||
|
||||
// Save to file
|
||||
cGZipFile File;
|
||||
if (!File.Open(a_FileName, cGZipFile::fmWrite))
|
||||
{
|
||||
LOG("Cannot open file \"%s\" for writing.", a_FileName.c_str());
|
||||
return false;
|
||||
}
|
||||
if (!File.Write(Writer.GetResult()))
|
||||
{
|
||||
LOG("Cannot write data to file \"%s\".", a_FileName.c_str());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
Clear();
|
||||
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;
|
||||
}
|
||||
|
||||
|
20
src/WorldStorage/SchematicFileSerilizer.h
Normal file
20
src/WorldStorage/SchematicFileSerilizer.h
Normal file
@ -0,0 +1,20 @@
|
||||
|
||||
#include "../BlockArea.h"
|
||||
|
||||
// fwd: FastNBT.h
|
||||
class cParsedNBT;
|
||||
|
||||
class cSchematicFileSerializer
|
||||
{
|
||||
public:
|
||||
|
||||
/// Loads an area from a .schematic file. Returns true if successful
|
||||
static bool LoadFromSchematicFile(const AString & a_FileName);
|
||||
|
||||
/// Saves the area into a .schematic file. Returns true if successful
|
||||
static bool SaveToSchematicFile(const AString & a_FileName);
|
||||
|
||||
private:
|
||||
/// 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);
|
||||
};
|
Loading…
Reference in New Issue
Block a user