From 68fc28857fce6fdc4ebde6fa8ec4760e4a68e86e Mon Sep 17 00:00:00 2001 From: Zach DeCook Date: Wed, 3 Jan 2018 11:33:31 -0500 Subject: Concrete mixing (#4096) Adds a block handler for concrete powder and implements hardening to concrete. Concrete powder turns into concrete when: * It is next to water when it receives a block update * It falls onto a water block (even with Physics SandInstantFall=1) --- CONTRIBUTORS | 1 + src/Blocks/BlockConcretePowder.h | 106 +++++++++++++++++++++++++++++++++++++++ src/Blocks/BlockHandler.cpp | 2 + src/Blocks/CMakeLists.txt | 1 + src/Entities/FallingBlock.cpp | 7 +++ src/Simulator/SandSimulator.cpp | 5 ++ 6 files changed, 122 insertions(+) create mode 100644 src/Blocks/BlockConcretePowder.h diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 5ed1d02b2..0fe2a8806 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -15,6 +15,7 @@ Bond_009 derouinw Diusrex Duralex +Earboxer (Zach DeCook) FakeTruth (founder) Gareth Nelson HaoTNN diff --git a/src/Blocks/BlockConcretePowder.h b/src/Blocks/BlockConcretePowder.h new file mode 100644 index 000000000..4b2a81b2a --- /dev/null +++ b/src/Blocks/BlockConcretePowder.h @@ -0,0 +1,106 @@ + +#pragma once + +#include "BlockHandler.h" + + + + + +class cBlockConcretePowderHandler : + public cBlockHandler +{ +public: + cBlockConcretePowderHandler(BLOCKTYPE a_BlockType): + cBlockHandler(a_BlockType) + { + } + + + + + + virtual void Check(cChunkInterface & a_ChunkInterface, cBlockPluginInterface & a_PluginInterface, int a_RelX, int a_RelY, int a_RelZ, cChunk & a_Chunk) override + { + if (GetSoaked(Vector3i(a_RelX, a_RelY, a_RelZ), a_Chunk)) + { + return; + } + cBlockHandler::Check(a_ChunkInterface, a_PluginInterface, a_RelX, a_RelY, a_RelZ, a_Chunk); + } + + + + + + /** Check blocks above and around to see if they are water. If one is, convert this into concrete block. + Returns TRUE if the block was changed. */ + bool GetSoaked(Vector3i a_Rel, cChunk & a_Chunk) + { + static const std::array WaterCheck + { + { + { 1, 0, 0}, + {-1, 0, 0}, + { 0, 0, 1}, + { 0, 0, -1}, + { 0, 1, 0}, + } + }; + + bool ShouldSoak = std::any_of(WaterCheck.cbegin(), WaterCheck.cend(), [a_Rel, & a_Chunk](Vector3i a_Offset) + { + BLOCKTYPE NeighborType; + return ( + a_Chunk.UnboundedRelGetBlockType(a_Rel.x + a_Offset.x, a_Rel.y + a_Offset.y, a_Rel.z + a_Offset.z, NeighborType) + && IsBlockWater(NeighborType) + ); + } + ); + + if (ShouldSoak) + { + NIBBLETYPE BlockMeta; + BlockMeta = a_Chunk.GetMeta(a_Rel.x, a_Rel.y, a_Rel.z); + a_Chunk.SetBlock(a_Rel.x, a_Rel.y, a_Rel.z, E_BLOCK_CONCRETE, BlockMeta); + return true; + } + return false; + } + + + + + + virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override + { + switch (a_Meta) + { + case E_META_CONCRETE_POWDER_WHITE: return 8; + case E_META_CONCRETE_POWDER_ORANGE: return 15; + case E_META_CONCRETE_POWDER_MAGENTA: return 16; + case E_META_CONCRETE_POWDER_LIGHTBLUE: return 17; + case E_META_CONCRETE_POWDER_YELLOW: return 18; + case E_META_CONCRETE_POWDER_LIGHTGREEN: return 19; + case E_META_CONCRETE_POWDER_PINK: return 20; + case E_META_CONCRETE_POWDER_GRAY: return 21; + case E_META_CONCRETE_POWDER_LIGHTGRAY: return 22; + case E_META_CONCRETE_POWDER_CYAN: return 23; + case E_META_CONCRETE_POWDER_PURPLE: return 24; + case E_META_CONCRETE_POWDER_BLUE: return 25; + case E_META_CONCRETE_POWDER_BROWN: return 26; + case E_META_CONCRETE_POWDER_GREEN: return 27; + case E_META_CONCRETE_POWDER_RED: return 28; + case E_META_CONCRETE_POWDER_BLACK: return 29; + default: + { + ASSERT(!"Unhandled meta in concrete powder handler!"); + return 0; + } + } + } +}; + + + + diff --git a/src/Blocks/BlockHandler.cpp b/src/Blocks/BlockHandler.cpp index 9fc41de76..fb097c395 100644 --- a/src/Blocks/BlockHandler.cpp +++ b/src/Blocks/BlockHandler.cpp @@ -20,6 +20,7 @@ #include "BlockCocoaPod.h" #include "BlockCommandBlock.h" #include "BlockComparator.h" +#include "BlockConcretePowder.h" #include "BlockCrops.h" #include "BlockDeadBush.h" #include "BlockDirt.h" @@ -210,6 +211,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType) case E_BLOCK_COCOA_POD: return new cBlockCocoaPodHandler (a_BlockType); case E_BLOCK_COMMAND_BLOCK: return new cBlockCommandBlockHandler (a_BlockType); case E_BLOCK_ACTIVE_COMPARATOR: return new cBlockComparatorHandler (a_BlockType); + case E_BLOCK_CONCRETE_POWDER: return new cBlockConcretePowderHandler (a_BlockType); case E_BLOCK_COBBLESTONE: return new cBlockStoneHandler (a_BlockType); case E_BLOCK_COBBLESTONE_STAIRS: return new cBlockStairsHandler (a_BlockType); case E_BLOCK_COBWEB: return new cBlockCobWebHandler (a_BlockType); diff --git a/src/Blocks/CMakeLists.txt b/src/Blocks/CMakeLists.txt index bc1b62290..496ec69e4 100644 --- a/src/Blocks/CMakeLists.txt +++ b/src/Blocks/CMakeLists.txt @@ -26,6 +26,7 @@ SET (HDRS BlockCocoaPod.h BlockCommandBlock.h BlockComparator.h + BlockConcretePowder.h BlockCrops.h BlockDeadBush.h BlockDirt.h diff --git a/src/Entities/FallingBlock.cpp b/src/Entities/FallingBlock.cpp index ae5bbd366..cbbb97202 100644 --- a/src/Entities/FallingBlock.cpp +++ b/src/Entities/FallingBlock.cpp @@ -86,6 +86,13 @@ void cFallingBlock::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) Destroy(true); return; } + else if ((m_BlockType == E_BLOCK_CONCRETE_POWDER) && IsBlockWater(BlockBelow)) + { + // Concrete powder falling into water solidifies on the first water it touches + cSandSimulator::FinishFalling(m_World, BlockX, BlockY, BlockZ, E_BLOCK_CONCRETE, m_BlockMeta); + Destroy(true); + return; + } float MilliDt = a_Dt.count() * 0.001f; AddSpeedY(MilliDt * -9.8f); diff --git a/src/Simulator/SandSimulator.cpp b/src/Simulator/SandSimulator.cpp index 01e699b49..d10523c61 100644 --- a/src/Simulator/SandSimulator.cpp +++ b/src/Simulator/SandSimulator.cpp @@ -319,6 +319,11 @@ void cSandSimulator::DoInstantFall(cChunk * a_Chunk, int a_RelX, int a_RelY, int { BlockY = y + 1; } + else if ((FallingBlockType == E_BLOCK_CONCRETE_POWDER) && IsBlockWater(BlockType)) + { + FallingBlockType = E_BLOCK_CONCRETE; + BlockY = y; + } else { // Can fall further down -- cgit v1.2.3