From 4c370798d52b1b7c055c49ff4a38f73cf720c82e Mon Sep 17 00:00:00 2001 From: "madmaxoft@gmail.com" Date: Sat, 6 Oct 2012 16:58:31 +0000 Subject: BlockArea writing support (BlockTypes with BlockMeta only) git-svn-id: http://mc-server.googlecode.com/svn/trunk@933 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- source/Bindings.cpp | 301 ++++++++++++++++++++++++++++++++++++++++++++++++++- source/Bindings.h | 2 +- source/BlockArea.cpp | 65 ++++++++++- source/BlockArea.h | 33 ++++-- source/Chunk.cpp | 53 +++++++++ source/Chunk.h | 4 + source/ChunkMap.cpp | 39 +++++++ source/ChunkMap.h | 4 + source/Globals.h | 3 + source/World.cpp | 9 ++ source/World.h | 7 ++ 11 files changed, 504 insertions(+), 16 deletions(-) (limited to 'source') diff --git a/source/Bindings.cpp b/source/Bindings.cpp index 27ed6a0a3..3c93ed6f0 100644 --- a/source/Bindings.cpp +++ b/source/Bindings.cpp @@ -1,6 +1,6 @@ /* ** Lua binding: AllToLua -** Generated automatically by tolua++-1.0.92 on 10/03/12 10:03:23. +** Generated automatically by tolua++-1.0.92 on 10/06/12 17:42:13. */ #ifndef __cplusplus @@ -6124,6 +6124,38 @@ static int tolua_AllToLua_cPlayer_GetInventory00(lua_State* tolua_S) } #endif //#ifndef TOLUA_DISABLE +/* method: GetEquippedItem of class cPlayer */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_GetEquippedItem00 +static int tolua_AllToLua_cPlayer_GetEquippedItem00(lua_State* tolua_S) +{ +#ifndef TOLUA_RELEASE + tolua_Error tolua_err; + if ( + !tolua_isusertype(tolua_S,1,"const cPlayer",0,&tolua_err) || + !tolua_isnoobj(tolua_S,2,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + const cPlayer* self = (const cPlayer*) tolua_tousertype(tolua_S,1,0); +#ifndef TOLUA_RELEASE + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetEquippedItem'", NULL); +#endif + { + const cItem& tolua_ret = (const cItem&) self->GetEquippedItem(); + tolua_pushusertype(tolua_S,(void*)&tolua_ret,"const cItem"); + } + } + return 1; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'GetEquippedItem'.",&tolua_err); + return 0; +#endif +} +#endif //#ifndef TOLUA_DISABLE + /* method: TeleportTo of class cPlayer */ #ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_TeleportTo00 static int tolua_AllToLua_cPlayer_TeleportTo00(lua_State* tolua_S) @@ -18853,6 +18885,40 @@ tolua_lerror: } #endif //#ifndef TOLUA_DISABLE +/* method: DumpToRawFile of class cBlockArea */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cBlockArea_DumpToRawFile00 +static int tolua_AllToLua_cBlockArea_DumpToRawFile00(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 'DumpToRawFile'", NULL); +#endif + { + self->DumpToRawFile(a_FileName); + tolua_pushcppstring(tolua_S,(const char*)a_FileName); + } + } + return 1; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'DumpToRawFile'.",&tolua_err); + return 0; +#endif +} +#endif //#ifndef TOLUA_DISABLE + /* method: SetRelBlockType of class cBlockArea */ #ifndef TOLUA_DISABLE_tolua_AllToLua_cBlockArea_SetRelBlockType00 static int tolua_AllToLua_cBlockArea_SetRelBlockType00(lua_State* tolua_S) @@ -19469,6 +19535,102 @@ static int tolua_AllToLua_cBlockArea_GetBlockSkyLight00(lua_State* tolua_S) } #endif //#ifndef TOLUA_DISABLE +/* method: GetSizeX of class cBlockArea */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cBlockArea_GetSizeX00 +static int tolua_AllToLua_cBlockArea_GetSizeX00(lua_State* tolua_S) +{ +#ifndef TOLUA_RELEASE + tolua_Error tolua_err; + if ( + !tolua_isusertype(tolua_S,1,"const cBlockArea",0,&tolua_err) || + !tolua_isnoobj(tolua_S,2,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + const cBlockArea* self = (const cBlockArea*) tolua_tousertype(tolua_S,1,0); +#ifndef TOLUA_RELEASE + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetSizeX'", NULL); +#endif + { + int tolua_ret = (int) self->GetSizeX(); + tolua_pushnumber(tolua_S,(lua_Number)tolua_ret); + } + } + return 1; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'GetSizeX'.",&tolua_err); + return 0; +#endif +} +#endif //#ifndef TOLUA_DISABLE + +/* method: GetSizeY of class cBlockArea */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cBlockArea_GetSizeY00 +static int tolua_AllToLua_cBlockArea_GetSizeY00(lua_State* tolua_S) +{ +#ifndef TOLUA_RELEASE + tolua_Error tolua_err; + if ( + !tolua_isusertype(tolua_S,1,"const cBlockArea",0,&tolua_err) || + !tolua_isnoobj(tolua_S,2,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + const cBlockArea* self = (const cBlockArea*) tolua_tousertype(tolua_S,1,0); +#ifndef TOLUA_RELEASE + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetSizeY'", NULL); +#endif + { + int tolua_ret = (int) self->GetSizeY(); + tolua_pushnumber(tolua_S,(lua_Number)tolua_ret); + } + } + return 1; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'GetSizeY'.",&tolua_err); + return 0; +#endif +} +#endif //#ifndef TOLUA_DISABLE + +/* method: GetSizeZ of class cBlockArea */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cBlockArea_GetSizeZ00 +static int tolua_AllToLua_cBlockArea_GetSizeZ00(lua_State* tolua_S) +{ +#ifndef TOLUA_RELEASE + tolua_Error tolua_err; + if ( + !tolua_isusertype(tolua_S,1,"const cBlockArea",0,&tolua_err) || + !tolua_isnoobj(tolua_S,2,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + const cBlockArea* self = (const cBlockArea*) tolua_tousertype(tolua_S,1,0); +#ifndef TOLUA_RELEASE + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetSizeZ'", NULL); +#endif + { + int tolua_ret = (int) self->GetSizeZ(); + tolua_pushnumber(tolua_S,(lua_Number)tolua_ret); + } + } + return 1; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'GetSizeZ'.",&tolua_err); + return 0; +#endif +} +#endif //#ifndef TOLUA_DISABLE + /* method: GetDataTypes of class cBlockArea */ #ifndef TOLUA_DISABLE_tolua_AllToLua_cBlockArea_GetDataTypes00 static int tolua_AllToLua_cBlockArea_GetDataTypes00(lua_State* tolua_S) @@ -19501,6 +19663,134 @@ static int tolua_AllToLua_cBlockArea_GetDataTypes00(lua_State* tolua_S) } #endif //#ifndef TOLUA_DISABLE +/* method: HasBlockTypes of class cBlockArea */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cBlockArea_HasBlockTypes00 +static int tolua_AllToLua_cBlockArea_HasBlockTypes00(lua_State* tolua_S) +{ +#ifndef TOLUA_RELEASE + tolua_Error tolua_err; + if ( + !tolua_isusertype(tolua_S,1,"const cBlockArea",0,&tolua_err) || + !tolua_isnoobj(tolua_S,2,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + const cBlockArea* self = (const cBlockArea*) tolua_tousertype(tolua_S,1,0); +#ifndef TOLUA_RELEASE + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'HasBlockTypes'", NULL); +#endif + { + bool tolua_ret = (bool) self->HasBlockTypes(); + tolua_pushboolean(tolua_S,(bool)tolua_ret); + } + } + return 1; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'HasBlockTypes'.",&tolua_err); + return 0; +#endif +} +#endif //#ifndef TOLUA_DISABLE + +/* method: HasBlockMetas of class cBlockArea */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cBlockArea_HasBlockMetas00 +static int tolua_AllToLua_cBlockArea_HasBlockMetas00(lua_State* tolua_S) +{ +#ifndef TOLUA_RELEASE + tolua_Error tolua_err; + if ( + !tolua_isusertype(tolua_S,1,"const cBlockArea",0,&tolua_err) || + !tolua_isnoobj(tolua_S,2,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + const cBlockArea* self = (const cBlockArea*) tolua_tousertype(tolua_S,1,0); +#ifndef TOLUA_RELEASE + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'HasBlockMetas'", NULL); +#endif + { + bool tolua_ret = (bool) self->HasBlockMetas(); + tolua_pushboolean(tolua_S,(bool)tolua_ret); + } + } + return 1; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'HasBlockMetas'.",&tolua_err); + return 0; +#endif +} +#endif //#ifndef TOLUA_DISABLE + +/* method: HasBlockLights of class cBlockArea */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cBlockArea_HasBlockLights00 +static int tolua_AllToLua_cBlockArea_HasBlockLights00(lua_State* tolua_S) +{ +#ifndef TOLUA_RELEASE + tolua_Error tolua_err; + if ( + !tolua_isusertype(tolua_S,1,"const cBlockArea",0,&tolua_err) || + !tolua_isnoobj(tolua_S,2,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + const cBlockArea* self = (const cBlockArea*) tolua_tousertype(tolua_S,1,0); +#ifndef TOLUA_RELEASE + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'HasBlockLights'", NULL); +#endif + { + bool tolua_ret = (bool) self->HasBlockLights(); + tolua_pushboolean(tolua_S,(bool)tolua_ret); + } + } + return 1; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'HasBlockLights'.",&tolua_err); + return 0; +#endif +} +#endif //#ifndef TOLUA_DISABLE + +/* method: HasBlockSkyLights of class cBlockArea */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cBlockArea_HasBlockSkyLights00 +static int tolua_AllToLua_cBlockArea_HasBlockSkyLights00(lua_State* tolua_S) +{ +#ifndef TOLUA_RELEASE + tolua_Error tolua_err; + if ( + !tolua_isusertype(tolua_S,1,"const cBlockArea",0,&tolua_err) || + !tolua_isnoobj(tolua_S,2,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + const cBlockArea* self = (const cBlockArea*) tolua_tousertype(tolua_S,1,0); +#ifndef TOLUA_RELEASE + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'HasBlockSkyLights'", NULL); +#endif + { + bool tolua_ret = (bool) self->HasBlockSkyLights(); + tolua_pushboolean(tolua_S,(bool)tolua_ret); + } + } + return 1; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'HasBlockSkyLights'.",&tolua_err); + return 0; +#endif +} +#endif //#ifndef TOLUA_DISABLE + /* method: FillBlocks of class cLuaChunk */ #ifndef TOLUA_DISABLE_tolua_AllToLua_cLuaChunk_FillBlocks00 static int tolua_AllToLua_cLuaChunk_FillBlocks00(lua_State* tolua_S) @@ -21878,6 +22168,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S) tolua_function(tolua_S,"IsOnGround",tolua_AllToLua_cPlayer_IsOnGround00); tolua_function(tolua_S,"GetStance",tolua_AllToLua_cPlayer_GetStance00); tolua_function(tolua_S,"GetInventory",tolua_AllToLua_cPlayer_GetInventory00); + tolua_function(tolua_S,"GetEquippedItem",tolua_AllToLua_cPlayer_GetEquippedItem00); tolua_function(tolua_S,"TeleportTo",tolua_AllToLua_cPlayer_TeleportTo00); tolua_function(tolua_S,"GetGameMode",tolua_AllToLua_cPlayer_GetGameMode00); tolua_function(tolua_S,"GetIP",tolua_AllToLua_cPlayer_GetIP00); @@ -22441,6 +22732,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S) tolua_function(tolua_S,"Read",tolua_AllToLua_cBlockArea_Read01); tolua_function(tolua_S,"Write",tolua_AllToLua_cBlockArea_Write00); tolua_function(tolua_S,"Write",tolua_AllToLua_cBlockArea_Write01); + tolua_function(tolua_S,"DumpToRawFile",tolua_AllToLua_cBlockArea_DumpToRawFile00); tolua_function(tolua_S,"SetRelBlockType",tolua_AllToLua_cBlockArea_SetRelBlockType00); tolua_function(tolua_S,"SetBlockType",tolua_AllToLua_cBlockArea_SetBlockType00); tolua_function(tolua_S,"SetRelBlockMeta",tolua_AllToLua_cBlockArea_SetRelBlockMeta00); @@ -22457,7 +22749,14 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S) tolua_function(tolua_S,"GetBlockLight",tolua_AllToLua_cBlockArea_GetBlockLight00); tolua_function(tolua_S,"GetRelBlockSkyLight",tolua_AllToLua_cBlockArea_GetRelBlockSkyLight00); tolua_function(tolua_S,"GetBlockSkyLight",tolua_AllToLua_cBlockArea_GetBlockSkyLight00); + tolua_function(tolua_S,"GetSizeX",tolua_AllToLua_cBlockArea_GetSizeX00); + tolua_function(tolua_S,"GetSizeY",tolua_AllToLua_cBlockArea_GetSizeY00); + tolua_function(tolua_S,"GetSizeZ",tolua_AllToLua_cBlockArea_GetSizeZ00); tolua_function(tolua_S,"GetDataTypes",tolua_AllToLua_cBlockArea_GetDataTypes00); + tolua_function(tolua_S,"HasBlockTypes",tolua_AllToLua_cBlockArea_HasBlockTypes00); + tolua_function(tolua_S,"HasBlockMetas",tolua_AllToLua_cBlockArea_HasBlockMetas00); + tolua_function(tolua_S,"HasBlockLights",tolua_AllToLua_cBlockArea_HasBlockLights00); + tolua_function(tolua_S,"HasBlockSkyLights",tolua_AllToLua_cBlockArea_HasBlockSkyLights00); tolua_endmodule(tolua_S); tolua_cclass(tolua_S,"cLuaChunk","cLuaChunk","",NULL); tolua_beginmodule(tolua_S,"cLuaChunk"); diff --git a/source/Bindings.h b/source/Bindings.h index 56b73ab50..d006609b1 100644 --- a/source/Bindings.h +++ b/source/Bindings.h @@ -1,6 +1,6 @@ /* ** Lua binding: AllToLua -** Generated automatically by tolua++-1.0.92 on 10/03/12 10:03:23. +** Generated automatically by tolua++-1.0.92 on 10/06/12 17:42:14. */ /* Exported function */ diff --git a/source/BlockArea.cpp b/source/BlockArea.cpp index caeaf609e..8c3888782 100644 --- a/source/BlockArea.cpp +++ b/source/BlockArea.cpp @@ -50,6 +50,7 @@ void cBlockArea::Clear(void) + bool cBlockArea::Read(cWorld * a_World, int a_MinBlockX, int a_MaxBlockX, int a_MinBlockY, int a_MaxBlockY, int a_MinBlockZ, int a_MaxBlockZ, int a_DataTypes) { // Normalize the coords: @@ -66,6 +67,11 @@ bool cBlockArea::Read(cWorld * a_World, int a_MinBlockX, int a_MaxBlockX, int a_ std::swap(a_MinBlockZ, a_MaxBlockZ); } + // Include the Max coords: + a_MaxBlockX += 1; + a_MaxBlockY += 1; + a_MaxBlockZ += 1; + // Check coords validity: if (a_MinBlockY < 0) { @@ -111,6 +117,7 @@ bool cBlockArea::Read(cWorld * a_World, int a_MinBlockX, int a_MaxBlockX, int a_ Clear(); return false; } + return true; } @@ -120,15 +127,66 @@ bool cBlockArea::Read(cWorld * a_World, int a_MinBlockX, int a_MaxBlockX, int a_ bool cBlockArea::Write(cWorld * a_World, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes) { - // TODO - ASSERT(!"Not implemented yet"); - return false; + ASSERT((a_DataTypes & GetDataTypes()) == a_DataTypes); // Are you requesting only the data that I have? + a_DataTypes = a_DataTypes & GetDataTypes(); // For release builds, silently cut off the datatypes that I don't have + + // Check coords validity: + if (a_MinBlockY < 0) + { + LOGWARNING("cBlockArea:Read(): MinBlockY less than zero, adjusting to zero"); + a_MinBlockY = 0; + } + else if (a_MinBlockY >= cChunkDef::Height - m_SizeY) + { + LOGWARNING("cBlockArea::Read(): MinBlockY + m_SizeY more than chunk height, adjusting to chunk height"); + a_MinBlockY = cChunkDef::Height - m_SizeY - 1; + } + + return a_World->WriteBlockArea(*this, a_MinBlockX, a_MinBlockY, a_MinBlockZ, a_DataTypes); } +void cBlockArea::DumpToRawFile(const AString & a_FileName) +{ + cFile f; + if (!f.Open(a_FileName, cFile::fmWrite)) + { + LOGWARNING("cBlockArea: Cannot open file \"%s\" for raw dump", a_FileName.c_str()); + return; + } + UInt32 SizeX = ntohl(m_SizeX); + UInt32 SizeY = ntohl(m_SizeY); + UInt32 SizeZ = ntohl(m_SizeZ); + f.Write(&SizeX, 4); + f.Write(&SizeY, 4); + f.Write(&SizeZ, 4); + unsigned char DataTypes = GetDataTypes(); + f.Write(&DataTypes, 1); + int NumBlocks = GetBlockCount(); + if (HasBlockTypes()) + { + f.Write(m_BlockTypes, NumBlocks * sizeof(BLOCKTYPE)); + } + if (HasBlockMetas()) + { + f.Write(m_BlockMetas, NumBlocks); + } + if (HasBlockLights()) + { + f.Write(m_BlockLight, NumBlocks); + } + if (HasBlockSkyLights()) + { + f.Write(m_BlockSkyLight, NumBlocks); + } +} + + + + void cBlockArea::SetRelBlockType(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType) { @@ -623,4 +681,3 @@ void cBlockArea::cChunkReader::BlockSkyLight(const NIBBLETYPE * a_BlockSkyLight) - diff --git a/source/BlockArea.h b/source/BlockArea.h index 5abdab3bb..8d374eaad 100644 --- a/source/BlockArea.h +++ b/source/BlockArea.h @@ -4,6 +4,8 @@ // Interfaces to the cBlockArea object representing an area of block data that can be queried from cWorld and then accessed again without further queries // The object also supports writing the blockdata back into cWorld, even into other coords +// NOTE: All Nibble values (meta, blocklight, skylight) are stored one-nibble-per-byte for faster access / editting! + @@ -48,9 +50,12 @@ public: /// Reads an area of blocks specified. Returns true if successful. All coords are inclusive. bool Read(cWorld * a_World, int a_MinBlockX, int a_MaxBlockX, int a_MinBlockY, int a_MaxBlockY, int a_MinBlockZ, int a_MaxBlockZ, int a_DataTypes = baTypes | baMetas); - /// Writes the area back into cWorld at the coords specified. Returns true if successful. + /// Writes the area back into cWorld at the coords specified. Returns true if successful in all chunks, false if only partially / not at all bool Write(cWorld * a_World, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes = baTypes | baMetas); + /// For testing purposes only, dumps the area into a file. + void DumpToRawFile(const AString & a_FileName); + // TODO: Write() is not too good an interface: if it fails, there's no way to repeat only for the parts that didn't write // A better way may be to return a list of cBlockAreas for each part that didn't succeed writing, so that the caller may try again @@ -74,21 +79,30 @@ public: NIBBLETYPE GetRelBlockSkyLight(int a_RelX, int a_RelY, int a_RelZ); NIBBLETYPE GetBlockSkyLight (int a_BlockX, int a_BlockY, int a_BlockZ); + int GetSizeX(void) const { return m_SizeX; } + int GetSizeY(void) const { return m_SizeY; } + int GetSizeZ(void) const { return m_SizeZ; } + /// Returns the datatypes that are stored in the object (bitmask of baXXX values) int GetDataTypes(void) const; + bool HasBlockTypes (void) const { return (m_BlockTypes != NULL); } + bool HasBlockMetas (void) const { return (m_BlockMetas != NULL); } + bool HasBlockLights (void) const { return (m_BlockLight != NULL); } + bool HasBlockSkyLights(void) const { return (m_BlockSkyLight != NULL); } + // tolua_end // Clients can use these for faster access to all blocktypes. Be careful though! /// Returns the internal pointer to the block types - BLOCKTYPE * GetBlockTypes(void) { return m_BlockTypes; } - int GetBlockCount(void) const { return m_SizeX * m_SizeY * m_SizeZ; } - - // tolua_begin + BLOCKTYPE * GetBlockTypes (void) { return m_BlockTypes; } + NIBBLETYPE * GetBlockMetas (void) { return m_BlockMetas; } // NOTE: one byte per block! + NIBBLETYPE * GetBlockLight (void) { return m_BlockLight; } // NOTE: one byte per block! + NIBBLETYPE * GetBlockSkyLight(void) { return m_BlockSkyLight; } // NOTE: one byte per block! + int GetBlockCount(void) const { return m_SizeX * m_SizeY * m_SizeZ; } + int MakeIndex(int a_RelX, int a_RelY, int a_RelZ); protected: - - // tolua_end class cChunkReader : public cChunkDataCallback @@ -114,7 +128,6 @@ protected: virtual void BlockSkyLight(const NIBBLETYPE * a_BlockSkyLight) override; } ; - // tolua_begin int m_OriginX; int m_OriginY; @@ -130,8 +143,6 @@ protected: bool SetSize(int a_SizeX, int a_SizeY, int a_SizeZ, int a_DataTypes); - int MakeIndex(int a_RelX, int a_RelY, int a_RelZ); - // Basic Setters: void SetRelNibble(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_Value, NIBBLETYPE * a_Array); void SetNibble (int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Value, NIBBLETYPE * a_Array); @@ -139,6 +150,8 @@ protected: // Basic Getters: NIBBLETYPE GetRelNibble(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE * a_Array); NIBBLETYPE GetNibble (int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE * a_Array); + + // tolua_begin } ; // tolua_end diff --git a/source/Chunk.cpp b/source/Chunk.cpp index 149adaa62..72b065bdd 100644 --- a/source/Chunk.cpp +++ b/source/Chunk.cpp @@ -317,6 +317,59 @@ void cChunk::GetBlockData(BLOCKTYPE * a_BlockData) +void cChunk::WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes) +{ + if ((a_DataTypes & (cBlockArea::baTypes | cBlockArea::baMetas)) != (cBlockArea::baTypes | cBlockArea::baMetas)) + { + LOGWARNING("cChunk::WriteBlockArea(): unsupported datatype request, can write only types + metas (0x%x), requested 0x%x. Ignoring.", + (cBlockArea::baTypes | cBlockArea::baMetas), a_DataTypes & (cBlockArea::baTypes | cBlockArea::baMetas) + ); + return; + } + + // SizeX, SizeZ are the dimensions of the block data to copy to the chunk (size of the geometric union) + + int BlockStartX = std::max(a_MinBlockX, m_PosX * cChunkDef::Width); + int BlockEndX = std::min(a_MinBlockX + a_Area.GetSizeX(), (m_PosX + 1) * cChunkDef::Width); + int BlockStartZ = std::max(a_MinBlockZ, m_PosZ * cChunkDef::Width); + int BlockEndZ = std::min(a_MinBlockZ + a_Area.GetSizeZ(), (m_PosZ + 1) * cChunkDef::Width); + int SizeX = BlockEndX - BlockStartX; + int SizeZ = BlockEndZ - BlockStartZ; + int OffX = BlockStartX - m_PosX * cChunkDef::Width; + int OffZ = BlockStartZ - m_PosZ * cChunkDef::Width; + int BaseX = BlockStartX - a_MinBlockX; + int BaseZ = BlockStartZ - a_MinBlockZ; + int SizeY = a_Area.GetSizeY(); + + // TODO: Improve this by not calling FastSetBlock() and doing the processing here + // so that the heightmap is touched only once for each column. + BLOCKTYPE * AreaBlockTypes = a_Area.GetBlockTypes(); + NIBBLETYPE * AreaBlockMetas = a_Area.GetBlockMetas(); + for (int y = 0; y < SizeY; y++) + { + int ChunkY = a_MinBlockY + y; + int AreaY = y; + for (int z = 0; z < SizeZ; z++) + { + int ChunkZ = OffZ + z; + int AreaZ = BaseZ + z; + for (int x = 0; x < SizeX; x++) + { + int ChunkX = OffX + x; + int AreaX = BaseX + x; + int idx = a_Area.MakeIndex(AreaX, AreaY, AreaZ); + BLOCKTYPE BlockType = AreaBlockTypes[idx]; + NIBBLETYPE BlockMeta = AreaBlockMetas[idx]; + FastSetBlock(ChunkX, ChunkY, ChunkZ, BlockType, BlockMeta); + } // for x + } // for z + } // for y +} + + + + + /// Returns true if there is a block entity at the coords specified bool cChunk::HasBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ) { diff --git a/source/Chunk.h b/source/Chunk.h index 480dea796..0a51e99d2 100644 --- a/source/Chunk.h +++ b/source/Chunk.h @@ -43,6 +43,7 @@ class cBlockArea; class cPawn; class cPickup; class cChunkDataSerializer; +class cBlockArea; typedef std::list cClientHandleList; typedef cItemCallback cEntityCallback; @@ -108,6 +109,9 @@ public: /// Copies entire block data into a_BlockData, the entire 4 arrays (Type, Meta, Light, SkyLight) void GetBlockData(BLOCKTYPE * a_BlockData); + /// Writes the specified cBlockArea at the coords specified. Note that the coords may extend beyond the chunk! + void WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes); + /// Returns true if there is a block entity at the coords specified bool HasBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ); diff --git a/source/ChunkMap.cpp b/source/ChunkMap.cpp index af8f09820..671eac708 100644 --- a/source/ChunkMap.cpp +++ b/source/ChunkMap.cpp @@ -10,6 +10,7 @@ #include "Pickup.h" #include "Chunk.h" #include "Generating/Trees.h" // used in cChunkMap::ReplaceTreeBlocks() for tree block discrimination +#include "BlockArea.h" #ifndef _WIN32 #include // abs @@ -1493,6 +1494,44 @@ bool cChunkMap::ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinCh +bool cChunkMap::WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes) +{ + // Convert block coords to chunks coords: + int MinChunkX, MaxChunkX; + int MinChunkZ, MaxChunkZ; + int MinBlockX = a_MinBlockX; + int MinBlockY = a_MinBlockY; + int MinBlockZ = a_MinBlockZ; + int MaxBlockX = a_MinBlockX + a_Area.GetSizeX(); + int MaxBlockY = a_MinBlockY + a_Area.GetSizeY(); + int MaxBlockZ = a_MinBlockZ + a_Area.GetSizeZ(); + cChunkDef::AbsoluteToRelative(MinBlockX, MinBlockY, MinBlockZ, MinChunkX, MinChunkZ); + cChunkDef::AbsoluteToRelative(MaxBlockX, MaxBlockY, MaxBlockZ, MaxChunkX, MaxChunkZ); + + // Iterate over chunks, write data into each: + bool Result = true; + cCSLock Lock(m_CSLayers); + for (int z = MinChunkZ; z <= MaxChunkZ; z++) + { + for (int x = MinChunkX; x <= MaxChunkX; x++) + { + cChunkPtr Chunk = GetChunkNoLoad(x, ZERO_CHUNK_Y, z); + if ((Chunk == NULL) || (!Chunk->IsValid())) + { + // Not present / not valid + Result = false; + continue; + } + Chunk->WriteBlockArea(a_Area, a_MinBlockX, a_MinBlockY, a_MinBlockZ, a_DataTypes); + } // for x + } // for z + return Result; +} + + + + + void cChunkMap::GetChunkStats(int & a_NumChunksValid, int & a_NumChunksDirty) { a_NumChunksValid = 0; diff --git a/source/ChunkMap.h b/source/ChunkMap.h index 165e41f10..bfdbc889b 100644 --- a/source/ChunkMap.h +++ b/source/ChunkMap.h @@ -22,6 +22,7 @@ class cFurnaceEntity; class cPawn; class cPickup; class cChunkDataSerializer; +class cBlockArea; typedef std::list cClientHandleList; typedef cChunk * cChunkPtr; @@ -216,6 +217,9 @@ public: /// Calls the callback for each chunk in the coords specified (all cords are inclusive). Returns true if all chunks have been processed successfully bool ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinChunkZ, int a_MaxChunkZ, cChunkDataCallback & a_Callback); + /// Writes the block area into the specified coords. Returns true if all chunks have been processed. Prefer cBlockArea::Write() instead. + bool WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes); + /// Returns the number of valid chunks and the number of dirty chunks void GetChunkStats(int & a_NumChunksValid, int & a_NumChunksDirty); diff --git a/source/Globals.h b/source/Globals.h index b9892c933..01b118cf8 100644 --- a/source/Globals.h +++ b/source/Globals.h @@ -70,6 +70,9 @@ typedef long long Int64; typedef int Int32; typedef short Int16; +typedef unsigned long long UInt64; +typedef unsigned int UInt32; +typedef unsigned short UInt16; diff --git a/source/World.cpp b/source/World.cpp index 7acbf8a39..961d99d7c 100644 --- a/source/World.cpp +++ b/source/World.cpp @@ -1135,6 +1135,15 @@ void cWorld::GetBlockTypeMeta(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYP +bool cWorld::WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes) +{ + return m_ChunkMap->WriteBlockArea(a_Area, a_MinBlockX, a_MinBlockY, a_MinBlockZ, a_DataTypes); +} + + + + + void cWorld::SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double a_BlockY, double a_BlockZ, double a_FlyAwaySpeed) { MTRand r1; diff --git a/source/World.h b/source/World.h index 16c80bd82..0fb2bac7c 100644 --- a/source/World.h +++ b/source/World.h @@ -252,6 +252,13 @@ public: // TODO: NIBBLETYPE GetBlockActualLight(int a_BlockX, int a_BlockY, int a_BlockZ); // tolua_export void GetBlockTypeMeta(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta); // tolua_export + /** Writes the block area into the specified coords. + Returns true if all chunks have been processed. + Prefer cBlockArea::Write() instead, this is the internal implementation; cBlockArea does error checking, too. + a_DataTypes is a bitmask of cBlockArea::baXXX constants ORed together. + */ + bool WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes); + /// Spawns item pickups for each item in the list. May compress pickups if too many entities: void SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double a_BlockY, double a_BlockZ, double a_FlyAwaySpeed = 1.0); -- cgit v1.2.3