Files
cuberite-2a/src/Blocks/BlockVine.h
T

289 lines
6.0 KiB
C++
Raw Normal View History

2013-07-29 12:13:03 +01:00
#pragma once
#include "BlockHandler.h"
2017-08-06 21:57:44 +02:00
2013-07-29 12:13:03 +01:00
class cBlockVineHandler final :
2013-07-29 12:13:03 +01:00
public cBlockHandler
{
2020-04-13 18:38:06 +02:00
using Super = cBlockHandler;
2013-07-29 12:13:03 +01:00
public:
using Super::Super;
private:
2013-07-29 12:13:03 +01:00
virtual bool GetPlacementBlockTypeMeta(
2020-04-21 22:19:22 +02:00
cChunkInterface & a_ChunkInterface,
cPlayer & a_Player,
const Vector3i a_PlacedBlockPos,
eBlockFace a_ClickedBlockFace,
const Vector3i a_CursorPos,
2013-07-29 12:13:03 +01:00
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) const override
2013-07-29 12:13:03 +01:00
{
// TODO: Disallow placement where the vine doesn't attach to something properly
BLOCKTYPE BlockType = 0;
NIBBLETYPE BlockMeta;
2020-04-21 22:19:22 +02:00
a_ChunkInterface.GetBlockTypeMeta(a_PlacedBlockPos, BlockType, BlockMeta);
2013-07-29 12:13:03 +01:00
if (BlockType == m_BlockType)
{
2020-04-21 22:19:22 +02:00
a_BlockMeta = BlockMeta | DirectionToMetaData(a_ClickedBlockFace);
2013-07-29 12:13:03 +01:00
}
else
{
2020-04-21 22:19:22 +02:00
a_BlockMeta = DirectionToMetaData(a_ClickedBlockFace);
2013-07-29 12:13:03 +01:00
}
a_BlockType = m_BlockType;
return true;
}
2020-09-23 16:06:27 +01:00
virtual cItems ConvertToPickups(NIBBLETYPE a_BlockMeta, const cEntity * a_Digger, const cItem * a_Tool) const override
2014-07-23 16:32:09 +02:00
{
// Only drops self when using shears, otherwise drops nothing:
if ((a_Tool == nullptr) || (a_Tool->m_ItemType != E_ITEM_SHEARS))
{
return {};
}
return cItem(E_BLOCK_VINES, 1, 0);
2014-07-23 16:32:09 +02:00
}
2013-07-29 12:13:03 +01:00
static NIBBLETYPE DirectionToMetaData(char a_BlockFace)
{
switch (a_BlockFace)
{
case BLOCK_FACE_NORTH: return 0x1;
case BLOCK_FACE_SOUTH: return 0x4;
case BLOCK_FACE_WEST: return 0x8;
case BLOCK_FACE_EAST: return 0x2;
default: return 0x0;
}
}
2013-07-29 12:13:03 +01:00
static char MetaDataToDirection(NIBBLETYPE a_MetaData)
{
switch (a_MetaData)
2013-07-29 12:13:03 +01:00
{
case 0x1: return BLOCK_FACE_NORTH;
case 0x4: return BLOCK_FACE_SOUTH;
case 0x8: return BLOCK_FACE_WEST;
case 0x2: return BLOCK_FACE_EAST;
default: return BLOCK_FACE_TOP;
}
}
2015-06-30 15:50:15 +01:00
/** Returns true if the specified block type is good for vines to attach to */
2013-07-29 12:13:03 +01:00
static bool IsBlockAttachable(BLOCKTYPE a_BlockType)
{
switch (a_BlockType)
{
2017-06-20 16:42:14 +02:00
case E_BLOCK_CHEST:
case E_BLOCK_ENDER_CHEST:
case E_BLOCK_GLASS:
2017-06-20 16:42:14 +02:00
case E_BLOCK_PISTON:
case E_BLOCK_PISTON_EXTENSION:
case E_BLOCK_REDSTONE_REPEATER_OFF:
case E_BLOCK_REDSTONE_REPEATER_ON:
case E_BLOCK_STAINED_GLASS:
2017-06-20 16:42:14 +02:00
case E_BLOCK_STICKY_PISTON:
case E_BLOCK_TRAPPED_CHEST:
{
// You can't attach a vine to this solid blocks.
return false;
}
default:
{
return cBlockInfo::IsSolid(a_BlockType);
}
}
2013-07-29 12:13:03 +01:00
}
2015-06-30 15:50:15 +01:00
/** Returns the meta that has the maximum allowable sides of the vine, given the surroundings */
static NIBBLETYPE GetMaxMeta(cChunk & a_Chunk, Vector3i a_RelPos)
2013-07-29 12:13:03 +01:00
{
static const struct
{
int x, z;
NIBBLETYPE Bit;
2013-07-29 12:13:03 +01:00
} Coords[] =
{
{ 0, 1, 1}, // south, ZP
{-1, 0, 2}, // west, XM
{ 0, -1, 4}, // north, ZM
{ 1, 0, 8}, // east, XP
} ;
NIBBLETYPE res = 0;
for (auto & Coord : Coords)
2013-07-29 12:13:03 +01:00
{
BLOCKTYPE BlockType;
NIBBLETYPE BlockMeta;
auto checkPos = a_RelPos.addedXZ(Coord.x, Coord.z);
2013-07-29 12:13:03 +01:00
if (
a_Chunk.UnboundedRelGetBlock(checkPos.x, checkPos.y, checkPos.z, BlockType, BlockMeta) &&
2013-07-29 12:13:03 +01:00
IsBlockAttachable(BlockType)
)
{
res |= Coord.Bit;
2013-07-29 12:13:03 +01:00
}
}
return res;
}
2016-02-05 23:45:45 +02:00
virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos, eBlockFace a_WhichNeighbor) const override
2013-07-29 12:13:03 +01:00
{
2020-08-01 11:25:06 +01:00
a_ChunkInterface.DoWithChunkAt(a_BlockPos, [&](cChunk & a_Chunk)
{
const auto a_RelPos = cChunkDef::AbsoluteToRelative(a_BlockPos);
NIBBLETYPE CurMeta = a_Chunk.GetMeta(a_RelPos);
NIBBLETYPE MaxMeta = GetMaxMeta(a_Chunk, a_RelPos);
2016-02-05 23:45:45 +02:00
2013-07-29 12:13:03 +01:00
// Check if vine above us, add its meta to MaxMeta
if ((a_RelPos.y < cChunkDef::Height - 1) && (a_Chunk.GetBlock(a_RelPos.addedY(1)) == m_BlockType))
2013-07-29 12:13:03 +01:00
{
MaxMeta |= a_Chunk.GetMeta(a_RelPos.addedY(1));
2013-07-29 12:13:03 +01:00
}
2016-02-05 23:45:45 +02:00
2013-07-29 12:13:03 +01:00
NIBBLETYPE Common = CurMeta & MaxMeta; // Neighbors that we have and are legal
if (Common != CurMeta)
{
// There is a neighbor missing, need to update the meta or even destroy the block
bool HasTop = (a_RelPos.y < cChunkDef::Height - 1) && IsBlockAttachable(a_Chunk.GetBlock(a_RelPos.addedY(1)));
2013-07-29 12:13:03 +01:00
if ((Common == 0) && !HasTop)
{
// The vine just lost all its support, destroy the block:
a_Chunk.SetBlock(a_RelPos, E_BLOCK_AIR, 0);
2020-08-01 11:25:06 +01:00
return false;
2013-07-29 12:13:03 +01:00
}
a_Chunk.SetBlock(a_RelPos, m_BlockType, Common);
2013-07-29 12:13:03 +01:00
}
2020-08-01 11:25:06 +01:00
return false;
});
2013-07-29 12:13:03 +01:00
}
virtual bool DoesIgnoreBuildCollision(cChunkInterface & a_ChunkInterface, Vector3i a_Pos, cPlayer & a_Player, NIBBLETYPE a_Meta) const override
2013-07-29 12:13:03 +01:00
{
return true;
}
2020-04-17 11:36:37 +02:00
virtual void OnUpdate(
cChunkInterface & a_ChunkInterface,
cWorldInterface & a_WorldInterface,
cBlockPluginInterface & a_PluginInterface,
cChunk & a_Chunk,
const Vector3i a_RelPos
) const override
2013-08-24 22:00:24 +01:00
{
2014-03-07 10:42:13 -08:00
UNUSED(a_ChunkInterface);
UNUSED(a_WorldInterface);
// Vine cannot grow down if at the bottom:
2020-04-17 11:36:37 +02:00
auto GrowPos = a_RelPos.addedY(-1);
if (!cChunkDef::IsValidHeight(GrowPos.y))
{
return;
}
// Grow one block down, if possible:
2014-03-07 10:42:13 -08:00
BLOCKTYPE Block;
2020-04-17 11:36:37 +02:00
a_Chunk.UnboundedRelGetBlockType(GrowPos, Block);
2014-03-07 10:42:13 -08:00
if (Block == E_BLOCK_AIR)
2013-08-24 22:00:24 +01:00
{
2020-04-17 11:36:37 +02:00
auto WorldPos = a_Chunk.RelativeToAbsolute(GrowPos);
if (!a_PluginInterface.CallHookBlockSpread(WorldPos.x, WorldPos.y, WorldPos.z, ssVineSpread))
2014-03-16 16:06:03 +01:00
{
2020-04-17 11:36:37 +02:00
a_Chunk.UnboundedRelSetBlock(GrowPos, E_BLOCK_VINES, a_Chunk.GetMeta(a_RelPos));
2014-03-16 16:06:03 +01:00
}
2013-08-24 22:00:24 +01:00
}
}
virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) const override
2013-07-29 12:13:03 +01:00
{
return ((a_Meta >> 1) | (a_Meta << 3)) & 0x0f; // Rotate bits to the right
}
virtual NIBBLETYPE MetaRotateCW(NIBBLETYPE a_Meta) const override
2013-07-29 12:13:03 +01:00
{
return ((a_Meta << 1) | (a_Meta >> 3)) & 0x0f; // Rotate bits to the left
}
2014-03-02 12:02:29 +00:00
virtual NIBBLETYPE MetaMirrorXY(NIBBLETYPE a_Meta) const override
2013-07-29 12:13:03 +01:00
{
// Bits 2 and 4 stay, bits 1 and 3 swap
return static_cast<NIBBLETYPE>((a_Meta & 0x0a) | ((a_Meta & 0x01) << 2) | ((a_Meta & 0x04) >> 2));
2013-07-29 12:13:03 +01:00
}
virtual NIBBLETYPE MetaMirrorYZ(NIBBLETYPE a_Meta) const override
2013-07-29 12:13:03 +01:00
{
// Bits 1 and 3 stay, bits 2 and 4 swap
return static_cast<NIBBLETYPE>((a_Meta & 0x05) | ((a_Meta & 0x02) << 2) | ((a_Meta & 0x08) >> 2));
2013-07-29 12:13:03 +01:00
}
virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override
2015-06-30 15:50:15 +01:00
{
UNUSED(a_Meta);
return 7;
}
2013-07-29 12:13:03 +01:00
} ;