summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authormadmaxoft@gmail.com <madmaxoft@gmail.com@0a769ca7-a7f5-676a-18bf-c427514a06d6>2012-10-06 18:58:31 +0200
committermadmaxoft@gmail.com <madmaxoft@gmail.com@0a769ca7-a7f5-676a-18bf-c427514a06d6>2012-10-06 18:58:31 +0200
commit4c370798d52b1b7c055c49ff4a38f73cf720c82e (patch)
treecb9c7233b4b55d8e6cb1fab410b81ea16f89d353 /source
parentLua plugins can get player's equipped item (diff)
downloadcuberite-4c370798d52b1b7c055c49ff4a38f73cf720c82e.tar
cuberite-4c370798d52b1b7c055c49ff4a38f73cf720c82e.tar.gz
cuberite-4c370798d52b1b7c055c49ff4a38f73cf720c82e.tar.bz2
cuberite-4c370798d52b1b7c055c49ff4a38f73cf720c82e.tar.lz
cuberite-4c370798d52b1b7c055c49ff4a38f73cf720c82e.tar.xz
cuberite-4c370798d52b1b7c055c49ff4a38f73cf720c82e.tar.zst
cuberite-4c370798d52b1b7c055c49ff4a38f73cf720c82e.zip
Diffstat (limited to 'source')
-rw-r--r--source/Bindings.cpp301
-rw-r--r--source/Bindings.h2
-rw-r--r--source/BlockArea.cpp65
-rw-r--r--source/BlockArea.h33
-rw-r--r--source/Chunk.cpp53
-rw-r--r--source/Chunk.h4
-rw-r--r--source/ChunkMap.cpp39
-rw-r--r--source/ChunkMap.h4
-rw-r--r--source/Globals.h3
-rw-r--r--source/World.cpp9
-rw-r--r--source/World.h7
11 files changed, 504 insertions, 16 deletions
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<cClientHandle *> cClientHandleList;
typedef cItemCallback<cEntity> 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 <cstdlib> // 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<cClientHandle *> 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);