From 7b10068370e42def4e28785d2e49acba52bad1fd Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sun, 18 Aug 2013 22:44:22 +0200 Subject: [PATCH] Implemented cWorld:QueueSetBlock(), as requested for delayed blocksetting. Untested yet, so might not work. --- source/Bindings.cpp | 82 ++++++++++++++++++++++++++++++++++++++++++++- source/Bindings.h | 2 +- source/Chunk.cpp | 36 ++++++++++++++++++++ source/Chunk.h | 24 +++++++++++++ source/ChunkMap.cpp | 17 ++++++++++ source/ChunkMap.h | 1 + source/World.cpp | 9 +++++ source/World.h | 19 +++++++++-- 8 files changed, 186 insertions(+), 4 deletions(-) diff --git a/source/Bindings.cpp b/source/Bindings.cpp index d33be08ac..fa5b8f975 100644 --- a/source/Bindings.cpp +++ b/source/Bindings.cpp @@ -1,6 +1,6 @@ /* ** Lua binding: AllToLua -** Generated automatically by tolua++-1.0.92 on 08/18/13 13:15:34. +** Generated automatically by tolua++-1.0.92 on 08/18/13 22:18:01. */ #ifndef __cplusplus @@ -10726,6 +10726,49 @@ static int tolua_AllToLua_cWorld_FastSetBlock00(lua_State* tolua_S) } #endif //#ifndef TOLUA_DISABLE +/* method: QueueSetBlock of class cWorld */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cWorld_QueueSetBlock00 +static int tolua_AllToLua_cWorld_QueueSetBlock00(lua_State* tolua_S) +{ +#ifndef TOLUA_RELEASE + tolua_Error tolua_err; + if ( + !tolua_isusertype(tolua_S,1,"cWorld",0,&tolua_err) || + !tolua_isnumber(tolua_S,2,0,&tolua_err) || + !tolua_isnumber(tolua_S,3,0,&tolua_err) || + !tolua_isnumber(tolua_S,4,0,&tolua_err) || + !tolua_isnumber(tolua_S,5,0,&tolua_err) || + !tolua_isnumber(tolua_S,6,0,&tolua_err) || + !tolua_isnumber(tolua_S,7,0,&tolua_err) || + !tolua_isnoobj(tolua_S,8,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + cWorld* self = (cWorld*) tolua_tousertype(tolua_S,1,0); + int a_BlockX = ((int) tolua_tonumber(tolua_S,2,0)); + int a_BLockY = ((int) tolua_tonumber(tolua_S,3,0)); + int a_BlockZ = ((int) tolua_tonumber(tolua_S,4,0)); + unsigned char a_BlockType = (( unsigned char) tolua_tonumber(tolua_S,5,0)); + unsigned char a_BlockMeta = (( unsigned char) tolua_tonumber(tolua_S,6,0)); + int a_TickDelay = ((int) tolua_tonumber(tolua_S,7,0)); +#ifndef TOLUA_RELEASE + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'QueueSetBlock'", NULL); +#endif + { + self->QueueSetBlock(a_BlockX,a_BLockY,a_BlockZ,a_BlockType,a_BlockMeta,a_TickDelay); + } + } + return 0; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'QueueSetBlock'.",&tolua_err); + return 0; +#endif +} +#endif //#ifndef TOLUA_DISABLE + /* method: GetBlock of class cWorld */ #ifndef TOLUA_DISABLE_tolua_AllToLua_cWorld_GetBlock00 static int tolua_AllToLua_cWorld_GetBlock00(lua_State* tolua_S) @@ -27149,7 +27192,11 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S) tolua_constant(tolua_S,"E_BLOCK_QUARTZ_STAIR",E_BLOCK_QUARTZ_STAIR); tolua_constant(tolua_S,"E_BLOCK_ACTIVATOR_RAIL",E_BLOCK_ACTIVATOR_RAIL); tolua_constant(tolua_S,"E_BLOCK_DROPPER",E_BLOCK_DROPPER); + tolua_constant(tolua_S,"E_BLOCK_STAINED_CLAY",E_BLOCK_STAINED_CLAY); + tolua_constant(tolua_S,"E_BLOCK_HAY_BALE",E_BLOCK_HAY_BALE); tolua_constant(tolua_S,"E_BLOCK_CARPET",E_BLOCK_CARPET); + tolua_constant(tolua_S,"E_BLOCK_HARDENED_CLAY",E_BLOCK_HARDENED_CLAY); + tolua_constant(tolua_S,"E_BLOCK_BLOCK_OF_COAL",E_BLOCK_BLOCK_OF_COAL); tolua_constant(tolua_S,"E_BLOCK_NUMBER_OF_TYPES",E_BLOCK_NUMBER_OF_TYPES); tolua_constant(tolua_S,"E_BLOCK_MAX_TYPE_ID",E_BLOCK_MAX_TYPE_ID); tolua_constant(tolua_S,"E_ITEM_EMPTY",E_ITEM_EMPTY); @@ -27416,6 +27463,38 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S) tolua_constant(tolua_S,"E_META_WOOL_GREEN",E_META_WOOL_GREEN); tolua_constant(tolua_S,"E_META_WOOL_RED",E_META_WOOL_RED); tolua_constant(tolua_S,"E_META_WOOL_BLACK",E_META_WOOL_BLACK); + tolua_constant(tolua_S,"E_META_CARPET_WHITE",E_META_CARPET_WHITE); + tolua_constant(tolua_S,"E_META_CARPET_ORANGE",E_META_CARPET_ORANGE); + tolua_constant(tolua_S,"E_META_CARPET_MAGENTA",E_META_CARPET_MAGENTA); + tolua_constant(tolua_S,"E_META_CARPET_LIGHTBLUE",E_META_CARPET_LIGHTBLUE); + tolua_constant(tolua_S,"E_META_CARPET_YELLOW",E_META_CARPET_YELLOW); + tolua_constant(tolua_S,"E_META_CARPET_LIGHTGREEN",E_META_CARPET_LIGHTGREEN); + tolua_constant(tolua_S,"E_META_CARPET_PINK",E_META_CARPET_PINK); + tolua_constant(tolua_S,"E_META_CARPET_GRAY",E_META_CARPET_GRAY); + tolua_constant(tolua_S,"E_META_CARPET_LIGHTGRAY",E_META_CARPET_LIGHTGRAY); + tolua_constant(tolua_S,"E_META_CARPET_CYAN",E_META_CARPET_CYAN); + tolua_constant(tolua_S,"E_META_CARPET_PURPLE",E_META_CARPET_PURPLE); + tolua_constant(tolua_S,"E_META_CARPET_BLUE",E_META_CARPET_BLUE); + tolua_constant(tolua_S,"E_META_CARPET_BROWN",E_META_CARPET_BROWN); + tolua_constant(tolua_S,"E_META_CARPET_GREEN",E_META_CARPET_GREEN); + tolua_constant(tolua_S,"E_META_CARPET_RED",E_META_CARPET_RED); + tolua_constant(tolua_S,"E_META_CARPET_BLACK",E_META_CARPET_BLACK); + tolua_constant(tolua_S,"E_META_STAINED_CLAY_WHITE",E_META_STAINED_CLAY_WHITE); + tolua_constant(tolua_S,"E_META_STAINED_CLAY_ORANGE",E_META_STAINED_CLAY_ORANGE); + tolua_constant(tolua_S,"E_META_STAINED_CLAY_MAGENTA",E_META_STAINED_CLAY_MAGENTA); + tolua_constant(tolua_S,"E_META_STAINED_CLAY_LIGHTBLUE",E_META_STAINED_CLAY_LIGHTBLUE); + tolua_constant(tolua_S,"E_META_STAINED_CLAY_YELLOW",E_META_STAINED_CLAY_YELLOW); + tolua_constant(tolua_S,"E_META_STAINED_CLAY_LIGHTGREEN",E_META_STAINED_CLAY_LIGHTGREEN); + tolua_constant(tolua_S,"E_META_STAINED_CLAY_PINK",E_META_STAINED_CLAY_PINK); + tolua_constant(tolua_S,"E_META_STAINED_CLAY_GRAY",E_META_STAINED_CLAY_GRAY); + tolua_constant(tolua_S,"E_META_STAINED_CLAY_LIGHTGRAY",E_META_STAINED_CLAY_LIGHTGRAY); + tolua_constant(tolua_S,"E_META_STAINED_CLAY_CYAN",E_META_STAINED_CLAY_CYAN); + tolua_constant(tolua_S,"E_META_STAINED_CLAY_PURPLE",E_META_STAINED_CLAY_PURPLE); + tolua_constant(tolua_S,"E_META_STAINED_CLAY_BLUE",E_META_STAINED_CLAY_BLUE); + tolua_constant(tolua_S,"E_META_STAINED_CLAY_BROWN",E_META_STAINED_CLAY_BROWN); + tolua_constant(tolua_S,"E_META_STAINED_CLAY_GREEN",E_META_STAINED_CLAY_GREEN); + tolua_constant(tolua_S,"E_META_STAINED_CLAY_RED",E_META_STAINED_CLAY_RED); + tolua_constant(tolua_S,"E_META_STAINED_CLAY_BLACK",E_META_STAINED_CLAY_BLACK); tolua_constant(tolua_S,"E_META_COAL_NORMAL",E_META_COAL_NORMAL); tolua_constant(tolua_S,"E_META_COAL_CHARCOAL",E_META_COAL_CHARCOAL); tolua_constant(tolua_S,"E_META_DYE_BLACK",E_META_DYE_BLACK); @@ -27955,6 +28034,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S) tolua_function(tolua_S,"GenerateChunk",tolua_AllToLua_cWorld_GenerateChunk00); tolua_function(tolua_S,"SetBlock",tolua_AllToLua_cWorld_SetBlock00); tolua_function(tolua_S,"FastSetBlock",tolua_AllToLua_cWorld_FastSetBlock00); + tolua_function(tolua_S,"QueueSetBlock",tolua_AllToLua_cWorld_QueueSetBlock00); tolua_function(tolua_S,"GetBlock",tolua_AllToLua_cWorld_GetBlock00); tolua_function(tolua_S,"GetBlockMeta",tolua_AllToLua_cWorld_GetBlockMeta00); tolua_function(tolua_S,"SetBlockMeta",tolua_AllToLua_cWorld_SetBlockMeta00); diff --git a/source/Bindings.h b/source/Bindings.h index a403294a9..5fcd02faa 100644 --- a/source/Bindings.h +++ b/source/Bindings.h @@ -1,6 +1,6 @@ /* ** Lua binding: AllToLua -** Generated automatically by tolua++-1.0.92 on 08/18/13 13:15:34. +** Generated automatically by tolua++-1.0.92 on 08/18/13 22:18:02. */ /* Exported function */ diff --git a/source/Chunk.cpp b/source/Chunk.cpp index 62d411b0c..a2cfb7ead 100644 --- a/source/Chunk.cpp +++ b/source/Chunk.cpp @@ -440,6 +440,9 @@ void cChunk::Tick(float a_Dt) (*itr)->SendUnloadChunk(m_PosX, m_PosZ); } m_UnloadQuery.clear(); + + // Set all blocks that have been queued for setting later: + ProcessQueuedSetBlocks(); CheckBlocks(); @@ -544,6 +547,30 @@ void cChunk::MoveEntityToNewChunk(cEntity * a_Entity) +void cChunk::ProcessQueuedSetBlocks(void) +{ + Int64 CurrTick = m_World->GetWorldAge(); + for (sSetBlockQueueVector::iterator itr = m_SetBlockQueue.begin(); itr != m_SetBlockQueue.end();) + { + if (itr->m_Tick < CurrTick) + { + // Not yet + ++itr; + continue; + } + else + { + // Now is the time to set the block + SetBlock(itr->m_RelX, itr->m_RelY, itr->m_RelZ, itr->m_BlockType, itr->m_BlockMeta); + itr = m_SetBlockQueue.erase(itr); + } + } // for itr - m_SetBlockQueue[] +} + + + + + void cChunk::BroadcastPendingBlockChanges(void) { sSetBlockVector Changes; @@ -1492,6 +1519,15 @@ void cChunk::SetBlock( int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType +void cChunk::QueueSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Int64 a_Tick) +{ + m_SetBlockQueue.push_back(sSetBlockQueueItem(a_RelX, a_RelY, a_RelZ, a_BlockType, a_BlockMeta, a_Tick)); +} + + + + + void cChunk::QueueTickBlock(int a_RelX, int a_RelY, int a_RelZ) { ASSERT ( diff --git a/source/Chunk.h b/source/Chunk.h index c4eeab6ae..cba39f7ee 100644 --- a/source/Chunk.h +++ b/source/Chunk.h @@ -136,6 +136,9 @@ public: // SetBlock() does a lot of work (heightmap, tickblocks, blockentities) so a BlockIdx version doesn't make sense void SetBlock( const Vector3i & a_RelBlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta ) { SetBlock( a_RelBlockPos.x, a_RelBlockPos.y, a_RelBlockPos.z, a_BlockType, a_BlockMeta ); } + /// Queues a block change till the specified world tick + void QueueSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Int64 a_Tick); + /// Queues block for ticking (m_ToTickQueue) void QueueTickBlock(int a_RelX, int a_RelY, int a_RelZ); @@ -319,6 +322,22 @@ private: friend class cChunkMap; + struct sSetBlockQueueItem + { + int m_RelX, m_RelY, m_RelZ; + BLOCKTYPE m_BlockType; + NIBBLETYPE m_BlockMeta; + Int64 m_Tick; + + sSetBlockQueueItem(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Int64 a_Tick) : + m_RelX(a_RelX), m_RelY(a_RelY), m_RelZ(a_RelZ) + { + } + } ; + + typedef std::vector sSetBlockQueueVector; + + bool m_IsValid; // True if the chunk is loaded / generated bool m_IsLightValid; // True if the blocklight and skylight are calculated bool m_IsDirty; // True if the chunk has changed since it was last saved @@ -329,6 +348,8 @@ private: std::vector m_ToTickBlocks; sSetBlockVector m_PendingSendBlocks; ///< Blocks that have changed and need to be sent to all clients + sSetBlockQueueVector m_SetBlockQueue; ///< Block changes that are queued to a specific tick + // A critical section is not needed, because all chunk access is protected by its parent ChunkMap's csLayers cClientHandleList m_LoadedByClient; cClientHandleList m_UnloadQuery; @@ -405,6 +426,9 @@ private: /// Called by Tick() when an entity moves out of this chunk into a neighbor; moves the entity and sends spawn / despawn packet to clients void MoveEntityToNewChunk(cEntity * a_Entity); + + /// Processes all blocks that have been scheduled for replacement by the QueueSetBlock() function + void ProcessQueuedSetBlocks(void); }; typedef cChunk * cChunkPtr; diff --git a/source/ChunkMap.cpp b/source/ChunkMap.cpp index 5a16495e6..cd4955077 100644 --- a/source/ChunkMap.cpp +++ b/source/ChunkMap.cpp @@ -1171,6 +1171,23 @@ void cChunkMap::SetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_B +void cChunkMap::QueueSetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, BLOCKTYPE a_BlockMeta, Int64 a_Tick) +{ + int ChunkX, ChunkZ, X = a_BlockX, Y = a_BlockY, Z = a_BlockZ; + cChunkDef::AbsoluteToRelative(X, Y, Z, ChunkX, ChunkZ); + + cCSLock Lock(m_CSLayers); + cChunkPtr Chunk = GetChunk(ChunkX, ZERO_CHUNK_Y, ChunkZ); + if ((Chunk != NULL) && Chunk->IsValid()) + { + Chunk->QueueSetBlock(X, Y, Z, a_BlockType, a_BlockMeta, a_Tick); + } +} + + + + + bool cChunkMap::GetBlockTypeMeta(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) { int ChunkX, ChunkZ, X = a_BlockX, Y = a_BlockY, Z = a_BlockZ; diff --git a/source/ChunkMap.h b/source/ChunkMap.h index 208d2824e..b0af0d779 100644 --- a/source/ChunkMap.h +++ b/source/ChunkMap.h @@ -135,6 +135,7 @@ public: NIBBLETYPE GetBlockBlockLight(int a_BlockX, int a_BlockY, int a_BlockZ); void SetBlockMeta (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockMeta); void SetBlock (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, BLOCKTYPE a_BlockMeta); + void QueueSetBlock (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, BLOCKTYPE a_BlockMeta, Int64 a_Tick); bool GetBlockTypeMeta (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta); bool GetBlockInfo (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_Meta, NIBBLETYPE & a_SkyLight, NIBBLETYPE & a_BlockLight); diff --git a/source/World.cpp b/source/World.cpp index e63e45498..70dbb5284 100644 --- a/source/World.cpp +++ b/source/World.cpp @@ -1385,6 +1385,15 @@ void cWorld::FastSetBlock(int a_X, int a_Y, int a_Z, BLOCKTYPE a_BlockType, NIBB +void cWorld::QueueSetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_TickDelay) +{ + m_ChunkMap->QueueSetBlock(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, GetWorldAge() + a_TickDelay); +} + + + + + BLOCKTYPE cWorld::GetBlock(int a_X, int a_Y, int a_Z) { // First check if it isn't queued in the m_FastSetBlockQueue: diff --git a/source/World.h b/source/World.h index 5d3de06d0..8c90b08c4 100644 --- a/source/World.h +++ b/source/World.h @@ -311,8 +311,23 @@ public: bool ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinChunkZ, int a_MaxChunkZ, cChunkDataCallback & a_Callback); // tolua_begin - void SetBlock (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); - void FastSetBlock (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); + + /** Sets the block at the specified coords to the specified value. + Full processing, incl. updating neighbors, is performed. + */ + void SetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); + + /** Sets the block at the specified coords to the specified value. + The replacement doesn't trigger block updates. + The replaced blocks aren't checked for block entities (block entity is leaked if it exists at this block) + */ + void FastSetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); + + /** Queues a SetBlock() with the specified parameters after the specified number of ticks. + Calls SetBlock(), so performs full processing of the replaced block. + */ + void QueueSetBlock(int a_BlockX, int a_BLockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_TickDelay); + BLOCKTYPE GetBlock (int a_BlockX, int a_BlockY, int a_BlockZ); NIBBLETYPE GetBlockMeta (int a_BlockX, int a_BlockY, int a_BlockZ); void SetBlockMeta (int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_MetaData);