parent
24a8456f79
commit
31a8d017d9
@ -16582,6 +16582,14 @@ end
|
||||
{
|
||||
Notes = "A flag in the metadata of heads that indicates that the head is a zombie head.",
|
||||
},
|
||||
E_META_SPONGE_DRY =
|
||||
{
|
||||
Notes = "A flag in the metadata of sponges that indicates that the sponge is dry.",
|
||||
},
|
||||
E_META_SPONGE_WET =
|
||||
{
|
||||
Notes = "A flag in the metadata of sponges that indicates that the sponge is wet.",
|
||||
},
|
||||
esBed =
|
||||
{
|
||||
Notes = "A bed explosion. The SourceData param is the {{Vector3i|position}} of the bed.",
|
||||
|
@ -806,6 +806,10 @@ enum ENUM_BLOCK_META : NIBBLETYPE
|
||||
E_META_SNOW_LAYER_SEVEN = 6,
|
||||
E_META_SNOW_LAYER_EIGHT = 7,
|
||||
|
||||
// E_BLOCK_SPONGE metas:
|
||||
E_META_SPONGE_DRY = 0,
|
||||
E_META_SPONGE_WET = 1,
|
||||
|
||||
// E_BLOCK_STAINED_CLAY metas:
|
||||
E_META_STAINED_CLAY_WHITE = 0,
|
||||
E_META_STAINED_CLAY_ORANGE = 1,
|
||||
|
@ -77,6 +77,7 @@
|
||||
#include "BlockSlab.h"
|
||||
#include "BlockSlime.h"
|
||||
#include "BlockSnow.h"
|
||||
#include "BlockSponge.h"
|
||||
#include "BlockStairs.h"
|
||||
#include "BlockStems.h"
|
||||
#include "BlockStone.h"
|
||||
@ -317,6 +318,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
|
||||
case E_BLOCK_SIGN_POST: return new cBlockSignPostHandler (a_BlockType);
|
||||
case E_BLOCK_SNOW: return new cBlockSnowHandler (a_BlockType);
|
||||
case E_BLOCK_SLIME_BLOCK: return new cBlockSlimeHandler (a_BlockType);
|
||||
case E_BLOCK_SPONGE: return new cBlockSpongeHandler (a_BlockType);
|
||||
case E_BLOCK_SPRUCE_DOOR: return new cBlockDoorHandler (a_BlockType);
|
||||
case E_BLOCK_SPRUCE_FENCE: return new cBlockFenceHandler (a_BlockType);
|
||||
case E_BLOCK_SPRUCE_FENCE_GATE: return new cBlockFenceGateHandler (a_BlockType);
|
||||
|
157
src/Blocks/BlockSponge.h
Normal file
157
src/Blocks/BlockSponge.h
Normal file
@ -0,0 +1,157 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BlockHandler.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class cBlockSpongeHandler :
|
||||
public cBlockHandler
|
||||
{
|
||||
public:
|
||||
cBlockSpongeHandler(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 around the sponge to see if they are water.
|
||||
If a dry sponge is touching water, soak up up to 65 blocks of water,
|
||||
with a taxicab distance of 7, and turn the sponge into a wet sponge.
|
||||
Returns TRUE if the block was changed. */
|
||||
bool GetSoaked(Vector3i a_Rel, cChunk & a_Chunk)
|
||||
{
|
||||
static const std::array<Vector3i, 6> WaterCheck
|
||||
{
|
||||
{
|
||||
{ 1, 0, 0},
|
||||
{-1, 0, 0},
|
||||
{ 0, 0, 1},
|
||||
{ 0, 0, -1},
|
||||
{ 0, 1, 0},
|
||||
{ 0, -1, 0},
|
||||
}
|
||||
};
|
||||
struct sSeed
|
||||
{
|
||||
sSeed(Vector3i pos, int d)
|
||||
{
|
||||
m_Pos = pos;
|
||||
m_Depth = d;
|
||||
}
|
||||
Vector3i m_Pos;
|
||||
int m_Depth;
|
||||
};
|
||||
|
||||
|
||||
// Check if this is a dry sponge next to a water block.
|
||||
NIBBLETYPE TargetMeta = a_Chunk.GetMeta(a_Rel.x, a_Rel.y, a_Rel.z);
|
||||
if (TargetMeta != E_META_SPONGE_DRY)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ShouldSoak = std::any_of(WaterCheck.cbegin(), WaterCheck.cend(), [a_Rel, & a_Chunk](Vector3i a_Offset)
|
||||
{
|
||||
return IsWet(a_Rel + a_Offset, a_Chunk);
|
||||
}
|
||||
);
|
||||
|
||||
// Early return if the sponge isn't touching any water.
|
||||
if (! ShouldSoak)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Use a queue to hold blocks that we want to check, so our search is breadth-first.
|
||||
std::queue<sSeed> Seeds;
|
||||
int count = 0;
|
||||
// Only go 7 blocks away from the center block.
|
||||
const int maxDepth = 7;
|
||||
// Start with the 6 blocks around the sponge.
|
||||
for (unsigned int i = 0; i < 6; i++)
|
||||
{
|
||||
Seeds.emplace(a_Rel + WaterCheck[i], maxDepth - 1);
|
||||
}
|
||||
|
||||
|
||||
// Keep checking blocks that are touching water blocks, or until 65 have been soaked up.
|
||||
while (!Seeds.empty() && count < 65)
|
||||
{
|
||||
sSeed seed = Seeds.front();
|
||||
Vector3i checkRel = seed.m_Pos;
|
||||
if (IsWet(checkRel, a_Chunk))
|
||||
{
|
||||
count++;
|
||||
DryUp(checkRel, a_Chunk);
|
||||
if (seed.m_Depth > 0)
|
||||
{
|
||||
// If this block was water, and we haven't yet gone too far away,
|
||||
// add itś neighbors to the queue to check.
|
||||
for (unsigned int i = 0; i < 6; i++)
|
||||
{
|
||||
Seeds.emplace(checkRel + WaterCheck[i], seed.m_Depth - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
Seeds.pop();
|
||||
}
|
||||
a_Chunk.SetBlock(a_Rel.x, a_Rel.y, a_Rel.z, E_BLOCK_SPONGE, E_META_SPONGE_WET);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static void DryUp(Vector3i a_Rel, cChunk & a_Chunk)
|
||||
{
|
||||
// TODO: support evaporating waterlogged blocks.
|
||||
a_Chunk.UnboundedRelSetBlock(a_Rel.x, a_Rel.y, a_Rel.z, E_BLOCK_AIR, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static bool IsWet(Vector3i a_Rel, cChunk & a_Chunk)
|
||||
{
|
||||
// TODO: support detecting waterlogged blocks.
|
||||
BLOCKTYPE Type;
|
||||
return(a_Chunk.UnboundedRelGetBlockType(a_Rel.x, a_Rel.y, a_Rel.z, Type) && IsBlockWater(Type));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override
|
||||
{
|
||||
UNUSED(a_Meta);
|
||||
return 18;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
Loading…
Reference in New Issue
Block a user