From ed47a8e409ac8d5273a3d6b61aba90248cc4c70d Mon Sep 17 00:00:00 2001 From: "madmaxoft@gmail.com" Date: Thu, 7 Feb 2013 10:09:42 +0000 Subject: 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 --- MCServer/Plugins/Debuggers/Debuggers.lua | 19 +++++++++++++ source/Bindings.cpp | 38 +++++++++++++++++++++++++- source/Bindings.h | 2 +- source/BlockArea.cpp | 46 ++++++++++++++++++++++++++++++++ source/BlockArea.h | 3 +++ source/OSSupport/GZipFile.cpp | 28 +++++++++++++++++++ source/OSSupport/GZipFile.h | 5 ++-- source/WorldStorage/FastNBT.cpp | 4 +-- source/WorldStorage/FastNBT.h | 2 +- 9 files changed, 140 insertions(+), 7 deletions(-) diff --git a/MCServer/Plugins/Debuggers/Debuggers.lua b/MCServer/Plugins/Debuggers/Debuggers.lua index ba410dd49..c80957511 100644 --- a/MCServer/Plugins/Debuggers/Debuggers.lua +++ b/MCServer/Plugins/Debuggers/Debuggers.lua @@ -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 diff --git a/source/Bindings.cpp b/source/Bindings.cpp index ffbb74431..9843e6578 100644 --- a/source/Bindings.cpp +++ b/source/Bindings.cpp @@ -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); diff --git a/source/Bindings.h b/source/Bindings.h index 2ee3ca938..c58c2044d 100644 --- a/source/Bindings.h +++ b/source/Bindings.h @@ -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 */ diff --git a/source/BlockArea.cpp b/source/BlockArea.cpp index 5cc78fd88..f7132f50d 100644 --- a/source/BlockArea.cpp +++ b/source/BlockArea.cpp @@ -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 ( diff --git a/source/BlockArea.h b/source/BlockArea.h index 58f5cf061..2c4a9e3ba 100644 --- a/source/BlockArea.h +++ b/source/BlockArea.h @@ -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); diff --git a/source/OSSupport/GZipFile.cpp b/source/OSSupport/GZipFile.cpp index 8f5edd3d7..dbdef3a8b 100644 --- a/source/OSSupport/GZipFile.cpp +++ b/source/OSSupport/GZipFile.cpp @@ -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); +} + + + + diff --git a/source/OSSupport/GZipFile.h b/source/OSSupport/GZipFile.h index bb8a88ec8..10fb447dd 100644 --- a/source/OSSupport/GZipFile.h +++ b/source/OSSupport/GZipFile.h @@ -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; } ; diff --git a/source/WorldStorage/FastNBT.cpp b/source/WorldStorage/FastNBT.cpp index a81be9a89..4a9a9df9f 100644 --- a/source/WorldStorage/FastNBT.cpp +++ b/source/WorldStorage/FastNBT.cpp @@ -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()); } diff --git a/source/WorldStorage/FastNBT.h b/source/WorldStorage/FastNBT.h index e4cb3179b..5a4b69866 100644 --- a/source/WorldStorage/FastNBT.h +++ b/source/WorldStorage/FastNBT.h @@ -213,7 +213,7 @@ protected: class cFastNBTWriter { public: - cFastNBTWriter(void); + cFastNBTWriter(const AString & a_RootTagName = ""); void BeginCompound(const AString & a_Name); void EndCompound(void); -- cgit v1.2.3