diff options
Diffstat (limited to '')
31 files changed, 521 insertions, 157 deletions
diff --git a/src/Blocks/BlockAnvil.h b/src/Blocks/BlockAnvil.h index abfa0f782..154394550 100644 --- a/src/Blocks/BlockAnvil.h +++ b/src/Blocks/BlockAnvil.h @@ -46,10 +46,10 @@ public: switch (Direction) { - case 0: a_BlockMeta = 0x2 | Meta << 2; break; - case 1: a_BlockMeta = 0x3 | Meta << 2; break; - case 2: a_BlockMeta = 0x0 | Meta << 2; break; - case 3: a_BlockMeta = 0x1 | Meta << 2; break; + case 0: a_BlockMeta = static_cast<NIBBLETYPE>(0x2 | Meta << 2); break; + case 1: a_BlockMeta = static_cast<NIBBLETYPE>(0x3 | Meta << 2); break; + case 2: a_BlockMeta = static_cast<NIBBLETYPE>(0x0 | Meta << 2); break; + case 3: a_BlockMeta = static_cast<NIBBLETYPE>(0x1 | Meta << 2); break; default: { return false; diff --git a/src/Blocks/BlockBed.h b/src/Blocks/BlockBed.h index 46f361686..905c0ea76 100644 --- a/src/Blocks/BlockBed.h +++ b/src/Blocks/BlockBed.h @@ -36,11 +36,6 @@ public: a_Pickups.push_back(cItem(E_ITEM_BED, 1, 0)); } - virtual bool CanDirtGrowGrass(NIBBLETYPE a_Meta) override - { - return true; - } - // Bed specific helper functions static NIBBLETYPE RotationToMetaData(double a_Rotation) @@ -53,7 +48,7 @@ public: a_Rotation = (a_Rotation / 360) * 4; - return ((char)a_Rotation + 2) % 4; + return (static_cast<NIBBLETYPE>(a_Rotation + 2)) % 4; } static Vector3i MetaDataToDirection(NIBBLETYPE a_MetaData) diff --git a/src/Blocks/BlockButton.h b/src/Blocks/BlockButton.h index d24c7d952..3558729bb 100644 --- a/src/Blocks/BlockButton.h +++ b/src/Blocks/BlockButton.h @@ -19,15 +19,35 @@ public: virtual void OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override { + NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ); + + double x(a_BlockX); + double y(a_BlockY); + double z(a_BlockZ); + + // If button is already on do nothing + if (Meta & 0x08) + { + return; + } + // Set p the ON bit to on - NIBBLETYPE Meta = (a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) | 0x08); + Meta |= 0x08; a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta); a_WorldInterface.WakeUpSimulators(a_BlockX, a_BlockY, a_BlockZ); - a_WorldInterface.GetBroadcastManager().BroadcastSoundEffect("random.click", (double)a_BlockX, (double)a_BlockY, (double)a_BlockZ, 0.5f, (Meta & 0x08) ? 0.6f : 0.5f); + a_WorldInterface.GetBroadcastManager().BroadcastSoundEffect("random.click", x, y, z, 0.5f, 0.6f); // Queue a button reset (unpress) - a_ChunkInterface.QueueSetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, (a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) & 0x07), m_BlockType == E_BLOCK_STONE_BUTTON ? 20 : 30, m_BlockType, a_WorldInterface); + int delay = (m_BlockType == E_BLOCK_STONE_BUTTON) ? 20 : 30; + + a_ChunkInterface.QueueSetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, (a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) & 0x07), delay, m_BlockType, a_WorldInterface); + + a_Player->GetWorld()->ScheduleTask(delay, [x, y, z](cWorld & a_World) + { + a_World.BroadcastSoundEffect("random.click", x, y, z, 0.5f, 0.5f); + }); + } @@ -67,14 +87,19 @@ public: case BLOCK_FACE_XM: return 0x2; case BLOCK_FACE_XP: return 0x1; case BLOCK_FACE_YM: return 0x0; - default: + case BLOCK_FACE_NONE: { ASSERT(!"Unhandled block face!"); return 0x0; } } + #if !defined(__clang__) + ASSERT(!"Unknown BLOCK_FACE"); + return 0; + #endif } + inline static eBlockFace BlockMetaDataToBlockFace(NIBBLETYPE a_Meta) { switch (a_Meta & 0x7) @@ -93,6 +118,7 @@ public: } } + virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override { NIBBLETYPE Meta; diff --git a/src/Blocks/BlockCocoaPod.h b/src/Blocks/BlockCocoaPod.h index 1b659d48f..4d16d2552 100644 --- a/src/Blocks/BlockCocoaPod.h +++ b/src/Blocks/BlockCocoaPod.h @@ -81,12 +81,18 @@ public: case BLOCK_FACE_XM: return 3; case BLOCK_FACE_XP: return 1; case BLOCK_FACE_ZP: return 2; - default: + case BLOCK_FACE_NONE: + case BLOCK_FACE_YM: + case BLOCK_FACE_YP: { ASSERT(!"Unknown face"); return 0; } } + #if !defined(__clang__) + ASSERT(!"Unknown BLOCK_FACE"); + return 0; + #endif } } ; diff --git a/src/Blocks/BlockComparator.h b/src/Blocks/BlockComparator.h index ed73a162e..3babeddad 100644 --- a/src/Blocks/BlockComparator.h +++ b/src/Blocks/BlockComparator.h @@ -64,6 +64,85 @@ public: a_BlockMeta = cBlockRedstoneRepeaterHandler::RepeaterRotationToMetaData(a_Player->GetYaw()); return true; } + + + inline static Vector3i GetSideCoordinate(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta, bool a_bInverse) + { + if (!a_bInverse) + { + switch (a_Meta) + { + case 0x0: a_BlockX++; break; + case 0x1: a_BlockZ--; break; + case 0x2: a_BlockX--; break; + case 0x3: a_BlockZ++; break; + default: + { + LOGWARNING("%s: Unknown metadata: %d", __FUNCTION__, a_Meta); + ASSERT(!"Unknown metadata while determining orientation of comparator!"); + break; + } + } + } + else + { + switch (a_Meta) + { + case 0x0: a_BlockX--; break; + case 0x1: a_BlockZ++; break; + case 0x2: a_BlockX++; break; + case 0x3: a_BlockZ--; break; + default: + { + LOGWARNING("%s: Unknown metadata: %d", __FUNCTION__, a_Meta); + ASSERT(!"Unknown metadata while determining orientation of comparator!"); + break; + } + } + } + + return Vector3i(a_BlockX, a_BlockY, a_BlockZ); + } + + + inline static Vector3i GetRearCoordinate(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta) + { + switch (a_Meta) + { + case 0x0: a_BlockZ++; break; + case 0x1: a_BlockX--; break; + case 0x2: a_BlockZ--; break; + case 0x3: a_BlockX++; break; + default: + { + LOGWARNING("%s: Unknown metadata: %d", __FUNCTION__, a_Meta); + ASSERT(!"Unknown metadata while determining orientation of comparator!"); + break; + } + } + + return Vector3i(a_BlockX, a_BlockY, a_BlockZ); + } + + + inline static Vector3i GetFrontCoordinate(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta) + { + switch (a_Meta) + { + case 0x0: a_BlockZ--; break; + case 0x1: a_BlockX++; break; + case 0x2: a_BlockZ++; break; + case 0x3: a_BlockX--; break; + default: + { + LOGWARNING("%s: Unknown metadata: %d", __FUNCTION__, a_Meta); + ASSERT(!"Unknown metadata while determining orientation of comparator!"); + break; + } + } + + return Vector3i(a_BlockX, a_BlockY, a_BlockZ); + } } ; diff --git a/src/Blocks/BlockDirt.h b/src/Blocks/BlockDirt.h index 32512a2ef..3d671d218 100644 --- a/src/Blocks/BlockDirt.h +++ b/src/Blocks/BlockDirt.h @@ -3,6 +3,7 @@ #include "BlockHandler.h" #include "../FastRandom.h" +#include "../BlockInfo.h" #include "Root.h" #include "Bindings/PluginManager.h" @@ -39,19 +40,6 @@ public: { return; } - - // Grass becomes dirt if there is something on top of it: - if (a_RelY < cChunkDef::Height - 1) - { - BLOCKTYPE Above; - NIBBLETYPE AboveMeta; - a_Chunk.GetBlockTypeMeta(a_RelX, a_RelY + 1, a_RelZ, Above, AboveMeta); - if (!cBlockInfo::GetHandler(Above)->CanDirtGrowGrass(AboveMeta)) - { - a_Chunk.FastSetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_DIRT, E_META_DIRT_NORMAL); - return; - } - } // Make sure that there is enough light at the source block to spread if (!a_Chunk.GetWorld()->IsChunkLighted(a_Chunk.GetPosX(), a_Chunk.GetPosZ())) @@ -59,10 +47,24 @@ public: a_Chunk.GetWorld()->QueueLightChunk(a_Chunk.GetPosX(), a_Chunk.GetPosZ()); return; } - else if ((a_RelY < cChunkDef::Height - 1) && std::max(a_Chunk.GetBlockLight(a_RelX, a_RelY + 1, a_RelZ), a_Chunk.GetTimeAlteredLight(a_Chunk.GetSkyLight(a_RelX, a_RelY + 1, a_RelZ))) < 9) + else if ((a_RelY < cChunkDef::Height - 1)) { + BLOCKTYPE above = a_Chunk.GetBlock(a_RelX, a_RelY + 1, a_RelZ); + + // Grass turns back to dirt when the block above is not transparent + if (!cBlockInfo::IsTransparent(above)) + { + a_Chunk.FastSetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_DIRT, E_META_DIRT_NORMAL); + return; + } + + NIBBLETYPE light = std::max(a_Chunk.GetBlockLight(a_RelX, a_RelY + 1, a_RelZ), a_Chunk.GetTimeAlteredLight(a_Chunk.GetSkyLight(a_RelX, a_RelY + 1, a_RelZ))); // Source block is not bright enough to spread - return; + if (light < 9) + { + return; + } + } // Grass spreads to adjacent dirt blocks: @@ -95,11 +97,10 @@ public: // Not a regular dirt block continue; } - - BLOCKTYPE AboveDest; - NIBBLETYPE AboveMeta; - Chunk->GetBlockTypeMeta(BlockX, BlockY + 1, BlockZ, AboveDest, AboveMeta); - if (cBlockInfo::GetHandler(AboveDest)->CanDirtGrowGrass(AboveMeta)) + BLOCKTYPE above = a_Chunk.GetBlock(BlockX, BlockY + 1, BlockZ); + NIBBLETYPE light = std::max(a_Chunk.GetBlockLight(BlockX, BlockY + 1, BlockZ), a_Chunk.GetTimeAlteredLight(a_Chunk.GetSkyLight(BlockX, BlockY + 1, BlockZ))); + // Grass does not spread to blocks with a light level less than 5 + if ((light > 4) && cBlockInfo::IsTransparent(above)) { if (!cRoot::Get()->GetPluginManager()->CallHookBlockSpread(*Chunk->GetWorld(), Chunk->GetPosX() * cChunkDef::Width + BlockX, BlockY, Chunk->GetPosZ() * cChunkDef::Width + BlockZ, ssGrassSpread)) { diff --git a/src/Blocks/BlockDoor.cpp b/src/Blocks/BlockDoor.cpp index d13c8d657..a4e375cf0 100644 --- a/src/Blocks/BlockDoor.cpp +++ b/src/Blocks/BlockDoor.cpp @@ -50,10 +50,24 @@ void cBlockDoorHandler::OnUse(cChunkInterface & a_ChunkInterface, cWorldInterfac UNUSED(a_CursorY); UNUSED(a_CursorZ); - if (a_ChunkInterface.GetBlock(a_BlockX, a_BlockY, a_BlockZ) == E_BLOCK_WOODEN_DOOR) + switch (a_ChunkInterface.GetBlock(a_BlockX, a_BlockY, a_BlockZ)) { - ChangeDoor(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ); - a_Player->GetWorld()->BroadcastSoundParticleEffect(1003, a_BlockX, a_BlockY, a_BlockZ, 0, a_Player->GetClientHandle()); + default: + { + ASSERT(!"Unhandled door block type"); + } + case E_BLOCK_ACACIA_DOOR: + case E_BLOCK_BIRCH_DOOR: + case E_BLOCK_DARK_OAK_DOOR: + case E_BLOCK_JUNGLE_DOOR: + case E_BLOCK_SPRUCE_DOOR: + case E_BLOCK_IRON_DOOR: + case E_BLOCK_WOODEN_DOOR: + { + ChangeDoor(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ); + a_Player->GetWorld()->BroadcastSoundParticleEffect(1003, a_BlockX, a_BlockY, a_BlockZ, 0, a_Player->GetClientHandle()); + break; + } } } diff --git a/src/Blocks/BlockDoor.h b/src/Blocks/BlockDoor.h index 445383e7c..79ed4f723 100644 --- a/src/Blocks/BlockDoor.h +++ b/src/Blocks/BlockDoor.h @@ -55,6 +55,10 @@ public: virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override { + if ((a_BlockMeta & 0x08) != 0) // is top part of door + { + return; + } switch (m_BlockType) { case E_BLOCK_WOODEN_DOOR: @@ -242,13 +246,13 @@ public: if ((Meta & 0x08) != 0) { // The coords are pointing at the top part of the door - if (a_BlockX > 0) + if (a_BlockY > 0) { NIBBLETYPE DownMeta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY - 1, a_BlockZ); - return (NIBBLETYPE) ((DownMeta & 0x07) | 0x08 | (Meta << 4)); + return static_cast<NIBBLETYPE>((DownMeta & 0x07) | 0x08 | (Meta << 4)); } // This is the top part of the door at the bottommost layer of the world, there's no bottom: - return (NIBBLETYPE) (0x08 | (Meta << 4)); + return static_cast<NIBBLETYPE>(0x08 | (Meta << 4)); } else { @@ -256,7 +260,7 @@ public: if (a_BlockY < cChunkDef::Height - 1) { NIBBLETYPE UpMeta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY + 1, a_BlockZ); - return (NIBBLETYPE) (Meta | (UpMeta << 4)); + return static_cast<NIBBLETYPE>(Meta | (UpMeta << 4)); } // This is the bottom part of the door at the topmost layer of the world, there's no top: return Meta; diff --git a/src/Blocks/BlockFarmland.h b/src/Blocks/BlockFarmland.h index 23a7392da..8d43632ff 100644 --- a/src/Blocks/BlockFarmland.h +++ b/src/Blocks/BlockFarmland.h @@ -65,13 +65,22 @@ public: } } - virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ) override + + virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_WhichNeighbor) override { + // Don't care about any neighbor but the one above us (fix recursion loop in #2213): + if (a_WhichNeighbor != BLOCK_FACE_YP) + { + return; + } + + // Don't care about anything if we're at the top of the world: if (a_BlockY >= cChunkDef::Height) { return; } + // Check whether we should revert to dirt: BLOCKTYPE UpperBlock = a_ChunkInterface.GetBlock(a_BlockX, a_BlockY + 1, a_BlockZ); if (cBlockInfo::FullyOccupiesVoxel(UpperBlock)) { @@ -79,11 +88,13 @@ public: } } + virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override { a_Pickups.Add(E_BLOCK_DIRT, 1, 0); // Reset meta } + bool IsWaterInNear(cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ) { if (a_Chunk.GetWorld()->IsWeatherWetAt(a_RelX, a_RelZ)) diff --git a/src/Blocks/BlockFire.h b/src/Blocks/BlockFire.h index 2038df94b..3f75455da 100644 --- a/src/Blocks/BlockFire.h +++ b/src/Blocks/BlockFire.h @@ -121,6 +121,20 @@ public: } } + int PortalHeight = MaxY - Y - 1; + int PortalWidth = XZP - XZM + 1; + if ((PortalHeight < a_WorldInterface.GetMinNetherPortalHeight()) || (PortalHeight > a_WorldInterface.GetMaxNetherPortalHeight())) + { + // The portal isn't high enough, or is too high + return; + } + + if ((PortalWidth < a_WorldInterface.GetMinNetherPortalWidth()) || (PortalWidth > a_WorldInterface.GetMaxNetherPortalWidth())) + { + // The portal isn't wide enough, or is too wide + return; + } + for (int Height = Y + 1; Height <= MaxY - 1; Height++) // Loop through boundary to set portal blocks { for (int Width = XZM; Width <= XZP; Width++) @@ -217,6 +231,11 @@ public: return (FoundFrameZP && FoundFrameZM); } + + virtual bool DoesIgnoreBuildCollision(cPlayer * a_Player, NIBBLETYPE a_Meta) override + { + return true; + } }; diff --git a/src/Blocks/BlockFluid.h b/src/Blocks/BlockFluid.h index 2823baedc..58b3ce042 100644 --- a/src/Blocks/BlockFluid.h +++ b/src/Blocks/BlockFluid.h @@ -49,12 +49,6 @@ public: } super::Check(a_ChunkInterface, a_PluginInterface, a_RelX, a_RelY, a_RelZ, a_Chunk); } - - - virtual bool CanDirtGrowGrass(NIBBLETYPE a_Meta) override - { - return false; - } } ; diff --git a/src/Blocks/BlockHandler.cpp b/src/Blocks/BlockHandler.cpp index 452cc94a5..412fc3aeb 100644 --- a/src/Blocks/BlockHandler.cpp +++ b/src/Blocks/BlockHandler.cpp @@ -389,12 +389,12 @@ void cBlockHandler::OnDestroyedByPlayer(cChunkInterface & a_ChunkInterface, cWor void cBlockHandler::OnPlaced(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { // Notify the neighbors - NeighborChanged(a_ChunkInterface, a_BlockX - 1, a_BlockY, a_BlockZ); - NeighborChanged(a_ChunkInterface, a_BlockX + 1, a_BlockY, a_BlockZ); - NeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY - 1, a_BlockZ); - NeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY + 1, a_BlockZ); - NeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ - 1); - NeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ + 1); + NeighborChanged(a_ChunkInterface, a_BlockX - 1, a_BlockY, a_BlockZ, BLOCK_FACE_XP); + NeighborChanged(a_ChunkInterface, a_BlockX + 1, a_BlockY, a_BlockZ, BLOCK_FACE_XM); + NeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY - 1, a_BlockZ, BLOCK_FACE_YP); + NeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY + 1, a_BlockZ, BLOCK_FACE_YM); + NeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ - 1, BLOCK_FACE_ZP); + NeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ + 1, BLOCK_FACE_ZM); } @@ -404,29 +404,30 @@ void cBlockHandler::OnPlaced(cChunkInterface & a_ChunkInterface, cWorldInterface void cBlockHandler::OnDestroyed(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ) { // Notify the neighbors - NeighborChanged(a_ChunkInterface, a_BlockX - 1, a_BlockY, a_BlockZ); - NeighborChanged(a_ChunkInterface, a_BlockX + 1, a_BlockY, a_BlockZ); - NeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY - 1, a_BlockZ); - NeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY + 1, a_BlockZ); - NeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ - 1); - NeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ + 1); + NeighborChanged(a_ChunkInterface, a_BlockX - 1, a_BlockY, a_BlockZ, BLOCK_FACE_XP); + NeighborChanged(a_ChunkInterface, a_BlockX + 1, a_BlockY, a_BlockZ, BLOCK_FACE_XM); + NeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY - 1, a_BlockZ, BLOCK_FACE_YP); + NeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY + 1, a_BlockZ, BLOCK_FACE_YM); + NeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ - 1, BLOCK_FACE_ZP); + NeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ + 1, BLOCK_FACE_ZM); } -void cBlockHandler::NeighborChanged(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ) +void cBlockHandler::NeighborChanged(cChunkInterface & a_ChunkInterface, int a_NeighborX, int a_NeighborY, int a_NeighborZ, eBlockFace a_WhichNeighbor) { - if ((a_BlockY >= 0) && (a_BlockY < cChunkDef::Height)) + if ((a_NeighborY >= 0) && (a_NeighborY < cChunkDef::Height)) { - cBlockInfo::GetHandler(a_ChunkInterface.GetBlock(a_BlockX, a_BlockY, a_BlockZ))->OnNeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ); + cBlockInfo::GetHandler(a_ChunkInterface.GetBlock(a_NeighborX, a_NeighborY, a_NeighborZ))->OnNeighborChanged(a_ChunkInterface, a_NeighborX, a_NeighborY, a_NeighborZ, a_WhichNeighbor); } } + void cBlockHandler::ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) { // Setting the meta to a_BlockMeta keeps most textures. The few other blocks have to override this. @@ -512,15 +513,6 @@ bool cBlockHandler::CanBeAt(cChunkInterface & a_ChunkInterface, int a_BlockX, in -bool cBlockHandler::CanDirtGrowGrass(NIBBLETYPE a_Meta) -{ - return ((cBlockInfo::IsTransparent(m_BlockType)) || (cBlockInfo::IsOneHitDig(m_BlockType))); -} - - - - - bool cBlockHandler::IsUseable() { return false; diff --git a/src/Blocks/BlockHandler.h b/src/Blocks/BlockHandler.h index 4dec0dc95..1b357c3f1 100644 --- a/src/Blocks/BlockHandler.h +++ b/src/Blocks/BlockHandler.h @@ -56,13 +56,19 @@ public: /// Called before a block gets destroyed / replaced with air virtual void OnDestroyed(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ); - /// Called when a direct neighbor of this block has been changed (The position is the own position, not the neighbor position) - virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ) {} - - /// Notifies all neighbors of the given block about a change - static void NeighborChanged(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ); - - /// Called while the player diggs the block. + /** Called when a direct neighbor of this block has been changed (The position is the block's own position, not the changing neighbor's position) + a_WhichNeighbor indicates which neighbor has changed. For example, BLOCK_FACE_YP meant the neighbor above has changed. + BLOCK_FACE_NONE means that it is a neighbor not directly adjacent (diagonal, etc.) */ + virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_WhichNeighbor) {} + + /** Notifies the specified neighbor that the current block has changed. + a_NeighborXYZ coords are the coords of the neighbor + a_WhichNeighbor specifies which neighbor (relative to a_NeighborXYZ) has changed. + For example BLOCK_FACE_YP means that the block at {a_NeighborX, a_NeighborY + 1, a_NeighborZ} has changed. + BLOCK_FACE_NONE means that it is a neighbor not directly adjacent (diagonal, etc.) */ + static void NeighborChanged(cChunkInterface & a_ChunkInterface, int a_NeighborX, int a_NeighborY, int a_NeighborZ, eBlockFace a_WhichNeighbor); + + /** Called when the player starts digging the block. */ virtual void OnDigging(cChunkInterface & cChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) {} /// Called if the user right clicks the block and the block is useable @@ -83,9 +89,6 @@ public: /// Checks if the block can stay at the specified relative coords in the chunk virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk); - - /** Can the dirt under this block grow to grass? */ - virtual bool CanDirtGrowGrass(NIBBLETYPE a_Meta); /** Checks if the block can be placed at this point. Default: CanBeAt(...) diff --git a/src/Blocks/BlockHopper.h b/src/Blocks/BlockHopper.h index 4a5d32dd5..06e2b0e9f 100644 --- a/src/Blocks/BlockHopper.h +++ b/src/Blocks/BlockHopper.h @@ -35,7 +35,7 @@ public: case BLOCK_FACE_NORTH: a_BlockMeta = E_META_HOPPER_FACING_ZP; break; case BLOCK_FACE_SOUTH: a_BlockMeta = E_META_HOPPER_FACING_ZM; break; case BLOCK_FACE_WEST: a_BlockMeta = E_META_HOPPER_FACING_XP; break; - default: a_BlockMeta = E_META_HOPPER_UNATTACHED; break; + case BLOCK_FACE_NONE: a_BlockMeta = E_META_HOPPER_UNATTACHED; break; } return true; } diff --git a/src/Blocks/BlockLadder.h b/src/Blocks/BlockLadder.h index ab3f55439..d727f8f8e 100644 --- a/src/Blocks/BlockLadder.h +++ b/src/Blocks/BlockLadder.h @@ -57,8 +57,17 @@ public: case BLOCK_FACE_ZP: return 0x3; case BLOCK_FACE_XM: return 0x4; case BLOCK_FACE_XP: return 0x5; - default: return 0x2; + case BLOCK_FACE_NONE: + case BLOCK_FACE_YM: + case BLOCK_FACE_YP: + { + return 0x2; + } } + #if !defined(__clang__) + ASSERT(!"Unknown BLOCK_FACE"); + return 0; + #endif } diff --git a/src/Blocks/BlockLeaves.h b/src/Blocks/BlockLeaves.h index bd9a7414e..2368eab7b 100644 --- a/src/Blocks/BlockLeaves.h +++ b/src/Blocks/BlockLeaves.h @@ -40,33 +40,49 @@ public: { cFastRandom rand; - // Old leaves - 3 bits contain display; new leaves - 1st bit, shifted left two for saplings to understand - if (rand.NextInt(6) == 0) + // There is a chance to drop a sapling that varies depending on the type of leaf broken. + // TODO: Take into account fortune for sapling drops. + int chance; + if ((m_BlockType == E_BLOCK_LEAVES) && ((a_BlockMeta & 0x03) == E_META_LEAVES_JUNGLE)) + { + // Jungle leaves have a 2.5% chance of dropping a sapling. + chance = rand.NextInt(40); + } + else + { + // Other leaves have a 5% chance of dropping a sapling. + chance = rand.NextInt(20); + } + if (chance == 0) { a_Pickups.push_back( cItem( E_BLOCK_SAPLING, 1, - (m_BlockType == E_BLOCK_LEAVES) ? (a_BlockMeta & 0x03) : (2 << (a_BlockMeta & 0x01)) + (m_BlockType == E_BLOCK_LEAVES) ? (a_BlockMeta & 0x03) : static_cast<short>(4 + (a_BlockMeta & 0x01)) ) ); } - - // 1 % chance of dropping an apple, if the leaves' type is Apple Leaves + + // 0.5 % chance of dropping an apple, if the leaves' type is Apple Leaves if ((m_BlockType == E_BLOCK_LEAVES) && ((a_BlockMeta & 0x03) == E_META_LEAVES_APPLE)) { - if (rand.NextInt(101) == 0) + if (rand.NextInt(200) == 0) { a_Pickups.push_back(cItem(E_ITEM_RED_APPLE, 1, 0)); } } } - - - virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ) override + + + virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_WhichNeighbor) override { + // Unset 0x8 bit so this block gets checked for decay: NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ); - a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta & 0x7); // Unset 0x8 bit so it gets checked for decay + if ((Meta & 0x08) != 0) + { + a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta & 0x7); + } } diff --git a/src/Blocks/BlockLever.h b/src/Blocks/BlockLever.h index 2da138e5f..8d676b56f 100644 --- a/src/Blocks/BlockLever.h +++ b/src/Blocks/BlockLever.h @@ -59,14 +59,18 @@ public: // Determine lever direction: switch (a_Dir) { - case BLOCK_FACE_YP: return 0x6; - case BLOCK_FACE_XP: return 0x1; - case BLOCK_FACE_XM: return 0x2; - case BLOCK_FACE_ZP: return 0x3; - case BLOCK_FACE_ZM: return 0x4; - case BLOCK_FACE_YM: return 0x0; - default: return 0x6; + case BLOCK_FACE_YP: return 0x6; + case BLOCK_FACE_XP: return 0x1; + case BLOCK_FACE_XM: return 0x2; + case BLOCK_FACE_ZP: return 0x3; + case BLOCK_FACE_ZM: return 0x4; + case BLOCK_FACE_YM: return 0x0; + case BLOCK_FACE_NONE: return 0x6; } + #if !defined(__clang__) + ASSERT(!"Unknown BLOCK_FACE"); + return 0; + #endif } diff --git a/src/Blocks/BlockPiston.cpp b/src/Blocks/BlockPiston.cpp index d9f4913d8..75f8621a7 100644 --- a/src/Blocks/BlockPiston.cpp +++ b/src/Blocks/BlockPiston.cpp @@ -179,7 +179,7 @@ void cBlockPistonHandler::ExtendPiston(int a_BlockX, int a_BlockY, int a_BlockZ, a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, pistonBlock, pistonMeta | 0x8); a_World->SetBlock(extx, exty, extz, E_BLOCK_PISTON_EXTENSION, pistonMeta | (IsSticky(pistonBlock) ? 8 : 0), false); - a_World->ScheduleTask(PISTON_TICK_DELAY, std::make_shared<cWorld::cTaskSendBlockToAllPlayers>(ScheduledBlocks)); + a_World->ScheduleTask(PISTON_TICK_DELAY, static_cast<cWorld::cTaskPtr>(std::make_shared<cWorld::cTaskSendBlockToAllPlayers>(ScheduledBlocks))); } @@ -229,7 +229,7 @@ void cBlockPistonHandler::RetractPiston(int a_BlockX, int a_BlockY, int a_BlockZ std::vector<Vector3i> ScheduledBlocks; ScheduledBlocks.push_back(Vector3i(a_BlockX, a_BlockY, a_BlockZ)); ScheduledBlocks.push_back(Vector3i(tempx, tempy, tempz)); - a_World->ScheduleTask(PISTON_TICK_DELAY + 1, std::make_shared<cWorld::cTaskSendBlockToAllPlayers>(ScheduledBlocks)); + a_World->ScheduleTask(PISTON_TICK_DELAY + 1, static_cast<cWorld::cTaskPtr>(std::make_shared<cWorld::cTaskSendBlockToAllPlayers>(ScheduledBlocks))); return; } } @@ -239,7 +239,7 @@ void cBlockPistonHandler::RetractPiston(int a_BlockX, int a_BlockY, int a_BlockZ std::vector<Vector3i> ScheduledBlocks; ScheduledBlocks.push_back(Vector3i(a_BlockX, a_BlockY, a_BlockZ)); - a_World->ScheduleTask(PISTON_TICK_DELAY + 1, std::make_shared<cWorld::cTaskSendBlockToAllPlayers>(ScheduledBlocks)); + a_World->ScheduleTask(PISTON_TICK_DELAY + 1, static_cast<cWorld::cTaskPtr>(std::make_shared<cWorld::cTaskSendBlockToAllPlayers>(ScheduledBlocks))); } diff --git a/src/Blocks/BlockQuartz.h b/src/Blocks/BlockQuartz.h index edc4fb9c5..b936a7e4a 100644 --- a/src/Blocks/BlockQuartz.h +++ b/src/Blocks/BlockQuartz.h @@ -36,6 +36,7 @@ public: return true; } + inline static NIBBLETYPE BlockFaceToMetaData(eBlockFace a_BlockFace, NIBBLETYPE a_QuartzMeta) { switch (a_BlockFace) @@ -58,11 +59,15 @@ public: return 0x3; // East or west } - default: + case BLOCK_FACE_NONE: { ASSERT(!"Unhandled block face!"); return a_QuartzMeta; // No idea, give a special meta (all sides the same) } } + #if !defined(__clang__) + ASSERT(!"Unknown BLOCK_FACE"); + return 0; + #endif } } ; diff --git a/src/Blocks/BlockRail.h b/src/Blocks/BlockRail.h index a2e27a351..7fb910e8c 100644 --- a/src/Blocks/BlockRail.h +++ b/src/Blocks/BlockRail.h @@ -47,15 +47,14 @@ public: super::OnPlaced(a_ChunkInterface, a_WorldInterface, a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta); // Alert diagonal rails - OnNeighborChanged(a_ChunkInterface, a_BlockX + 1, a_BlockY + 1, a_BlockZ); - OnNeighborChanged(a_ChunkInterface, a_BlockX - 1, a_BlockY + 1, a_BlockZ); - OnNeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY + 1, a_BlockZ + 1); - OnNeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY + 1, a_BlockZ - 1); - - OnNeighborChanged(a_ChunkInterface, a_BlockX + 1, a_BlockY - 1, a_BlockZ); - OnNeighborChanged(a_ChunkInterface, a_BlockX - 1, a_BlockY - 1, a_BlockZ); - OnNeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY - 1, a_BlockZ + 1); - OnNeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY - 1, a_BlockZ - 1); + OnNeighborChanged(a_ChunkInterface, a_BlockX + 1, a_BlockY + 1, a_BlockZ, BLOCK_FACE_NONE); + OnNeighborChanged(a_ChunkInterface, a_BlockX - 1, a_BlockY + 1, a_BlockZ, BLOCK_FACE_NONE); + OnNeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY + 1, a_BlockZ + 1, BLOCK_FACE_NONE); + OnNeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY + 1, a_BlockZ - 1, BLOCK_FACE_NONE); + OnNeighborChanged(a_ChunkInterface, a_BlockX + 1, a_BlockY - 1, a_BlockZ, BLOCK_FACE_NONE); + OnNeighborChanged(a_ChunkInterface, a_BlockX - 1, a_BlockY - 1, a_BlockZ, BLOCK_FACE_NONE); + OnNeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY - 1, a_BlockZ + 1, BLOCK_FACE_NONE); + OnNeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY - 1, a_BlockZ - 1, BLOCK_FACE_NONE); } @@ -64,19 +63,18 @@ public: super::OnDestroyed(a_ChunkInterface, a_WorldInterface, a_BlockX, a_BlockY, a_BlockZ); // Alert diagonal rails - OnNeighborChanged(a_ChunkInterface, a_BlockX + 1, a_BlockY + 1, a_BlockZ); - OnNeighborChanged(a_ChunkInterface, a_BlockX - 1, a_BlockY + 1, a_BlockZ); - OnNeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY + 1, a_BlockZ + 1); - OnNeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY + 1, a_BlockZ - 1); - - OnNeighborChanged(a_ChunkInterface, a_BlockX + 1, a_BlockY - 1, a_BlockZ); - OnNeighborChanged(a_ChunkInterface, a_BlockX - 1, a_BlockY - 1, a_BlockZ); - OnNeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY - 1, a_BlockZ + 1); - OnNeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY - 1, a_BlockZ - 1); + OnNeighborChanged(a_ChunkInterface, a_BlockX + 1, a_BlockY + 1, a_BlockZ, BLOCK_FACE_NONE); + OnNeighborChanged(a_ChunkInterface, a_BlockX - 1, a_BlockY + 1, a_BlockZ, BLOCK_FACE_NONE); + OnNeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY + 1, a_BlockZ + 1, BLOCK_FACE_NONE); + OnNeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY + 1, a_BlockZ - 1, BLOCK_FACE_NONE); + OnNeighborChanged(a_ChunkInterface, a_BlockX + 1, a_BlockY - 1, a_BlockZ, BLOCK_FACE_NONE); + OnNeighborChanged(a_ChunkInterface, a_BlockX - 1, a_BlockY - 1, a_BlockZ, BLOCK_FACE_NONE); + OnNeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY - 1, a_BlockZ + 1, BLOCK_FACE_NONE); + OnNeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY - 1, a_BlockZ - 1, BLOCK_FACE_NONE); } - virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ) override + virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_WhichNeighbor) override { NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ); if (IsUnstable(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ) && (Meta != FindMeta(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ))) @@ -487,7 +485,12 @@ public: } break; } - default: break; + case BLOCK_FACE_NONE: + case BLOCK_FACE_YM: + case BLOCK_FACE_YP: + { + break; + } } return true; } diff --git a/src/Blocks/BlockSapling.h b/src/Blocks/BlockSapling.h index bec79c6f3..c15e0a195 100644 --- a/src/Blocks/BlockSapling.h +++ b/src/Blocks/BlockSapling.h @@ -3,6 +3,7 @@ #include "BlockHandler.h" #include "../World.h" +#include "../FastRandom.h" @@ -34,17 +35,144 @@ public: virtual void OnUpdate(cChunkInterface & cChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_PluginInterface, cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ) override { NIBBLETYPE Meta = a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ); - - if ((Meta & 0x08) != 0) + NIBBLETYPE Light = std::max(a_Chunk.GetBlockLight(a_RelX, a_RelY, a_RelZ), a_Chunk.GetTimeAlteredLight(a_Chunk.GetSkyLight(a_RelX, a_RelY, a_RelZ))); + + // Only grow if we have the right amount of light + if (Light > 8) + { + cFastRandom random; + // Only grow if we are in the right growth stage and have the right amount of space around them. + if (((Meta & 0x08) != 0) && (random.NextInt(99) < 45) && CanGrowAt(a_Chunk, a_RelX, a_RelY, a_RelZ, Meta)) + { + int BlockX = a_RelX + a_Chunk.GetPosX() * cChunkDef::Width; + int BlockZ = a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width; + a_Chunk.GetWorld()->GrowTree(BlockX, a_RelY, BlockZ); + } + // Only move to the next growth stage if we haven't gone there yet + else if (((Meta & 0x08) == 0) && (random.NextInt(99) < 45)) + { + a_Chunk.SetMeta(a_RelX, a_RelY, a_RelZ, Meta | 0x08); + } + } + } + + bool CanGrowAt(cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_Meta) + { + a_Meta = a_Meta & 0x07; + int CheckHeight = 0; + bool LargeTree = false; + + // Get the height to check against + switch (a_Meta) { - int BlockX = a_RelX + a_Chunk.GetPosX() * cChunkDef::Width; - int BlockZ = a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width; - a_Chunk.GetWorld()->GrowTree(BlockX, a_RelY, BlockZ); + case E_META_SAPLING_APPLE: + { + CheckHeight = 5; + break; + } + case E_META_SAPLING_CONIFER: + { + CheckHeight = 7; + if (IsLargeTree(a_Chunk, a_RelX, a_RelY, a_RelZ, a_Meta)) + { + CheckHeight = 16; + LargeTree = true; + } + break; + } + case E_META_SAPLING_BIRCH: + { + CheckHeight = 6; + break; + } + case E_META_SAPLING_JUNGLE: + { + CheckHeight = 7; + if (IsLargeTree(a_Chunk, a_RelX, a_RelY, a_RelZ, a_Meta)) + { + CheckHeight = 13; + LargeTree = true; + } + break; + } + // Dark Oaks only grow in a 2x2 area + case E_META_SAPLING_DARK_OAK: + { + if (!IsLargeTree(a_Chunk, a_RelX, a_RelY, a_RelZ, a_Meta)) + { + return false; + } + CheckHeight = 7; + LargeTree = true; + break; + } } - else + // We should always get a valid CheckHeight + ASSERT(CheckHeight != 0); + + // Don't grow a tree if we don't have enough space left above it in the chunk + if ((a_RelY + CheckHeight) > cChunkDef::Height) + { + return false; + } + bool CanGrow = true; + + // Validate the neighbor blocks. They cannot be solid. + BLOCKTYPE check = E_BLOCK_AIR; + a_Chunk.UnboundedRelGetBlockType(a_RelX - 1, a_RelY, a_RelZ, check); + CanGrow = CanGrow && cBlockInfo::IsTransparent(check); + + a_Chunk.UnboundedRelGetBlockType(a_RelX + 1, a_RelY, a_RelZ, check); + CanGrow = CanGrow && cBlockInfo::IsTransparent(check); + + a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ - 1, check); + CanGrow = CanGrow && cBlockInfo::IsTransparent(check); + + a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ + 1, check); + CanGrow = CanGrow && cBlockInfo::IsTransparent(check); + + + + while (CheckHeight && CanGrow) { - a_Chunk.SetMeta(a_RelX, a_RelY, a_RelZ, Meta | 0x08); + check = a_Chunk.GetBlock(a_RelX, a_RelY + CheckHeight, a_RelZ); + CanGrow = CanGrow && ((check == E_BLOCK_AIR) || (check == E_BLOCK_LEAVES)); + + // We have to check above the neighboring saplings as well + if (LargeTree) + { + a_Chunk.UnboundedRelGetBlockType(a_RelX + 1, a_RelY + CheckHeight, a_RelZ, check); + CanGrow = CanGrow && ((check == E_BLOCK_AIR) || (check == E_BLOCK_LEAVES)); + + a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY + CheckHeight, a_RelZ + 1, check); + CanGrow = CanGrow && ((check == E_BLOCK_AIR) || (check == E_BLOCK_LEAVES)); + + a_Chunk.UnboundedRelGetBlockType(a_RelX + 1, a_RelY + CheckHeight, a_RelZ + 1, check); + CanGrow = CanGrow && ((check == E_BLOCK_AIR) || (check == E_BLOCK_LEAVES)); + } + + --CheckHeight; } + + return CanGrow; + } + +private: + bool IsLargeTree(cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_Meta) + { + BLOCKTYPE type; + NIBBLETYPE meta; + bool LargeTree = true; + a_Chunk.UnboundedRelGetBlock(a_RelX + 1, a_RelY, a_RelZ, type, meta); + LargeTree = LargeTree && (type == E_BLOCK_SAPLING) && ((a_Meta & meta) == a_Meta); + + a_Chunk.UnboundedRelGetBlock(a_RelX + 1, a_RelY, a_RelZ + 1, type, meta); + LargeTree = LargeTree && (type == E_BLOCK_SAPLING) && ((a_Meta & meta) == a_Meta); + + a_Chunk.UnboundedRelGetBlock(a_RelX, a_RelY, a_RelZ + 1, type, meta); + LargeTree = LargeTree && (type == E_BLOCK_SAPLING) && ((a_Meta & meta) == a_Meta); + + return LargeTree; } } ; diff --git a/src/Blocks/BlockSideways.h b/src/Blocks/BlockSideways.h index 4b1e38d6d..e52fbaa2f 100644 --- a/src/Blocks/BlockSideways.h +++ b/src/Blocks/BlockSideways.h @@ -58,12 +58,16 @@ public: return a_Meta | 0x4; // East or west } - default: + case BLOCK_FACE_NONE: { ASSERT(!"Unhandled block face!"); return a_Meta | 0xC; // No idea, give a special meta } } + #if !defined(__clang__) + ASSERT(!"Unknown BLOCK_FACE"); + return 0; + #endif } } ; diff --git a/src/Blocks/BlockSlab.h b/src/Blocks/BlockSlab.h index d762154df..58e85013e 100644 --- a/src/Blocks/BlockSlab.h +++ b/src/Blocks/BlockSlab.h @@ -41,7 +41,7 @@ public: ) override { a_BlockType = m_BlockType; - NIBBLETYPE Meta = (NIBBLETYPE) a_Player->GetEquippedItem().m_ItemDamage; + NIBBLETYPE Meta = static_cast<NIBBLETYPE>(a_Player->GetEquippedItem().m_ItemDamage); // Set the correct metadata based on player equipped item (i.e. a_BlockMeta not initialised yet) switch (a_BlockFace) @@ -88,12 +88,6 @@ public: return true; } - - virtual bool CanDirtGrowGrass(NIBBLETYPE a_Meta) override - { - return ((a_Meta & 0x8) != 0); - } - /// Returns true if the specified blocktype is one of the slabs handled by this handler static bool IsAnySlabType(BLOCKTYPE a_BlockType) @@ -104,7 +98,7 @@ public: virtual void OnCancelRightClick(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace) override { - if ((a_BlockFace == BLOCK_FACE_NONE) || (a_Player->GetEquippedItem().m_ItemType != (short)m_BlockType)) + if ((a_BlockFace == BLOCK_FACE_NONE) || (a_Player->GetEquippedItem().m_ItemType != static_cast<short>(m_BlockType))) { return; } diff --git a/src/Blocks/BlockStairs.h b/src/Blocks/BlockStairs.h index d396204e0..7ef69d2ec 100644 --- a/src/Blocks/BlockStairs.h +++ b/src/Blocks/BlockStairs.h @@ -62,12 +62,6 @@ public: } - virtual bool CanDirtGrowGrass(NIBBLETYPE a_Meta) override - { - return true; - } - - static NIBBLETYPE RotationToMetaData(double a_Rotation) { a_Rotation += 90 + 45; // So its not aligned with axis diff --git a/src/Blocks/BlockTorch.h b/src/Blocks/BlockTorch.h index d63df94cf..0a834d13d 100644 --- a/src/Blocks/BlockTorch.h +++ b/src/Blocks/BlockTorch.h @@ -59,7 +59,7 @@ public: case BLOCK_FACE_WEST: return E_META_TORCH_WEST; case BLOCK_FACE_NORTH: return E_META_TORCH_NORTH; case BLOCK_FACE_SOUTH: return E_META_TORCH_SOUTH; - default: + case BLOCK_FACE_NONE: { ASSERT(!"Unhandled torch direction!"); break; @@ -103,6 +103,11 @@ public: case E_BLOCK_STAINED_GLASS: case E_BLOCK_FENCE: case E_BLOCK_NETHER_BRICK_FENCE: + case E_BLOCK_SPRUCE_FENCE: + case E_BLOCK_BIRCH_FENCE: + case E_BLOCK_JUNGLE_FENCE: + case E_BLOCK_DARK_OAK_FENCE: + case E_BLOCK_ACACIA_FENCE: case E_BLOCK_COBBLESTONE_WALL: { // Torches can only be placed on top of these blocks @@ -114,6 +119,22 @@ public: // Toches can be placed on the top of these slabs only if the occupy the top half of the voxel return ((a_BlockFace == BLOCK_FACE_YP) && ((a_BlockMeta & 0x08) == 0x08)); } + case E_BLOCK_WOODEN_STAIRS: + case E_BLOCK_COBBLESTONE_STAIRS: + case E_BLOCK_BRICK_STAIRS: + case E_BLOCK_STONE_BRICK_STAIRS: + case E_BLOCK_NETHER_BRICK_STAIRS: + case E_BLOCK_SANDSTONE_STAIRS: + case E_BLOCK_SPRUCE_WOOD_STAIRS: + case E_BLOCK_BIRCH_WOOD_STAIRS: + case E_BLOCK_JUNGLE_WOOD_STAIRS: + case E_BLOCK_QUARTZ_STAIRS: + case E_BLOCK_ACACIA_WOOD_STAIRS: + case E_BLOCK_DARK_OAK_WOOD_STAIRS: + case E_BLOCK_RED_SANDSTONE_STAIRS: + { + return (a_BlockFace == BLOCK_FACE_TOP) && (a_BlockMeta & E_BLOCK_STAIRS_UPSIDE_DOWN); + } default: { if (cBlockInfo::FullyOccupiesVoxel(a_BlockType)) diff --git a/src/Blocks/BlockTrapdoor.h b/src/Blocks/BlockTrapdoor.h index dbb0b5a5b..a1d2dff6f 100644 --- a/src/Blocks/BlockTrapdoor.h +++ b/src/Blocks/BlockTrapdoor.h @@ -66,6 +66,7 @@ public: return true; } + inline static NIBBLETYPE BlockFaceToMetaData(eBlockFace a_BlockFace) { switch (a_BlockFace) @@ -74,14 +75,21 @@ public: case BLOCK_FACE_ZM: return 0x0; case BLOCK_FACE_XP: return 0x3; case BLOCK_FACE_XM: return 0x2; - default: + case BLOCK_FACE_NONE: + case BLOCK_FACE_YM: + case BLOCK_FACE_YP: { ASSERT(!"Unhandled block face!"); return 0; } } + #if !defined(__clang__) + ASSERT(!"Unknown BLOCK_FACE"); + return 0; + #endif } + inline static eBlockFace BlockMetaDataToBlockFace(NIBBLETYPE a_Meta) { switch (a_Meta & 0x3) @@ -98,6 +106,7 @@ public: } } + virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override { NIBBLETYPE Meta; diff --git a/src/Blocks/BlockTripwireHook.h b/src/Blocks/BlockTripwireHook.h index 88d389711..39892af5a 100644 --- a/src/Blocks/BlockTripwireHook.h +++ b/src/Blocks/BlockTripwireHook.h @@ -16,6 +16,7 @@ public: { } + virtual bool GetPlacementBlockTypeMeta( cChunkInterface & a_ChunkInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, @@ -29,6 +30,7 @@ public: return true; } + inline static NIBBLETYPE DirectionToMetadata(eBlockFace a_Direction) { switch (a_Direction) @@ -37,10 +39,21 @@ public: case BLOCK_FACE_XP: return 0x3; case BLOCK_FACE_ZM: return 0x2; case BLOCK_FACE_ZP: return 0x0; - default: ASSERT(!"Unhandled tripwire hook direction!"); return 0x0; + case BLOCK_FACE_NONE: + case BLOCK_FACE_YM: + case BLOCK_FACE_YP: + { + ASSERT(!"Unhandled tripwire hook direction!"); + return 0x0; + } } + #if !defined(__clang__) + ASSERT(!"Unknown BLOCK_FACE"); + return 0; + #endif } + inline static eBlockFace MetadataToDirection(NIBBLETYPE a_Meta) { switch (a_Meta & 0x03) @@ -53,6 +66,7 @@ public: } } + virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override { // Reset meta to zero diff --git a/src/Blocks/BlockVine.h b/src/Blocks/BlockVine.h index 00d7a69b8..3d06a8223 100644 --- a/src/Blocks/BlockVine.h +++ b/src/Blocks/BlockVine.h @@ -177,7 +177,7 @@ public: } - virtual void OnUpdate(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_BlockPluginInterface, cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ) + virtual void OnUpdate(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_BlockPluginInterface, cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ) override { UNUSED(a_ChunkInterface); UNUSED(a_WorldInterface); diff --git a/src/Blocks/BlockWallSign.h b/src/Blocks/BlockWallSign.h index b6599d033..9b90b78bf 100644 --- a/src/Blocks/BlockWallSign.h +++ b/src/Blocks/BlockWallSign.h @@ -55,11 +55,13 @@ public: { switch (a_Direction) { - case 0x2: return 0x2; - case 0x3: return 0x3; - case 0x4: return 0x4; - case 0x5: return 0x5; - default: + case BLOCK_FACE_ZM: return 0x2; + case BLOCK_FACE_ZP: return 0x3; + case BLOCK_FACE_XM: return 0x4; + case BLOCK_FACE_XP: return 0x5; + case BLOCK_FACE_NONE: + case BLOCK_FACE_YP: + case BLOCK_FACE_YM: { break; } diff --git a/src/Blocks/CMakeLists.txt b/src/Blocks/CMakeLists.txt index ed3e321d4..d8affd9cf 100644 --- a/src/Blocks/CMakeLists.txt +++ b/src/Blocks/CMakeLists.txt @@ -95,6 +95,11 @@ SET (HDRS MetaRotator.h WorldInterface.h) +if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + set_source_files_properties(BlockHandler.cpp PROPERTIES COMPILE_FLAGS "-Wno-error=old-style-cast") + set_source_files_properties(BlockPiston.cpp PROPERTIES COMPILE_FLAGS "-Wno-error=old-style-cast") +endif() + if(NOT MSVC) add_library(Blocks ${SRCS} ${HDRS}) endif() diff --git a/src/Blocks/WorldInterface.h b/src/Blocks/WorldInterface.h index 44c118195..826df7034 100644 --- a/src/Blocks/WorldInterface.h +++ b/src/Blocks/WorldInterface.h @@ -55,6 +55,18 @@ public: /** Returns true if it is raining, stormy or snowing at the specified location. This takes into account biomes. */ virtual bool IsWeatherWetAt(int a_BlockX, int a_BlockZ) = 0; + /** Returns or sets the minumim or maximum netherportal width */ + virtual int GetMinNetherPortalWidth(void) const = 0; + virtual int GetMaxNetherPortalWidth(void) const = 0; + virtual void SetMinNetherPortalWidth(int a_NewMinWidth) = 0; + virtual void SetMaxNetherPortalWidth(int a_NewMaxWidth) = 0; + + /** Returns or sets the minumim or maximum netherportal height */ + virtual int GetMinNetherPortalHeight(void) const = 0; + virtual int GetMaxNetherPortalHeight(void) const = 0; + virtual void SetMinNetherPortalHeight(int a_NewMinHeight) = 0; + virtual void SetMaxNetherPortalHeight(int a_NewMaxHeight) = 0; + /** Returns the world height at the specified coords; waits for the chunk to get loaded / generated */ virtual int GetHeight(int a_BlockX, int a_BlockZ) = 0; |