1
0

BigFlower fixes (#3826)

* BigFlowers fixes

* Correct upper part meta
* Documented parameters to DoesIgnoreBuildCollision
This commit is contained in:
peterbell10 2017-07-07 15:37:53 +01:00 committed by Lukas Pioch
parent 885d828712
commit bbf5bec817
20 changed files with 78 additions and 50 deletions

View File

@ -15493,6 +15493,10 @@ end
{
Notes = "The player has swapped their held item with the item in their offhand slot (1.9)",
},
E_META_BIG_FLOWER_TOP =
{
Notes = "The metadata of a big flower block that indicates it is the top block.",
},
E_META_CONCRETE_BLACK =
{
Notes = "A flag in the metadata of concete that indicates that the concrete is black.",

View File

@ -552,6 +552,8 @@ enum ENUM_BLOCK_META : NIBBLETYPE
E_META_BIG_FLOWER_LARGE_FERN = 3,
E_META_BIG_FLOWER_ROSE_BUSH = 4,
E_META_BIG_FLOWER_PEONY = 5,
// 0x8 is supposedly a bit flag but all vanilla plants have this value
E_META_BIG_FLOWER_TOP = 10,
// E_BLOCK_BREWING_STAND metas
E_META_BREWING_STAND_FILLED_SLOT_XP = 1,

View File

@ -18,19 +18,39 @@ public:
{
}
virtual bool DoesIgnoreBuildCollision(cPlayer * a_Player, NIBBLETYPE a_Meta) override
virtual bool DoesIgnoreBuildCollision(cChunkInterface & a_ChunkInterface, Vector3i a_Pos, cPlayer & a_Player, NIBBLETYPE a_Meta) override
{
return (((a_Meta & E_META_BIG_FLOWER_DOUBLE_TALL_GRASS) != 0) || (a_Meta & E_META_BIG_FLOWER_LARGE_FERN) != 0);
if (IsMetaTopPart(a_Meta))
{
BLOCKTYPE BottomType;
if (
(a_Pos.y < 1) ||
!a_ChunkInterface.GetBlockTypeMeta(a_Pos.x, a_Pos.y - 1, a_Pos.z, BottomType, a_Meta) ||
(BottomType != E_BLOCK_BIG_FLOWER)
)
{
// Can't find the flower meta so assume grass
return true;
}
}
NIBBLETYPE FlowerMeta = a_Meta & 0x07;
return (
(FlowerMeta == E_META_BIG_FLOWER_DOUBLE_TALL_GRASS) ||
(FlowerMeta == E_META_BIG_FLOWER_LARGE_FERN)
);
}
virtual void DropBlock(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_BlockPluginInterface, cEntity * a_Digger, int a_BlockX, int a_BlockY, int a_BlockZ, bool a_CanDrop) override
{
NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
int AlternateY = a_BlockY;
int BottomY = a_BlockY;
if (Meta & 0x8)
{
--AlternateY;
--BottomY;
}
else
{
@ -39,13 +59,18 @@ public:
// also destroy the other block if it has a valid height and is a big flower
if (cChunkDef::IsValidHeight(AlternateY) && a_ChunkInterface.GetBlock(a_BlockX, AlternateY, a_BlockZ) == E_BLOCK_BIG_FLOWER)
{
super::DropBlock(a_ChunkInterface, a_WorldInterface, a_BlockPluginInterface, a_Digger, a_BlockX, a_BlockY, a_BlockZ, a_CanDrop);
super::DropBlock(a_ChunkInterface, a_WorldInterface, a_BlockPluginInterface, a_Digger, a_BlockX, BottomY, a_BlockZ, a_CanDrop);
a_ChunkInterface.FastSetBlock(a_BlockX, AlternateY, a_BlockZ, E_BLOCK_AIR, 0);
}
}
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
if (IsMetaTopPart(a_BlockMeta))
{
return; // No way to tell flower type
}
NIBBLETYPE Meta = a_BlockMeta & 0x7;
if (Meta == E_META_BIG_FLOWER_DOUBLE_TALL_GRASS)
{

View File

@ -17,7 +17,7 @@ public:
{
}
virtual bool DoesIgnoreBuildCollision(void) override
virtual bool DoesIgnoreBuildCollision(cChunkInterface & a_ChunkInterface, Vector3i a_Pos, cPlayer & a_Player, NIBBLETYPE a_Meta) override
{
return true;
}

View File

@ -232,7 +232,7 @@ public:
return (FoundFrameZP && FoundFrameZM);
}
virtual bool DoesIgnoreBuildCollision(cPlayer * a_Player, NIBBLETYPE a_Meta) override
virtual bool DoesIgnoreBuildCollision(cChunkInterface & a_ChunkInterface, Vector3i a_Pos, cPlayer & a_Player, NIBBLETYPE a_Meta) override
{
return true;
}

View File

@ -24,7 +24,7 @@ public:
// No pickups
}
virtual bool DoesIgnoreBuildCollision(void) override
virtual bool DoesIgnoreBuildCollision(cChunkInterface & a_ChunkInterface, Vector3i a_Pos, cPlayer & a_Player, NIBBLETYPE a_Meta) override
{
return true;
}

View File

@ -582,7 +582,7 @@ bool cBlockHandler::IsClickedThrough(void)
bool cBlockHandler::DoesIgnoreBuildCollision(void)
bool cBlockHandler::DoesIgnoreBuildCollision(cChunkInterface & a_ChunkInterface, Vector3i a_Pos, cPlayer & a_Player, NIBBLETYPE a_Meta)
{
return (m_BlockType == E_BLOCK_AIR);
}

View File

@ -114,16 +114,11 @@ public:
/** Checks if the player can build "inside" this block.
For example blocks placed "on" snow will be placed at the same position. So: Snow ignores Build collision
@param a_Pos Position of the block
@param a_Player Player trying to build on the block
@param a_Meta Meta value of the block currently at a_Pos
*/
virtual bool DoesIgnoreBuildCollision(void);
/** Similar to DoesIgnoreBuildCollision(void), but is used for cases where block's meta or
player's item-in-hand is needed to determine collision (thin snow) */
virtual bool DoesIgnoreBuildCollision(cPlayer *, NIBBLETYPE a_Meta)
{
UNUSED(a_Meta);
return DoesIgnoreBuildCollision();
}
virtual bool DoesIgnoreBuildCollision(cChunkInterface & ChunkInterface, Vector3i a_Pos, cPlayer & a_Player, NIBBLETYPE a_Meta);
/** Returns if this block drops if it gets destroyed by an unsuitable situation.
Default: true */

View File

@ -41,9 +41,9 @@ public:
return true;
}
virtual bool DoesIgnoreBuildCollision(cPlayer * a_Player, NIBBLETYPE a_Meta) override
virtual bool DoesIgnoreBuildCollision(cChunkInterface & a_ChunkInterface, Vector3i a_Pos, cPlayer & a_Player, NIBBLETYPE a_Meta) override
{
if ((a_Player->GetEquippedItem().m_ItemType == E_BLOCK_SNOW) && (a_Meta < 7))
if ((a_Player.GetEquippedItem().m_ItemType == E_BLOCK_SNOW) && (a_Meta < 7))
{
return true; // If a player is holding a (thin) snow block and it's size can be increased, return collision ignored
}

View File

@ -18,7 +18,7 @@ public:
{
}
virtual bool DoesIgnoreBuildCollision(void) override
virtual bool DoesIgnoreBuildCollision(cChunkInterface & a_ChunkInterface, Vector3i a_Pos, cPlayer & a_Player, NIBBLETYPE a_Meta) override
{
return true;
}

View File

@ -163,7 +163,7 @@ public:
}
}
virtual bool DoesIgnoreBuildCollision(void) override
virtual bool DoesIgnoreBuildCollision(cChunkInterface & a_ChunkInterface, Vector3i a_Pos, cPlayer & a_Player, NIBBLETYPE a_Meta) override
{
return true;
}

View File

@ -1184,7 +1184,7 @@ bool cChunk::GrowTallGrass(int a_RelX, int a_RelY, int a_RelZ)
default: return false;
}
return UnboundedRelFastSetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_BIG_FLOWER, LargeFlowerMeta) &&
UnboundedRelFastSetBlock(a_RelX, a_RelY + 1, a_RelZ, E_BLOCK_BIG_FLOWER, 0x8 | LargeFlowerMeta);
UnboundedRelFastSetBlock(a_RelX, a_RelY + 1, a_RelZ, E_BLOCK_BIG_FLOWER, E_META_BIG_FLOWER_TOP);
}

View File

@ -260,7 +260,7 @@ void cFinishGenClumpTopBlock::TryPlaceFoliageClump(cChunkDesc & a_ChunkDesc, int
a_ChunkDesc.SetBlockTypeMeta(x, Top + 1, z, a_BlockType, a_BlockMeta);
if (a_IsDoubleTall)
{
a_ChunkDesc.SetBlockTypeMeta(x, Top + 2, z, E_BLOCK_BIG_FLOWER, 0x8 | a_BlockMeta);
a_ChunkDesc.SetBlockTypeMeta(x, Top + 2, z, E_BLOCK_BIG_FLOWER, E_META_BIG_FLOWER_TOP);
a_ChunkDesc.SetHeight(x, z, static_cast<HEIGHTTYPE>(Top + 2));
}
else
@ -554,7 +554,7 @@ void cFinishGenTallGrass::GenFinish(cChunkDesc & a_ChunkDesc)
{
NIBBLETYPE Meta = (m_Noise.IntNoise2DInt(xx * 100, zz * 100) / 7 % 100) > 25 ? 2 : 3;
a_ChunkDesc.SetBlockTypeMeta(x, y, z, E_BLOCK_BIG_FLOWER, Meta);
a_ChunkDesc.SetBlockTypeMeta(x, y + 1, z, E_BLOCK_BIG_FLOWER, 0x8 | Meta);
a_ChunkDesc.SetBlockTypeMeta(x, y + 1, z, E_BLOCK_BIG_FLOWER, E_META_BIG_FLOWER_TOP);
a_ChunkDesc.SetHeight(x, z, static_cast<HEIGHTTYPE>(y + 1));
}
}

View File

@ -34,17 +34,30 @@ public:
sSetBlockVector & a_BlocksToSet
) override
{
// Can only be placed on the floor:
if ((a_BlockY < 0) || (a_World.GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ) == E_BLOCK_AIR))
// Can only be placed on dirt:
if ((a_BlockY <= 0) || !IsBlockTypeOfDirt(a_World.GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ)))
{
return false;
}
a_BlocksToSet.emplace_back(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_BIG_FLOWER, a_EquippedItem.m_ItemDamage & 0x07);
if (a_BlockY < cChunkDef::Height - 1)
// Needs at least two free blocks to build in
if (a_BlockY >= cChunkDef::Height - 1)
{
a_BlocksToSet.emplace_back(a_BlockX, a_BlockY + 1, a_BlockZ, E_BLOCK_BIG_FLOWER, (a_EquippedItem.m_ItemDamage & 0x07) | 0x08);
return false;
}
BLOCKTYPE TopType;
NIBBLETYPE TopMeta;
a_World.GetBlockTypeMeta(a_BlockX, a_BlockY + 1, a_BlockZ, TopType, TopMeta);
cChunkInterface ChunkInterface(a_World.GetChunkMap());
if (!BlockHandler(TopType)->DoesIgnoreBuildCollision(ChunkInterface, { a_BlockX, a_BlockY + 1, a_BlockZ }, a_Player, TopMeta))
{
return false;
}
a_BlocksToSet.emplace_back(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_BIG_FLOWER, a_EquippedItem.m_ItemDamage & 0x07);
a_BlocksToSet.emplace_back(a_BlockX, a_BlockY + 1, a_BlockZ, E_BLOCK_BIG_FLOWER, E_META_BIG_FLOWER_TOP);
return true;
}
};

View File

@ -51,12 +51,9 @@ public:
BLOCKTYPE ClickedBlock;
NIBBLETYPE ClickedBlockMeta;
a_World.GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, ClickedBlock, ClickedBlockMeta);
if (
BlockHandler(ClickedBlock)->DoesIgnoreBuildCollision() ||
BlockHandler(ClickedBlock)->DoesIgnoreBuildCollision(&a_Player, ClickedBlockMeta)
)
cChunkInterface ChunkInterface(a_World.GetChunkMap());
if (BlockHandler(ClickedBlock)->DoesIgnoreBuildCollision(ChunkInterface, { a_BlockX, a_BlockY, a_BlockZ }, a_Player, ClickedBlockMeta))
{
cChunkInterface ChunkInterface(a_World.GetChunkMap());
BlockHandler(ClickedBlock)->OnDestroyedByPlayer(ChunkInterface, a_World, &a_Player, a_BlockX, a_BlockY, a_BlockZ);
}
else
@ -75,10 +72,7 @@ public:
// Clicked on side of block, make sure that placement won't be cancelled if there is a slab able to be double slabbed.
// No need to do combinability (dblslab) checks, client will do that here.
if (
!BlockHandler(PlaceBlock)->DoesIgnoreBuildCollision() &&
!BlockHandler(PlaceBlock)->DoesIgnoreBuildCollision(&a_Player, PlaceMeta)
)
if (BlockHandler(ClickedBlock)->DoesIgnoreBuildCollision(ChunkInterface, { a_BlockX, a_BlockY, a_BlockZ }, a_Player, ClickedBlockMeta))
{
// Tried to place a block into another?
// Happens when you place a block aiming at side of block with a torch on it or stem beside it

View File

@ -357,14 +357,11 @@ bool cItemHandler::OnPlayerPlace(
NIBBLETYPE ClickedBlockMeta;
a_World.GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, ClickedBlock, ClickedBlockMeta);
cChunkInterface ChunkInterface(a_World.GetChunkMap());
// Check if the block ignores build collision (water, grass etc.):
if (
BlockHandler(ClickedBlock)->DoesIgnoreBuildCollision() ||
BlockHandler(ClickedBlock)->DoesIgnoreBuildCollision(&a_Player, ClickedBlockMeta)
)
if (BlockHandler(ClickedBlock)->DoesIgnoreBuildCollision(ChunkInterface, { a_BlockX, a_BlockY, a_BlockZ }, a_Player, ClickedBlockMeta))
{
cChunkInterface ChunkInterface(a_World.GetChunkMap());
BlockHandler(ClickedBlock)->OnDestroyedByPlayer(ChunkInterface, a_World, &a_Player, a_BlockX, a_BlockY, a_BlockZ);
}
else
@ -383,10 +380,7 @@ bool cItemHandler::OnPlayerPlace(
// Clicked on side of block, make sure that placement won't be cancelled if there is a slab able to be double slabbed.
// No need to do combinability (dblslab) checks, client will do that here.
if (
!BlockHandler(PlaceBlock)->DoesIgnoreBuildCollision() &&
!BlockHandler(PlaceBlock)->DoesIgnoreBuildCollision(&a_Player, PlaceMeta)
)
if (!BlockHandler(PlaceBlock)->DoesIgnoreBuildCollision(ChunkInterface, { a_BlockX, a_BlockY, a_BlockZ }, a_Player, PlaceMeta))
{
// Tried to place a block into another?
// Happens when you place a block aiming at side of block with a torch on it or stem beside it

View File

@ -32,7 +32,8 @@ public:
BLOCKTYPE ClickedBlock;
NIBBLETYPE ClickedBlockMeta;
a_World.GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, ClickedBlock, ClickedBlockMeta);
bool isReplacingClickedBlock = BlockHandler(ClickedBlock)->DoesIgnoreBuildCollision() || BlockHandler(ClickedBlock)->DoesIgnoreBuildCollision(&a_Player, ClickedBlockMeta);
cChunkInterface ChunkInterface(a_World.GetChunkMap());
bool isReplacingClickedBlock = BlockHandler(ClickedBlock)->DoesIgnoreBuildCollision(ChunkInterface, { a_BlockX, a_BlockY, a_BlockZ }, a_Player, ClickedBlockMeta);
// If the regular placement doesn't work, do no further processing:
if (!super::OnPlayerPlace(a_World, a_Player, a_EquippedItem, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ))

View File

@ -222,7 +222,7 @@ bool cBlockHandler::IsClickedThrough(void)
bool cBlockHandler::DoesIgnoreBuildCollision(void)
bool cBlockHandler::DoesIgnoreBuildCollision(cChunkInterface & a_ChunkInterface, Vector3i a_Pos, cPlayer & a_Player, NIBBLETYPE a_Meta)
{
return (m_BlockType == E_BLOCK_AIR);
}

View File

@ -222,7 +222,7 @@ bool cBlockHandler::IsClickedThrough(void)
bool cBlockHandler::DoesIgnoreBuildCollision(void)
bool cBlockHandler::DoesIgnoreBuildCollision(cChunkInterface & a_ChunkInterface, Vector3i a_Pos, cPlayer & a_Player, NIBBLETYPE a_Meta)
{
return (m_BlockType == E_BLOCK_AIR);
}

View File

@ -150,7 +150,7 @@ bool cBlockHandler::IsClickedThrough(void)
bool cBlockHandler::DoesIgnoreBuildCollision(void)
bool cBlockHandler::DoesIgnoreBuildCollision(cChunkInterface & a_ChunkInterface, Vector3i a_Pos, cPlayer & a_Player, NIBBLETYPE a_Meta)
{
return (m_BlockType == E_BLOCK_AIR);
}