From 8090c13cde2d61a0330f1e262de7526318a0965d Mon Sep 17 00:00:00 2001 From: "madmaxoft@gmail.com" Date: Fri, 15 Mar 2013 20:18:11 +0000 Subject: Huge performance boost in blockhandlers, they have direct access to chunk data when blockchecking. Also fixed vines' placement. git-svn-id: http://mc-server.googlecode.com/svn/trunk@1278 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- source/Blocks/BlockVine.h | 105 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 79 insertions(+), 26 deletions(-) (limited to 'source/Blocks/BlockVine.h') diff --git a/source/Blocks/BlockVine.h b/source/Blocks/BlockVine.h index 2f35c11d9..88338e86d 100644 --- a/source/Blocks/BlockVine.h +++ b/source/Blocks/BlockVine.h @@ -25,45 +25,98 @@ public: BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta ) override { + // TODO: Disallow placement where the vine doesn't attach to something properly + BLOCKTYPE BlockType = 0; + NIBBLETYPE BlockMeta; + a_World->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, BlockType, BlockMeta); + if (BlockType == m_BlockType) + { + a_BlockMeta = BlockMeta | cVine::DirectionToMetaData(a_BlockFace); + } + else + { + a_BlockMeta = cVine::DirectionToMetaData(a_BlockFace); + } a_BlockType = m_BlockType; - a_BlockMeta = cVine::DirectionToMetaData(a_BlockFace); return true; } - virtual bool CanBePlacedAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace) override + /// Returns true if the specified block type is good for vines to attach to + static bool IsBlockAttachable(BLOCKTYPE a_BlockType) { - if ( - (a_World->GetBlock( a_BlockX, a_BlockY + 1, a_BlockZ ) == E_BLOCK_VINES) && - (cVine::MetaDataToDirection(a_World->GetBlockMeta(a_BlockX, a_BlockY + 1, a_BlockZ)) == a_BlockFace) - ) + return (a_BlockType == E_BLOCK_LEAVES) || g_BlockIsSolid[a_BlockType]; + } + + + /// Returns the meta that has the maximum allowable sides of the vine, given the surroundings + NIBBLETYPE GetMaxMeta(cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ) + { + static const struct { - return true; - } - - BLOCKTYPE TopBlock = a_World->GetBlock( a_BlockX, a_BlockY + 1, a_BlockZ); - if (g_BlockIsSolid[TopBlock] || (TopBlock == E_BLOCK_LEAVES)) + int x, z; + int Bit; + } Coords[] = { - AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, true); - BLOCKTYPE BaseBlock = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ); - if (!g_BlockIsSolid[BaseBlock] && (BaseBlock != E_BLOCK_LEAVES)) + { 0, 1, 1}, // south, ZP + {-1, 0, 2}, // west, XM + { 0, -1, 4}, // north, ZM + { 1, 0, 8}, // east, XP + } ; + int res = 0; + for (int i = 0; i < ARRAYCOUNT(Coords); i++) + { + BLOCKTYPE BlockType; + NIBBLETYPE BlockMeta; + if ( + a_Chunk.UnboundedRelGetBlock(a_RelX + Coords[i].x, a_RelY, a_RelZ + Coords[i].z, BlockType, BlockMeta) && + IsBlockAttachable(BlockType) + ) { - AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, false); - a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_VINES, 0); + res |= Coords[i].Bit; } - return true; } - - AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, true); - BLOCKTYPE BaseBlock = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ); - return (g_BlockIsSolid[BaseBlock] || (BaseBlock == E_BLOCK_LEAVES)); + return res; } - - - virtual bool CanBeAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override + + + void Check(int a_RelX, int a_RelY, int a_RelZ, cChunk & a_Chunk) override { - char Dir = cVine::MetaDataToDirection(a_World->GetBlockMeta( a_BlockX, a_BlockY, a_BlockZ)); - return CanBePlacedAt(a_World, a_BlockX, a_BlockY, a_BlockZ, Dir); + NIBBLETYPE CurMeta = a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ); + NIBBLETYPE MaxMeta = GetMaxMeta(a_Chunk, a_RelX, a_RelY, a_RelZ); + + // Check if vine above us, add its meta to MaxMeta + if ((a_RelY < cChunkDef::Height - 1) && (a_Chunk.GetBlock(a_RelX, a_RelY + 1, a_RelZ) == m_BlockType)) + { + MaxMeta |= a_Chunk.GetMeta(a_RelX, a_RelY + 1, a_RelZ); + } + + NIBBLETYPE Common = CurMeta & MaxMeta; // Neighbors that we have and are legal + if (Common != CurMeta) + { + // There is a neighbor missing, need to update the meta or even destroy the block + bool HasTop = (a_RelY < cChunkDef::Height - 1) && IsBlockAttachable(a_Chunk.GetBlock(a_RelX, a_RelY + 1, a_RelZ)); + if ((Common == 0) && !HasTop) + { + // The vine just lost all its support, destroy the block: + if (DoesDropOnUnsuitable()) + { + int BlockX = a_RelX + a_Chunk.GetPosX() * cChunkDef::Width; + int BlockZ = a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width; + DropBlock(a_Chunk.GetWorld(), NULL, BlockX, a_RelY, BlockZ); + } + a_Chunk.SetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_AIR, 0); + return; + } + a_Chunk.SetBlock(a_RelX, a_RelY, a_RelZ, m_BlockType, Common); + } + else + { + // Wake up the simulators for this block: + int BlockX = a_RelX + a_Chunk.GetPosX() * cChunkDef::Width; + int BlockZ = a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width; + a_Chunk.GetWorld()->GetSimulatorManager()->WakeUp(BlockX, a_RelY, BlockZ, &a_Chunk); + } } -- cgit v1.2.3