diff options
Diffstat (limited to 'source/Blocks/BlockTorch.h')
-rw-r--r-- | source/Blocks/BlockTorch.h | 104 |
1 files changed, 72 insertions, 32 deletions
diff --git a/source/Blocks/BlockTorch.h b/source/Blocks/BlockTorch.h index 3a50cab77..a52b373cb 100644 --- a/source/Blocks/BlockTorch.h +++ b/source/Blocks/BlockTorch.h @@ -24,16 +24,31 @@ public: BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta ) override { - // Find proper placement. Use the player-supplied one as the default, but fix if not okay: - if (!TorchCanBePlacedAt(a_World, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace)) + // Find proper placement of torch + + if ((a_BlockFace == BLOCK_FACE_TOP) || (a_BlockFace == BLOCK_FACE_BOTTOM)) { - a_BlockFace = FindSuitableFace(a_World, a_BlockX, a_BlockY, a_BlockZ); - - if (a_BlockFace == BLOCK_FACE_BOTTOM) + a_BlockFace = FindSuitableFace(a_World, a_BlockX, a_BlockY, a_BlockZ); // Top or bottom faces clicked, find a suitable face + if (a_BlockFace == BLOCK_FACE_NONE) { + // Client wouldn't have sent anything anyway, but whatever return false; } } + else + { + // Not top or bottom faces, try to preserve whatever face was clicked + if (!TorchCanBePlacedAt(a_World, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace)) + { + // Torch couldn't be placed on whatever face was clicked, last ditch resort - find another face + a_BlockFace = FindSuitableFace(a_World, a_BlockX, a_BlockY, a_BlockZ); + if (a_BlockFace == BLOCK_FACE_NONE) + { + return false; + } + } + } + a_BlockType = m_BlockType; a_BlockMeta = DirectionToMetaData(a_BlockFace); return true; @@ -100,51 +115,54 @@ public: } - virtual bool DoesAllowBlockOnTop(void) override - { - return true; - } - - - static bool CanBePlacedOn(BLOCKTYPE a_BlockType, char a_Direction) + static bool CanBePlacedOn(BLOCKTYPE a_BlockType, char a_BlockFace) { - if ( g_BlockIsSolid[a_BlockType] ) { - return (a_Direction == 0x1); // allow only direction "standing on floor" + if ( !g_BlockIsTorchPlaceable[a_BlockType] ) + { + return (a_BlockFace == BLOCK_FACE_TOP); // Allow placement only when torch upright } - else { - return g_BlockIsSolid[a_BlockType]; + else + { + return true; } } static bool TorchCanBePlacedAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace) { - // TODO: If placing a torch from below, check all 4 XZ neighbors, place it on that neighbor instead - // How to propagate that change up? - // Simon: The easiest way is to calculate the position two times, shouldn�t cost much cpu power :) - - if (a_BlockFace == BLOCK_FACE_BOTTOM) - { - return false; - } - AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, true); - return CanBePlacedOn(a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ), a_BlockFace); } - /// Finds a suitable Face for the Torch. Returns BLOCK_FACE_BOTTOM on failure + /// Finds a suitable face to place the torch, returning BLOCK_FACE_NONE on failure static char FindSuitableFace(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) { - for (int i = 1; i <= 5; i++) + for (int i = 0; i <= 5; i++) { - if (TorchCanBePlacedAt(a_World, a_BlockX, a_BlockY, a_BlockZ, i)) + AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, i, true); + BLOCKTYPE BlockInQuestion = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ); + + if ( + ((BlockInQuestion == E_BLOCK_GLASS) || + (BlockInQuestion == E_BLOCK_FENCE) || + (BlockInQuestion == E_BLOCK_NETHER_BRICK_FENCE) || + (BlockInQuestion == E_BLOCK_COBBLESTONE_WALL)) && + (i == BLOCK_FACE_TOP) + ) + { + return i; + } + else if ((g_BlockIsTorchPlaceable[BlockInQuestion]) && (i != BLOCK_FACE_BOTTOM)) { return i; } + else + { + AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, i, false); + } } - return BLOCK_FACE_BOTTOM; + return BLOCK_FACE_NONE; } @@ -163,11 +181,33 @@ public: virtual bool CanBeAt(int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override { - // TODO: Use AdjustCoordsByMeta(), then cChunk::UnboundedRelGetBlock() and finally some comparison char Face = MetaDataToDirection(a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ)); int BlockX = a_RelX + a_Chunk.GetPosX() * cChunkDef::Width; int BlockZ = a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width; - return TorchCanBePlacedAt(a_Chunk.GetWorld(), BlockX, a_RelY, BlockZ, Face); + + AddFaceDirection(a_RelX, a_RelY, a_RelZ, Face, true); + BLOCKTYPE BlockInQuestion; + a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ, BlockInQuestion); + + if ( + (BlockInQuestion == E_BLOCK_GLASS) || + (BlockInQuestion == E_BLOCK_FENCE) || + (BlockInQuestion == E_BLOCK_NETHER_BRICK_FENCE) || + (BlockInQuestion == E_BLOCK_COBBLESTONE_WALL) + ) + { + // Torches can be placed on tops of glass and fences, despite them being 'untorcheable' + // No need to check for upright orientation, it was done when the torch was placed + return true; + } + else if ( !g_BlockIsTorchPlaceable[BlockInQuestion] ) + { + return false; + } + else + { + return true; + } } |