cBlockArea can now be saved as a .schematic file.

git-svn-id: http://mc-server.googlecode.com/svn/trunk@1198 0a769ca7-a7f5-676a-18bf-c427514a06d6
master
madmaxoft@gmail.com 2013-02-07 10:09:42 +00:00
parent 1ba07a82b6
commit ed47a8e409
9 changed files with 140 additions and 7 deletions

View File

@ -149,6 +149,25 @@ function OnPlayerUsingItem(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, C
return false;
end
-- Rclk with an ender pearl saves a predefined area around the cursor into a .schematic file
if (Player:GetEquippedItem().m_ItemType == E_ITEM_ENDER_PEARL) then
local Area = cBlockArea();
if not(Area:Read(Player:GetWorld(),
BlockX - 8, BlockX + 8, BlockY - 8, BlockY + 8, BlockZ - 8, BlockZ + 8)
) then
LOG("LUA: Area couldn't be read");
return false;
end
LOG("LUA: Area read, saving now.");
if not(Area:SaveToSchematicFile("schematics/out.schematic")) then
LOG("LUA: Cannot save schematic file.");
return false;
end
LOG("LUA: Done.");
return false;
end
end

View File

@ -1,6 +1,6 @@
/*
** Lua binding: AllToLua
** Generated automatically by tolua++-1.0.92 on 02/06/13 22:02:40.
** Generated automatically by tolua++-1.0.92 on 02/07/13 10:38:08.
*/
#ifndef __cplusplus
@ -17894,6 +17894,41 @@ static int tolua_AllToLua_cBlockArea_LoadFromSchematicFile00(lua_State* tolua_S)
}
#endif //#ifndef TOLUA_DISABLE
/* method: SaveToSchematicFile of class cBlockArea */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cBlockArea_SaveToSchematicFile00
static int tolua_AllToLua_cBlockArea_SaveToSchematicFile00(lua_State* tolua_S)
{
#ifndef TOLUA_RELEASE
tolua_Error tolua_err;
if (
!tolua_isusertype(tolua_S,1,"cBlockArea",0,&tolua_err) ||
!tolua_iscppstring(tolua_S,2,0,&tolua_err) ||
!tolua_isnoobj(tolua_S,3,&tolua_err)
)
goto tolua_lerror;
else
#endif
{
cBlockArea* self = (cBlockArea*) tolua_tousertype(tolua_S,1,0);
const AString a_FileName = ((const AString) tolua_tocppstring(tolua_S,2,0));
#ifndef TOLUA_RELEASE
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'SaveToSchematicFile'", NULL);
#endif
{
bool tolua_ret = (bool) self->SaveToSchematicFile(a_FileName);
tolua_pushboolean(tolua_S,(bool)tolua_ret);
tolua_pushcppstring(tolua_S,(const char*)a_FileName);
}
}
return 2;
#ifndef TOLUA_RELEASE
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'SaveToSchematicFile'.",&tolua_err);
return 0;
#endif
}
#endif //#ifndef TOLUA_DISABLE
/* method: Crop of class cBlockArea */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cBlockArea_Crop00
static int tolua_AllToLua_cBlockArea_Crop00(lua_State* tolua_S)
@ -21776,6 +21811,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_function(tolua_S,"Write",tolua_AllToLua_cBlockArea_Write01);
tolua_function(tolua_S,"DumpToRawFile",tolua_AllToLua_cBlockArea_DumpToRawFile00);
tolua_function(tolua_S,"LoadFromSchematicFile",tolua_AllToLua_cBlockArea_LoadFromSchematicFile00);
tolua_function(tolua_S,"SaveToSchematicFile",tolua_AllToLua_cBlockArea_SaveToSchematicFile00);
tolua_function(tolua_S,"Crop",tolua_AllToLua_cBlockArea_Crop00);
tolua_function(tolua_S,"SetRelBlockType",tolua_AllToLua_cBlockArea_SetRelBlockType00);
tolua_function(tolua_S,"SetBlockType",tolua_AllToLua_cBlockArea_SetBlockType00);

View File

@ -1,6 +1,6 @@
/*
** Lua binding: AllToLua
** Generated automatically by tolua++-1.0.92 on 02/06/13 22:02:40.
** Generated automatically by tolua++-1.0.92 on 02/07/13 10:38:08.
*/
/* Exported function */

View File

@ -223,6 +223,52 @@ bool cBlockArea::LoadFromSchematicFile(const AString & a_FileName)
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());
}
Writer.Finish();
// TODO: 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;
}
void cBlockArea::Crop(int a_AddMinX, int a_SubMaxX, int a_AddMinY, int a_SubMaxY, int a_AddMinZ, int a_SubMaxZ)
{
if (

View File

@ -65,6 +65,9 @@ public:
/// 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);

View File

@ -36,6 +36,7 @@ bool cGZipFile::Open(const AString & a_FileName, eMode a_Mode)
return false;
}
m_File = gzopen(a_FileName.c_str(), (a_Mode == fmRead) ? "r" : "w");
m_Mode = a_Mode;
return (m_File != NULL);
}
@ -64,6 +65,12 @@ int cGZipFile::ReadRestOfFile(AString & a_Contents)
return -1;
}
if (m_Mode != fmRead)
{
ASSERT(!"Bad file mode, cannot read");
return -1;
}
// Since the gzip format doesn't really support getting the uncompressed length, we need to read incrementally. Yuck!
int NumBytesRead = 0;
char Buffer[64 KiB];
@ -77,3 +84,24 @@ int cGZipFile::ReadRestOfFile(AString & a_Contents)
bool cGZipFile::Write(const AString & a_Contents)
{
if (m_File == NULL)
{
ASSERT(!"No file has been opened");
return false;
}
if (m_Mode != fmWrite)
{
ASSERT(!"Bad file mode, cannot write");
return false;
}
return (gzwrite(m_File, a_Contents.data(), a_Contents.size()) != 0);
}

View File

@ -36,11 +36,12 @@ public:
/// Reads the rest of the file and decompresses it into a_Contents. Returns the number of decompressed bytes, <0 for error
int ReadRestOfFile(AString & a_Contents);
/// Writes a_Contents into file, compressing it along the way. Returns the number of decompressed bytes, <0 for error. Multiple writes are supported.
int Write(AString & a_Contents);
/// Writes a_Contents into file, compressing it along the way. Returns true if successful. Multiple writes are supported.
bool Write(const AString & a_Contents);
protected:
gzFile m_File;
eMode m_Mode;
} ;

View File

@ -327,13 +327,13 @@ int cParsedNBT::FindTagByPath(int a_Tag, const AString & a_Path) const
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cFastNBTWriter:
cFastNBTWriter::cFastNBTWriter(void) :
cFastNBTWriter::cFastNBTWriter(const AString & a_RootTagName) :
m_CurrentStack(0)
{
m_Stack[0].m_Type = TAG_Compound;
m_Result.reserve(100 * 1024);
m_Result.push_back(TAG_Compound);
WriteString("", 0);
WriteString(a_RootTagName.data(), a_RootTagName.size());
}

View File

@ -213,7 +213,7 @@ protected:
class cFastNBTWriter
{
public:
cFastNBTWriter(void);
cFastNBTWriter(const AString & a_RootTagName = "");
void BeginCompound(const AString & a_Name);
void EndCompound(void);