2013-07-29 11:13:03 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "BlockHandler.h"
|
2017-08-06 19:57:44 +00:00
|
|
|
|
|
|
|
|
2013-07-29 11:13:03 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2020-10-05 10:27:14 +00:00
|
|
|
class cBlockVineHandler final :
|
2013-07-29 11:13:03 +00:00
|
|
|
public cBlockHandler
|
|
|
|
{
|
2020-04-13 16:38:06 +00:00
|
|
|
using Super = cBlockHandler;
|
2019-10-16 08:06:34 +00:00
|
|
|
|
2013-07-29 11:13:03 +00:00
|
|
|
public:
|
2019-10-16 08:06:34 +00:00
|
|
|
|
2020-09-20 13:50:52 +00:00
|
|
|
using Super::Super;
|
2019-10-16 08:06:34 +00:00
|
|
|
|
2020-09-20 13:50:52 +00:00
|
|
|
private:
|
2019-10-16 08:06:34 +00:00
|
|
|
|
2021-05-05 13:25:10 +00:00
|
|
|
static const NIBBLETYPE VINE_LOST_SUPPORT = 16;
|
|
|
|
static const NIBBLETYPE VINE_UNCHANGED = 17;
|
2019-10-16 08:06:34 +00:00
|
|
|
|
|
|
|
|
2021-05-05 13:25:10 +00:00
|
|
|
virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
|
|
|
|
{
|
|
|
|
return GetMaxMeta(a_Chunk, a_Position, a_Meta) != VINE_LOST_SUPPORT;
|
|
|
|
}
|
2019-10-16 08:06:34 +00:00
|
|
|
|
|
|
|
|
2021-03-28 13:41:34 +00:00
|
|
|
virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override
|
2014-07-23 14:32:09 +00:00
|
|
|
{
|
2019-10-16 08:06:34 +00: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 14:32:09 +00:00
|
|
|
}
|
|
|
|
|
2019-10-16 08:06:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-07-29 11:13:03 +00:00
|
|
|
static char MetaDataToDirection(NIBBLETYPE a_MetaData)
|
|
|
|
{
|
2014-07-21 13:19:48 +00:00
|
|
|
switch (a_MetaData)
|
2013-07-29 11:13:03 +00: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 08:06:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-06-30 14:50:15 +00:00
|
|
|
/** Returns true if the specified block type is good for vines to attach to */
|
2013-07-29 11:13:03 +00:00
|
|
|
static bool IsBlockAttachable(BLOCKTYPE a_BlockType)
|
|
|
|
{
|
2014-10-07 14:48:37 +00:00
|
|
|
switch (a_BlockType)
|
|
|
|
{
|
2017-06-20 14:42:14 +00:00
|
|
|
case E_BLOCK_CHEST:
|
|
|
|
case E_BLOCK_ENDER_CHEST:
|
2014-10-07 14:48:37 +00:00
|
|
|
case E_BLOCK_GLASS:
|
2017-06-20 14:42:14 +00: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 14:48:37 +00:00
|
|
|
case E_BLOCK_STAINED_GLASS:
|
2017-06-20 14:42:14 +00:00
|
|
|
case E_BLOCK_STICKY_PISTON:
|
2014-10-07 14:48:37 +00: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 11:13:03 +00:00
|
|
|
}
|
|
|
|
|
2019-10-16 08:06:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-05-05 13:25:10 +00:00
|
|
|
/** Returns the meta that has the maximum allowable sides of the vine, given the surroundings and current vine meta.
|
|
|
|
Returns special values for a vine that can continue to exist unchanged, or must die completely. */
|
|
|
|
static NIBBLETYPE GetMaxMeta(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_CurrentMeta)
|
2013-07-29 11:13:03 +00:00
|
|
|
{
|
|
|
|
static const struct
|
|
|
|
{
|
|
|
|
int x, z;
|
2014-03-30 21:13:13 +00:00
|
|
|
NIBBLETYPE Bit;
|
2013-07-29 11:13:03 +00:00
|
|
|
} Coords[] =
|
|
|
|
{
|
|
|
|
{ 0, 1, 1}, // south, ZP
|
|
|
|
{-1, 0, 2}, // west, XM
|
|
|
|
{ 0, -1, 4}, // north, ZM
|
|
|
|
{ 1, 0, 8}, // east, XP
|
|
|
|
} ;
|
2021-05-05 13:25:10 +00:00
|
|
|
|
|
|
|
NIBBLETYPE MaxMeta = 0;
|
2017-11-20 11:13:11 +00:00
|
|
|
for (auto & Coord : Coords)
|
2013-07-29 11:13:03 +00:00
|
|
|
{
|
|
|
|
BLOCKTYPE BlockType;
|
|
|
|
NIBBLETYPE BlockMeta;
|
2021-05-05 13:25:10 +00:00
|
|
|
auto checkPos = a_Position.addedXZ(Coord.x, Coord.z);
|
2013-07-29 11:13:03 +00:00
|
|
|
if (
|
2019-10-16 08:06:34 +00:00
|
|
|
a_Chunk.UnboundedRelGetBlock(checkPos.x, checkPos.y, checkPos.z, BlockType, BlockMeta) &&
|
2013-07-29 11:13:03 +00:00
|
|
|
IsBlockAttachable(BlockType)
|
|
|
|
)
|
|
|
|
{
|
2021-05-05 13:25:10 +00:00
|
|
|
MaxMeta |= Coord.Bit;
|
2013-07-29 11:13:03 +00:00
|
|
|
}
|
|
|
|
}
|
2021-05-05 13:25:10 +00:00
|
|
|
|
|
|
|
// Check if vine above us, add its meta to MaxMeta:
|
|
|
|
if ((a_Position.y < cChunkDef::Height - 1) && (a_Chunk.GetBlock(a_Position.addedY(1)) == E_BLOCK_VINES))
|
|
|
|
{
|
|
|
|
MaxMeta |= a_Chunk.GetMeta(a_Position.addedY(1));
|
|
|
|
}
|
|
|
|
|
|
|
|
NIBBLETYPE Common = a_CurrentMeta & MaxMeta; // Neighbors that we have and are legal.
|
|
|
|
if (Common != a_CurrentMeta)
|
|
|
|
{
|
|
|
|
bool HasTop = (a_Position.y < (cChunkDef::Height - 1)) && IsBlockAttachable(a_Chunk.GetBlock(a_Position.addedY(1)));
|
|
|
|
if ((Common == 0) && !HasTop) // Meta equals 0 also means top. Make a last-ditch attempt to save the vine.
|
|
|
|
{
|
|
|
|
return VINE_LOST_SUPPORT;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Common;
|
|
|
|
}
|
|
|
|
|
|
|
|
return VINE_UNCHANGED;
|
2013-07-29 11:13:03 +00:00
|
|
|
}
|
2016-02-05 21:45:45 +00:00
|
|
|
|
2019-10-16 08:06:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-09-20 13:50:52 +00:00
|
|
|
virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos, eBlockFace a_WhichNeighbor) const override
|
2013-07-29 11:13:03 +00:00
|
|
|
{
|
2020-08-01 10:25:06 +00:00
|
|
|
a_ChunkInterface.DoWithChunkAt(a_BlockPos, [&](cChunk & a_Chunk)
|
|
|
|
{
|
|
|
|
|
2021-05-05 13:25:10 +00:00
|
|
|
const auto Position = cChunkDef::AbsoluteToRelative(a_BlockPos);
|
|
|
|
const auto MaxMeta = GetMaxMeta(a_Chunk, Position, a_Chunk.GetMeta(Position));
|
2016-02-05 21:45:45 +00:00
|
|
|
|
2021-05-05 13:25:10 +00:00
|
|
|
if (MaxMeta == VINE_UNCHANGED)
|
2013-07-29 11:13:03 +00:00
|
|
|
{
|
2021-05-05 13:25:10 +00:00
|
|
|
return false;
|
2013-07-29 11:13:03 +00:00
|
|
|
}
|
2016-02-05 21:45:45 +00:00
|
|
|
|
2021-05-05 13:25:10 +00:00
|
|
|
// There is a neighbor missing, need to update the meta or even destroy the block.
|
|
|
|
|
|
|
|
if (MaxMeta == VINE_LOST_SUPPORT)
|
2013-07-29 11:13:03 +00:00
|
|
|
{
|
2021-05-05 13:25:10 +00:00
|
|
|
// The vine just lost all its support, destroy the block:
|
|
|
|
a_Chunk.SetBlock(Position, E_BLOCK_AIR, 0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// It lost some of its support, set it to what remains (SetBlock to notify neighbors):
|
|
|
|
a_Chunk.SetBlock(Position, E_BLOCK_VINES, MaxMeta);
|
2013-07-29 11:13:03 +00:00
|
|
|
}
|
2020-08-01 10:25:06 +00:00
|
|
|
|
|
|
|
return false;
|
|
|
|
});
|
2013-07-29 11:13:03 +00:00
|
|
|
}
|
|
|
|
|
2019-10-16 08:06:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-05-05 13:25:10 +00:00
|
|
|
virtual bool DoesIgnoreBuildCollision(const cWorld & a_World, const cItem & a_HeldItem, const Vector3i a_Position, const NIBBLETYPE a_Meta, const eBlockFace a_ClickedBlockFace, const bool a_ClickedDirectly) const override
|
2013-07-29 11:13:03 +00:00
|
|
|
{
|
2021-05-05 13:25:10 +00:00
|
|
|
return !a_ClickedDirectly || (a_HeldItem.m_ItemType != m_BlockType);
|
2013-07-29 11:13:03 +00:00
|
|
|
}
|
|
|
|
|
2019-10-16 08:06:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-04-17 09:36:37 +00:00
|
|
|
virtual void OnUpdate(
|
|
|
|
cChunkInterface & a_ChunkInterface,
|
|
|
|
cWorldInterface & a_WorldInterface,
|
|
|
|
cBlockPluginInterface & a_PluginInterface,
|
|
|
|
cChunk & a_Chunk,
|
|
|
|
const Vector3i a_RelPos
|
2020-09-20 13:50:52 +00:00
|
|
|
) const override
|
2013-08-24 21:00:24 +00:00
|
|
|
{
|
2014-03-07 18:42:13 +00:00
|
|
|
UNUSED(a_ChunkInterface);
|
|
|
|
UNUSED(a_WorldInterface);
|
|
|
|
|
2014-10-15 17:01:55 +00:00
|
|
|
// Vine cannot grow down if at the bottom:
|
2020-04-17 09:36:37 +00:00
|
|
|
auto GrowPos = a_RelPos.addedY(-1);
|
|
|
|
if (!cChunkDef::IsValidHeight(GrowPos.y))
|
2014-10-15 17:01:55 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Grow one block down, if possible:
|
2014-03-07 18:42:13 +00:00
|
|
|
BLOCKTYPE Block;
|
2020-04-17 09:36:37 +00:00
|
|
|
a_Chunk.UnboundedRelGetBlockType(GrowPos, Block);
|
2014-03-07 18:42:13 +00:00
|
|
|
if (Block == E_BLOCK_AIR)
|
2013-08-24 21:00:24 +00:00
|
|
|
{
|
2020-04-17 09:36:37 +00:00
|
|
|
auto WorldPos = a_Chunk.RelativeToAbsolute(GrowPos);
|
|
|
|
if (!a_PluginInterface.CallHookBlockSpread(WorldPos.x, WorldPos.y, WorldPos.z, ssVineSpread))
|
2014-03-16 15:06:03 +00:00
|
|
|
{
|
2020-04-17 09:36:37 +00:00
|
|
|
a_Chunk.UnboundedRelSetBlock(GrowPos, E_BLOCK_VINES, a_Chunk.GetMeta(a_RelPos));
|
2014-03-16 15:06:03 +00:00
|
|
|
}
|
2013-08-24 21:00:24 +00:00
|
|
|
}
|
|
|
|
}
|
2014-10-15 17:01:55 +00:00
|
|
|
|
2019-10-16 08:06:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-09-20 13:50:52 +00:00
|
|
|
virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) const override
|
2013-07-29 11:13:03 +00:00
|
|
|
{
|
|
|
|
return ((a_Meta >> 1) | (a_Meta << 3)) & 0x0f; // Rotate bits to the right
|
|
|
|
}
|
|
|
|
|
2019-10-16 08:06:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-09-20 13:50:52 +00:00
|
|
|
virtual NIBBLETYPE MetaRotateCW(NIBBLETYPE a_Meta) const override
|
2013-07-29 11:13:03 +00:00
|
|
|
{
|
|
|
|
return ((a_Meta << 1) | (a_Meta >> 3)) & 0x0f; // Rotate bits to the left
|
|
|
|
}
|
2014-03-02 12:02:29 +00:00
|
|
|
|
2019-10-16 08:06:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-09-20 13:50:52 +00:00
|
|
|
virtual NIBBLETYPE MetaMirrorXY(NIBBLETYPE a_Meta) const override
|
2013-07-29 11:13:03 +00:00
|
|
|
{
|
|
|
|
// Bits 2 and 4 stay, bits 1 and 3 swap
|
2015-07-29 15:04:03 +00:00
|
|
|
return static_cast<NIBBLETYPE>((a_Meta & 0x0a) | ((a_Meta & 0x01) << 2) | ((a_Meta & 0x04) >> 2));
|
2013-07-29 11:13:03 +00:00
|
|
|
}
|
|
|
|
|
2019-10-16 08:06:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-09-20 13:50:52 +00:00
|
|
|
virtual NIBBLETYPE MetaMirrorYZ(NIBBLETYPE a_Meta) const override
|
2013-07-29 11:13:03 +00:00
|
|
|
{
|
|
|
|
// Bits 1 and 3 stay, bits 2 and 4 swap
|
2015-07-29 15:04:03 +00:00
|
|
|
return static_cast<NIBBLETYPE>((a_Meta & 0x05) | ((a_Meta & 0x02) << 2) | ((a_Meta & 0x08) >> 2));
|
2013-07-29 11:13:03 +00:00
|
|
|
}
|
|
|
|
|
2019-10-16 08:06:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-09-20 13:50:52 +00:00
|
|
|
virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override
|
2015-06-30 14:50:15 +00:00
|
|
|
{
|
|
|
|
UNUSED(a_Meta);
|
|
|
|
return 7;
|
|
|
|
}
|
2013-07-29 11:13:03 +00:00
|
|
|
} ;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|