2013-07-29 07:13:03 -04:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "BlockHandler.h"
|
2017-08-06 15:57:44 -04:00
|
|
|
|
|
|
|
|
2013-07-29 07:13:03 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class cBlockVineHandler :
|
|
|
|
public cBlockHandler
|
|
|
|
{
|
2020-04-13 12:38:06 -04:00
|
|
|
using Super = cBlockHandler;
|
2019-10-16 04:06:34 -04:00
|
|
|
|
2013-07-29 07:13:03 -04:00
|
|
|
public:
|
2019-10-16 04:06:34 -04:00
|
|
|
|
|
|
|
cBlockVineHandler(BLOCKTYPE a_BlockType):
|
2020-04-13 12:38:06 -04:00
|
|
|
Super(a_BlockType)
|
2013-07-29 07:13:03 -04:00
|
|
|
{
|
|
|
|
}
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2019-10-16 04:06:34 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-07-29 07:13:03 -04:00
|
|
|
virtual bool GetPlacementBlockTypeMeta(
|
2020-04-21 16:19:22 -04:00
|
|
|
cChunkInterface & a_ChunkInterface,
|
|
|
|
cPlayer & a_Player,
|
|
|
|
const Vector3i a_PlacedBlockPos,
|
|
|
|
eBlockFace a_ClickedBlockFace,
|
|
|
|
const Vector3i a_CursorPos,
|
2013-07-29 07:13:03 -04:00
|
|
|
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
|
|
|
|
) override
|
|
|
|
{
|
|
|
|
// TODO: Disallow placement where the vine doesn't attach to something properly
|
|
|
|
BLOCKTYPE BlockType = 0;
|
|
|
|
NIBBLETYPE BlockMeta;
|
2020-04-21 16:19:22 -04:00
|
|
|
a_ChunkInterface.GetBlockTypeMeta(a_PlacedBlockPos, BlockType, BlockMeta);
|
2013-07-29 07:13:03 -04:00
|
|
|
if (BlockType == m_BlockType)
|
|
|
|
{
|
2020-04-21 16:19:22 -04:00
|
|
|
a_BlockMeta = BlockMeta | DirectionToMetaData(a_ClickedBlockFace);
|
2013-07-29 07:13:03 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-04-21 16:19:22 -04:00
|
|
|
a_BlockMeta = DirectionToMetaData(a_ClickedBlockFace);
|
2013-07-29 07:13:03 -04:00
|
|
|
}
|
|
|
|
a_BlockType = m_BlockType;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-10-16 04:06:34 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
virtual cItems ConvertToPickups(NIBBLETYPE a_BlockMeta, cBlockEntity * a_BlockEntity, const cEntity * a_Digger, const cItem * a_Tool) override
|
2014-07-23 10:32:09 -04:00
|
|
|
{
|
2019-10-16 04:06:34 -04: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 10:32:09 -04:00
|
|
|
}
|
|
|
|
|
2019-10-16 04:06:34 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-07-29 07:13:03 -04: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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-16 04:06:34 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-07-29 07:13:03 -04:00
|
|
|
static char MetaDataToDirection(NIBBLETYPE a_MetaData)
|
|
|
|
{
|
2014-07-21 09:19:48 -04:00
|
|
|
switch (a_MetaData)
|
2013-07-29 07:13:03 -04: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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-16 04:06:34 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-06-30 10:50:15 -04:00
|
|
|
/** Returns true if the specified block type is good for vines to attach to */
|
2013-07-29 07:13:03 -04:00
|
|
|
static bool IsBlockAttachable(BLOCKTYPE a_BlockType)
|
|
|
|
{
|
2014-10-07 10:48:37 -04:00
|
|
|
switch (a_BlockType)
|
|
|
|
{
|
2017-06-20 10:42:14 -04:00
|
|
|
case E_BLOCK_CHEST:
|
|
|
|
case E_BLOCK_ENDER_CHEST:
|
2014-10-07 10:48:37 -04:00
|
|
|
case E_BLOCK_GLASS:
|
2017-06-20 10:42:14 -04:00
|
|
|
case E_BLOCK_PISTON:
|
|
|
|
case E_BLOCK_PISTON_EXTENSION:
|
|
|
|
case E_BLOCK_REDSTONE_REPEATER_OFF:
|
|
|
|
case E_BLOCK_REDSTONE_REPEATER_ON:
|
2014-10-07 10:48:37 -04:00
|
|
|
case E_BLOCK_STAINED_GLASS:
|
2017-06-20 10:42:14 -04:00
|
|
|
case E_BLOCK_STICKY_PISTON:
|
2014-10-07 10:48:37 -04:00
|
|
|
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 07:13:03 -04:00
|
|
|
}
|
|
|
|
|
2019-10-16 04:06:34 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-06-30 10:50:15 -04:00
|
|
|
/** Returns the meta that has the maximum allowable sides of the vine, given the surroundings */
|
2019-10-16 04:06:34 -04:00
|
|
|
NIBBLETYPE GetMaxMeta(cChunk & a_Chunk, Vector3i a_RelPos)
|
2013-07-29 07:13:03 -04:00
|
|
|
{
|
|
|
|
static const struct
|
|
|
|
{
|
|
|
|
int x, z;
|
2014-03-30 17:13:13 -04:00
|
|
|
NIBBLETYPE Bit;
|
2013-07-29 07:13:03 -04:00
|
|
|
} Coords[] =
|
|
|
|
{
|
|
|
|
{ 0, 1, 1}, // south, ZP
|
|
|
|
{-1, 0, 2}, // west, XM
|
|
|
|
{ 0, -1, 4}, // north, ZM
|
|
|
|
{ 1, 0, 8}, // east, XP
|
|
|
|
} ;
|
2014-03-30 17:13:13 -04:00
|
|
|
NIBBLETYPE res = 0;
|
2017-11-20 06:13:11 -05:00
|
|
|
for (auto & Coord : Coords)
|
2013-07-29 07:13:03 -04:00
|
|
|
{
|
|
|
|
BLOCKTYPE BlockType;
|
|
|
|
NIBBLETYPE BlockMeta;
|
2019-10-16 04:06:34 -04:00
|
|
|
auto checkPos = a_RelPos.addedXZ(Coord.x, Coord.z);
|
2013-07-29 07:13:03 -04:00
|
|
|
if (
|
2019-10-16 04:06:34 -04:00
|
|
|
a_Chunk.UnboundedRelGetBlock(checkPos.x, checkPos.y, checkPos.z, BlockType, BlockMeta) &&
|
2013-07-29 07:13:03 -04:00
|
|
|
IsBlockAttachable(BlockType)
|
|
|
|
)
|
|
|
|
{
|
2017-11-20 06:13:11 -05:00
|
|
|
res |= Coord.Bit;
|
2013-07-29 07:13:03 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2019-10-16 04:06:34 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
virtual void Check(
|
|
|
|
cChunkInterface & a_ChunkInterface, cBlockPluginInterface & a_PluginInterface,
|
|
|
|
Vector3i a_RelPos,
|
|
|
|
cChunk & a_Chunk
|
|
|
|
) override
|
2013-07-29 07:13:03 -04:00
|
|
|
{
|
2019-10-16 04:06:34 -04:00
|
|
|
NIBBLETYPE CurMeta = a_Chunk.GetMeta(a_RelPos);
|
|
|
|
NIBBLETYPE MaxMeta = GetMaxMeta(a_Chunk, a_RelPos);
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2013-07-29 07:13:03 -04:00
|
|
|
// Check if vine above us, add its meta to MaxMeta
|
2019-10-16 04:06:34 -04:00
|
|
|
if ((a_RelPos.y < cChunkDef::Height - 1) && (a_Chunk.GetBlock(a_RelPos.addedY(1)) == m_BlockType))
|
2013-07-29 07:13:03 -04:00
|
|
|
{
|
2019-10-16 04:06:34 -04:00
|
|
|
MaxMeta |= a_Chunk.GetMeta(a_RelPos.addedY(1));
|
2013-07-29 07:13:03 -04:00
|
|
|
}
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2013-07-29 07:13:03 -04: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
|
2019-10-16 04:06:34 -04:00
|
|
|
bool HasTop = (a_RelPos.y < cChunkDef::Height - 1) && IsBlockAttachable(a_Chunk.GetBlock(a_RelPos.addedY(1)));
|
2013-07-29 07:13:03 -04:00
|
|
|
if ((Common == 0) && !HasTop)
|
|
|
|
{
|
|
|
|
// The vine just lost all its support, destroy the block:
|
|
|
|
if (DoesDropOnUnsuitable())
|
|
|
|
{
|
2019-10-16 04:06:34 -04:00
|
|
|
a_ChunkInterface.DropBlockAsPickups(a_Chunk.RelativeToAbsolute(a_RelPos));
|
2013-07-29 07:13:03 -04:00
|
|
|
}
|
2019-10-16 04:06:34 -04:00
|
|
|
a_Chunk.SetBlock(a_RelPos, E_BLOCK_AIR, 0);
|
2013-07-29 07:13:03 -04:00
|
|
|
return;
|
|
|
|
}
|
2019-10-16 04:06:34 -04:00
|
|
|
a_Chunk.SetBlock(a_RelPos, m_BlockType, Common);
|
2013-07-29 07:13:03 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-10-16 04:06:34 -04:00
|
|
|
auto absPos = a_Chunk.RelativeToAbsolute(a_RelPos);
|
|
|
|
a_Chunk.GetWorld()->GetSimulatorManager()->WakeUp(absPos, &a_Chunk);
|
2013-07-29 07:13:03 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-16 04:06:34 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-07-07 10:37:53 -04:00
|
|
|
virtual bool DoesIgnoreBuildCollision(cChunkInterface & a_ChunkInterface, Vector3i a_Pos, cPlayer & a_Player, NIBBLETYPE a_Meta) override
|
2013-07-29 07:13:03 -04:00
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-10-16 04:06:34 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-07-29 07:13:03 -04:00
|
|
|
virtual bool DoesDropOnUnsuitable(void) override
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2014-10-15 13:01:55 -04:00
|
|
|
|
2019-10-16 04:06:34 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-04-17 05:36:37 -04:00
|
|
|
virtual void OnUpdate(
|
|
|
|
cChunkInterface & a_ChunkInterface,
|
|
|
|
cWorldInterface & a_WorldInterface,
|
|
|
|
cBlockPluginInterface & a_PluginInterface,
|
|
|
|
cChunk & a_Chunk,
|
|
|
|
const Vector3i a_RelPos
|
|
|
|
) override
|
2013-08-24 17:00:24 -04:00
|
|
|
{
|
2014-03-07 13:42:13 -05:00
|
|
|
UNUSED(a_ChunkInterface);
|
|
|
|
UNUSED(a_WorldInterface);
|
|
|
|
|
2014-10-15 13:01:55 -04:00
|
|
|
// Vine cannot grow down if at the bottom:
|
2020-04-17 05:36:37 -04:00
|
|
|
auto GrowPos = a_RelPos.addedY(-1);
|
|
|
|
if (!cChunkDef::IsValidHeight(GrowPos.y))
|
2014-10-15 13:01:55 -04:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Grow one block down, if possible:
|
2014-03-07 13:42:13 -05:00
|
|
|
BLOCKTYPE Block;
|
2020-04-17 05:36:37 -04:00
|
|
|
a_Chunk.UnboundedRelGetBlockType(GrowPos, Block);
|
2014-03-07 13:42:13 -05:00
|
|
|
if (Block == E_BLOCK_AIR)
|
2013-08-24 17:00:24 -04:00
|
|
|
{
|
2020-04-17 05:36:37 -04:00
|
|
|
auto WorldPos = a_Chunk.RelativeToAbsolute(GrowPos);
|
|
|
|
if (!a_PluginInterface.CallHookBlockSpread(WorldPos.x, WorldPos.y, WorldPos.z, ssVineSpread))
|
2014-03-16 11:06:03 -04:00
|
|
|
{
|
2020-04-17 05:36:37 -04:00
|
|
|
a_Chunk.UnboundedRelSetBlock(GrowPos, E_BLOCK_VINES, a_Chunk.GetMeta(a_RelPos));
|
2014-03-16 11:06:03 -04:00
|
|
|
}
|
2013-08-24 17:00:24 -04:00
|
|
|
}
|
|
|
|
}
|
2014-10-15 13:01:55 -04:00
|
|
|
|
2019-10-16 04:06:34 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-07-29 07:13:03 -04:00
|
|
|
virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) override
|
|
|
|
{
|
|
|
|
return ((a_Meta >> 1) | (a_Meta << 3)) & 0x0f; // Rotate bits to the right
|
|
|
|
}
|
|
|
|
|
2019-10-16 04:06:34 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-07-29 07:13:03 -04:00
|
|
|
virtual NIBBLETYPE MetaRotateCW(NIBBLETYPE a_Meta) override
|
|
|
|
{
|
|
|
|
return ((a_Meta << 1) | (a_Meta >> 3)) & 0x0f; // Rotate bits to the left
|
|
|
|
}
|
2014-03-02 07:02:29 -05:00
|
|
|
|
2019-10-16 04:06:34 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-07-29 07:13:03 -04:00
|
|
|
virtual NIBBLETYPE MetaMirrorXY(NIBBLETYPE a_Meta) override
|
|
|
|
{
|
|
|
|
// Bits 2 and 4 stay, bits 1 and 3 swap
|
2015-07-29 11:04:03 -04:00
|
|
|
return static_cast<NIBBLETYPE>((a_Meta & 0x0a) | ((a_Meta & 0x01) << 2) | ((a_Meta & 0x04) >> 2));
|
2013-07-29 07:13:03 -04:00
|
|
|
}
|
|
|
|
|
2019-10-16 04:06:34 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-07-29 07:13:03 -04:00
|
|
|
virtual NIBBLETYPE MetaMirrorYZ(NIBBLETYPE a_Meta) override
|
|
|
|
{
|
|
|
|
// Bits 1 and 3 stay, bits 2 and 4 swap
|
2015-07-29 11:04:03 -04:00
|
|
|
return static_cast<NIBBLETYPE>((a_Meta & 0x05) | ((a_Meta & 0x02) << 2) | ((a_Meta & 0x08) >> 2));
|
2013-07-29 07:13:03 -04:00
|
|
|
}
|
|
|
|
|
2019-10-16 04:06:34 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-06-30 10:50:15 -04:00
|
|
|
virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override
|
|
|
|
{
|
|
|
|
UNUSED(a_Meta);
|
|
|
|
return 7;
|
|
|
|
}
|
2013-07-29 07:13:03 -04:00
|
|
|
} ;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|