| 1509 | |
| 1510 | |
| 1511 | void cChunk::FastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, BLOCKTYPE a_BlockMeta) |
| 1512 | { |
| 1513 | ASSERT(!((a_RelX < 0) || (a_RelX >= Width) || (a_RelY < 0) || (a_RelY >= Height) || (a_RelZ < 0) || (a_RelZ >= Width))); |
| 1514 | |
| 1515 | ASSERT(IsValid()); |
| 1516 | |
| 1517 | const int index = MakeIndexNoCheck(a_RelX, a_RelY, a_RelZ); |
| 1518 | const BLOCKTYPE OldBlockType = cChunkDef::GetBlock(m_BlockTypes, index); |
| 1519 | const BLOCKTYPE OldBlockMeta = GetNibble(m_BlockMeta, index); |
| 1520 | if ((OldBlockType == a_BlockType) && (OldBlockMeta == a_BlockMeta)) |
| 1521 | { |
| 1522 | return; |
| 1523 | } |
| 1524 | |
| 1525 | MarkDirty(); |
| 1526 | |
| 1527 | m_BlockTypes[index] = a_BlockType; |
| 1528 | |
| 1529 | // The client doesn't need to distinguish between stationary and nonstationary fluids: |
| 1530 | if ( |
| 1531 | (OldBlockMeta != a_BlockMeta) || // Different meta always gets sent to the client |
| 1532 | !( |
| 1533 | ((OldBlockType == E_BLOCK_STATIONARY_WATER) && (a_BlockType == E_BLOCK_WATER)) || // Replacing stationary water with water |
| 1534 | ((OldBlockType == E_BLOCK_WATER) && (a_BlockType == E_BLOCK_STATIONARY_WATER)) || // Replacing water with stationary water |
| 1535 | ((OldBlockType == E_BLOCK_STATIONARY_LAVA) && (a_BlockType == E_BLOCK_LAVA)) || // Replacing stationary water with water |
| 1536 | ((OldBlockType == E_BLOCK_LAVA) && (a_BlockType == E_BLOCK_STATIONARY_LAVA)) // Replacing water with stationary water |
| 1537 | ) |
| 1538 | ) |
| 1539 | { |
| 1540 | m_PendingSendBlocks.push_back(sSetBlock(m_PosX, m_PosZ, a_RelX, a_RelY, a_RelZ, a_BlockType, a_BlockMeta)); |
| 1541 | } |
| 1542 | |
| 1543 | SetNibble(m_BlockMeta, index, a_BlockMeta); |
| 1544 | |
| 1545 | // ONLY recalculate lighting if it's necessary! |
| 1546 | if ( |
| 1547 | (cBlockInfo::GetLightValue (OldBlockType) != cBlockInfo::GetLightValue (a_BlockType)) || |
| 1548 | (cBlockInfo::GetSpreadLightFalloff(OldBlockType) != cBlockInfo::GetSpreadLightFalloff(a_BlockType)) || |
| 1549 | (cBlockInfo::IsTransparent (OldBlockType) != cBlockInfo::IsTransparent (a_BlockType)) |
| 1550 | ) |
| 1551 | { |
| 1552 | m_IsLightValid = false; |
| 1553 | } |
| 1554 | |
| 1555 | // Update heightmap, if needed: |
| 1556 | if (a_RelY >= m_HeightMap[a_RelX + a_RelZ * Width]) |
| 1557 | { |
| 1558 | if (a_BlockType != E_BLOCK_AIR) |
| 1559 | { |
| 1560 | m_HeightMap[a_RelX + a_RelZ * Width] = (unsigned char)a_RelY; |
| 1561 | } |
| 1562 | else |
| 1563 | { |
| 1564 | for (int y = a_RelY - 1; y > 0; --y) |
| 1565 | { |
| 1566 | if (m_BlockTypes[MakeIndexNoCheck(a_RelX, y, a_RelZ)] != E_BLOCK_AIR) |
| 1567 | { |
| 1568 | m_HeightMap[a_RelX + a_RelZ * Width] = (unsigned char)y; |
no test coverage detected