From 46e1228f73d37753c9b888d97f941084b6fb558b Mon Sep 17 00:00:00 2001 From: "madmaxoft@gmail.com" Date: Sun, 3 Mar 2013 08:40:37 +0000 Subject: [PATCH] SandSimulator: Fixed sand dropping on half-slabs; added more blocks that break falling sand into pickups, fixed instant-fall git-svn-id: http://mc-server.googlecode.com/svn/trunk@1242 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- source/FallingBlock.cpp | 18 ++++-- source/Simulator/SandSimulator.cpp | 88 ++++++++++++++++++------------ source/Simulator/SandSimulator.h | 2 +- 3 files changed, 66 insertions(+), 42 deletions(-) diff --git a/source/FallingBlock.cpp b/source/FallingBlock.cpp index 12362009d..8ad313bb9 100644 --- a/source/FallingBlock.cpp +++ b/source/FallingBlock.cpp @@ -64,12 +64,20 @@ void cFallingBlock::Tick(float a_Dt, MTRand & a_TickRandom) if (BlockY < cChunkDef::Height - 1) { - BLOCKTYPE BlockBelow = GetWorld()->GetBlock(BlockX, BlockY, BlockZ); - if ( - cSandSimulator::DoesBreakFallingThrough(BlockBelow) || // Fallen onto a block that breaks this into pickups (e. g. half-slab) - !cSandSimulator::CanContinueFallThrough(BlockBelow) // Fallen onto a solid block - ) + BLOCKTYPE BlockBelow; + NIBBLETYPE BelowMeta; + GetWorld()->GetBlockTypeMeta(BlockX, BlockY, BlockZ, BlockBelow, BelowMeta); + if (cSandSimulator::DoesBreakFallingThrough(BlockBelow, BelowMeta)) { + // Fallen onto a block that breaks this into pickups (e. g. half-slab) + // Must finish the fall with coords one below the block: + cSandSimulator::FinishFalling(m_World, BlockX, BlockY, BlockZ, m_BlockType, m_BlockMeta); + Destroy(); + return; + } + else if (!cSandSimulator::CanContinueFallThrough(BlockBelow)) + { + // Fallen onto a solid block cSandSimulator::FinishFalling(m_World, BlockX, BlockY + 1, BlockZ, m_BlockType, m_BlockMeta); Destroy(); return; diff --git a/source/Simulator/SandSimulator.cpp b/source/Simulator/SandSimulator.cpp index 84646a10a..baab76d67 100644 --- a/source/Simulator/SandSimulator.cpp +++ b/source/Simulator/SandSimulator.cpp @@ -101,7 +101,7 @@ void cSandSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * cSandSimulatorChunkData & ChunkData = a_Chunk->GetSandSimulatorData(); for (cSandSimulatorChunkData::iterator itr = ChunkData.begin(); itr != ChunkData.end(); ++itr) { - if ((itr->x == RelX) && (itr->y == a_BlockY) && (itr->z == a_BlockZ)) + if ((itr->x == RelX) && (itr->y == a_BlockY) && (itr->z == RelZ)) { return; } @@ -121,10 +121,10 @@ bool cSandSimulator::CanStartFallingThrough(BLOCKTYPE a_BlockType) { case E_BLOCK_AIR: case E_BLOCK_FIRE: - case E_BLOCK_WATER: - case E_BLOCK_STATIONARY_WATER: case E_BLOCK_LAVA: case E_BLOCK_STATIONARY_LAVA: + case E_BLOCK_STATIONARY_WATER: + case E_BLOCK_WATER: { return true; } @@ -141,33 +141,41 @@ bool cSandSimulator::CanContinueFallThrough(BLOCKTYPE a_BlockType) switch (a_BlockType) { case E_BLOCK_AIR: - case E_BLOCK_FIRE: - case E_BLOCK_WATER: - case E_BLOCK_STATIONARY_WATER: - case E_BLOCK_LAVA: - case E_BLOCK_STATIONARY_LAVA: - case E_BLOCK_POWERED_RAIL: - case E_BLOCK_DETECTOR_RAIL: - case E_BLOCK_COBWEB: - case E_BLOCK_TALL_GRASS: - case E_BLOCK_DEAD_BUSH: - case E_BLOCK_YELLOW_FLOWER: - case E_BLOCK_RED_ROSE: case E_BLOCK_BROWN_MUSHROOM: - case E_BLOCK_RED_MUSHROOM: - case E_BLOCK_TORCH: - case E_BLOCK_REDSTONE_WIRE: + case E_BLOCK_COBWEB: case E_BLOCK_CROPS: - case E_BLOCK_PUMPKIN_STEM: + case E_BLOCK_DEAD_BUSH: + case E_BLOCK_DETECTOR_RAIL: + case E_BLOCK_FIRE: + case E_BLOCK_FLOWER_POT: + case E_BLOCK_LAVA: + case E_BLOCK_LEVER: + case E_BLOCK_MINECART_TRACKS: case E_BLOCK_MELON_STEM: - case E_BLOCK_REDSTONE_TORCH_OFF: - case E_BLOCK_REDSTONE_TORCH_ON: - case E_BLOCK_STONE_BUTTON: - case E_BLOCK_STONE_PRESSURE_PLATE: - case E_BLOCK_WOODEN_BUTTON: - case E_BLOCK_WOODEN_PRESSURE_PLATE: + case E_BLOCK_POWERED_RAIL: + case E_BLOCK_PUMPKIN_STEM: case E_BLOCK_REDSTONE_REPEATER_OFF: case E_BLOCK_REDSTONE_REPEATER_ON: + case E_BLOCK_REDSTONE_TORCH_OFF: + case E_BLOCK_REDSTONE_TORCH_ON: + case E_BLOCK_REDSTONE_WIRE: + case E_BLOCK_RED_MUSHROOM: + case E_BLOCK_RED_ROSE: + case E_BLOCK_SIGN_POST: + case E_BLOCK_STATIONARY_LAVA: + case E_BLOCK_STATIONARY_WATER: + case E_BLOCK_STONE_BUTTON: + case E_BLOCK_STONE_PRESSURE_PLATE: + case E_BLOCK_TALL_GRASS: + case E_BLOCK_TORCH: + case E_BLOCK_TRAPDOOR: + case E_BLOCK_TRIPWIRE: + case E_BLOCK_TRIPWIRE_HOOK: + case E_BLOCK_WALLSIGN: + case E_BLOCK_WATER: + case E_BLOCK_WOODEN_BUTTON: + case E_BLOCK_WOODEN_PRESSURE_PLATE: + case E_BLOCK_YELLOW_FLOWER: { return true; } @@ -184,13 +192,13 @@ bool cSandSimulator::IsReplacedOnRematerialization(BLOCKTYPE a_BlockType) switch (a_BlockType) { case E_BLOCK_AIR: + case E_BLOCK_DEAD_BUSH: case E_BLOCK_FIRE: - case E_BLOCK_WATER: - case E_BLOCK_STATIONARY_WATER: case E_BLOCK_LAVA: case E_BLOCK_STATIONARY_LAVA: + case E_BLOCK_STATIONARY_WATER: case E_BLOCK_TALL_GRASS: - case E_BLOCK_DEAD_BUSH: + case E_BLOCK_WATER: { return true; } @@ -202,14 +210,14 @@ bool cSandSimulator::IsReplacedOnRematerialization(BLOCKTYPE a_BlockType) -bool cSandSimulator::DoesBreakFallingThrough(BLOCKTYPE a_BlockType) +bool cSandSimulator::DoesBreakFallingThrough(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { switch (a_BlockType) { case E_BLOCK_STONE_SLAB: case E_BLOCK_WOODEN_SLAB: { - return true; + return ((a_BlockMeta & 0x08) == 0); // Only a bottom-slab breaks the block } } return false; @@ -255,11 +263,19 @@ void cSandSimulator::DoInstantFall(cChunk * a_Chunk, int a_RelX, int a_RelY, int // Search for a place to put it: for (int y = a_RelY - 1; y >= 0; y--) { - BLOCKTYPE BlockType = a_Chunk->GetBlock(a_RelX, y, a_RelZ); - if ( - !DoesBreakFallingThrough(BlockType) && - CanContinueFallThrough(BlockType) - ) + BLOCKTYPE BlockType; + NIBBLETYPE BlockMeta; + a_Chunk->GetBlockTypeMeta(a_RelX, y, a_RelZ, BlockType, BlockMeta); + int BlockY; + if (DoesBreakFallingThrough(BlockType, BlockMeta)) + { + BlockY = y; + } + else if (!CanContinueFallThrough(BlockType)) + { + BlockY = y + 1; + } + else { // Can fall further down continue; @@ -268,7 +284,7 @@ void cSandSimulator::DoInstantFall(cChunk * a_Chunk, int a_RelX, int a_RelY, int // Finish the fall at the found bottom: int BlockX = a_RelX + a_Chunk->GetPosX() * cChunkDef::Width; int BlockZ = a_RelZ + a_Chunk->GetPosZ() * cChunkDef::Width; - FinishFalling(&m_World, BlockX, y + 1, BlockZ, FallingBlockType, FallingBlockMeta); + FinishFalling(&m_World, BlockX, BlockY, BlockZ, FallingBlockType, FallingBlockMeta); return; } diff --git a/source/Simulator/SandSimulator.h b/source/Simulator/SandSimulator.h index 571258049..6e9ea15ac 100644 --- a/source/Simulator/SandSimulator.h +++ b/source/Simulator/SandSimulator.h @@ -29,7 +29,7 @@ public: static bool IsReplacedOnRematerialization(BLOCKTYPE a_BlockType); /// Returns true if the specified block breaks falling blocks while they fall through it (e. g. halfslabs) - static bool DoesBreakFallingThrough(BLOCKTYPE a_BlockType); + static bool DoesBreakFallingThrough(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); /** Called when a block finishes falling at the specified coords, either by insta-fall, or through cFallingBlock entity.