bool cItemHandler::OnPlayerPlace( cWorld & a_World, cPlayer & a_Player, const cItem & a_EquippedItem, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ ) { if (a_BlockFace < 0) { // Clicked in air return false; } if ((a_BlockY < 0) || (a_BlockY >= cChunkDef::Height)) { // The clicked block is outside the world, ignore this call altogether (#128) return false; } BLOCKTYPE ClickedBlock; NIBBLETYPE ClickedBlockMeta; a_World.GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, ClickedBlock, ClickedBlockMeta); // Check if the block ignores build collision (water, grass etc.): if ( BlockHandler(ClickedBlock)->DoesIgnoreBuildCollision() || BlockHandler(ClickedBlock)->DoesIgnoreBuildCollision(&a_Player, ClickedBlockMeta) ) { cChunkInterface ChunkInterface(a_World.GetChunkMap()); BlockHandler(ClickedBlock)->OnDestroyedByPlayer(ChunkInterface, a_World, &a_Player, a_BlockX, a_BlockY, a_BlockZ); } else { AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace); if ((a_BlockY < 0) || (a_BlockY >= cChunkDef::Height)) { // The block is being placed outside the world, ignore this packet altogether (#128) return false; } NIBBLETYPE PlaceMeta; BLOCKTYPE PlaceBlock; a_World.GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, PlaceBlock, PlaceMeta); // Clicked on side of block, make sure that placement won't be cancelled if there is a slab able to be double slabbed. // No need to do combinability (dblslab) checks, client will do that here. if ( !BlockHandler(PlaceBlock)->DoesIgnoreBuildCollision() && !BlockHandler(PlaceBlock)->DoesIgnoreBuildCollision(&a_Player, PlaceMeta) ) { // Tried to place a block *into* another? // Happens when you place a block aiming at side of block with a torch on it or stem beside it return false; } } BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; if (!GetPlacementBlockTypeMeta(&a_World, &a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta)) { // Handler refused the placement, send that information back to the client: a_World.SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, &a_Player); a_Player.GetInventory().SendEquippedSlot(); return false; } if (!a_Player.PlaceBlock(a_BlockX, a_BlockY, a_BlockZ, BlockType, BlockMeta)) { // The placement failed, the block has already been re-sent, re-send inventory: a_Player.GetInventory().SendEquippedSlot(); return false; } AString PlaceSound = cBlockInfo::GetPlaceSound(BlockType); float Volume = 1.0f, Pitch = 0.8f; if (PlaceSound == "dig.metal") { Pitch = 1.2f; PlaceSound = "dig.stone"; } else if (PlaceSound == "random.anvil_land") { Volume = 0.65f; } a_World.BroadcastSoundEffect(PlaceSound, a_BlockX + 0.5, a_BlockY + 0.5, a_BlockZ + 0.5, Volume, Pitch); // Remove the "placed" item: if (a_Player.IsGameModeSurvival()) { a_Player.GetInventory().RemoveOneEquippedItem(); } return true; }
bool GetLargeTreeAdjustment(cWorld & a_World, int & a_X, int & a_Y, int & a_Z, NIBBLETYPE a_Meta) { bool IsLarge = true; a_Meta = a_Meta & 0x07; // Check to see if we are the northwest corner for (int x = 0; x < 2; ++x) { for (int z = 0; z < 2; ++z) { NIBBLETYPE meta; BLOCKTYPE type; a_World.GetBlockTypeMeta(a_X + x, a_Y, a_Z + z, type, meta); IsLarge = IsLarge && (type == E_BLOCK_SAPLING) && ((a_Meta & meta) == a_Meta); } } if (IsLarge) { return true; } IsLarge = true; // Check to see if we are the southwest corner for (int x = 0; x < 2; ++x) { for (int z = 0; z > -2; --z) { NIBBLETYPE meta; BLOCKTYPE type; a_World.GetBlockTypeMeta(a_X + x, a_Y, a_Z + z, type, meta); IsLarge = IsLarge && (type == E_BLOCK_SAPLING) && ((a_Meta & meta) == a_Meta); } } if (IsLarge) { --a_Z; return true; } IsLarge = true; // Check to see if we are the southeast corner for (int x = 0; x > -2; --x) { for (int z = 0; z > -2; --z) { NIBBLETYPE meta; BLOCKTYPE type; a_World.GetBlockTypeMeta(a_X + x, a_Y, a_Z + z, type, meta); IsLarge = IsLarge && (type == E_BLOCK_SAPLING) && ((a_Meta & meta) == a_Meta); } } if (IsLarge) { --a_Z; --a_X; return true; } IsLarge = true; // Check to see if we are the northeast corner for (int x = 0; x > -2; --x) { for (int z = 0; z < 2; ++z) { NIBBLETYPE meta; BLOCKTYPE type; a_World.GetBlockTypeMeta(a_X + x, a_Y, a_Z + z, type, meta); IsLarge = IsLarge && (type == E_BLOCK_SAPLING) && ((a_Meta & meta) == a_Meta); } } if (IsLarge) { --a_X; } return IsLarge; }