mirror of
https://github.com/cuberite/cuberite.git
synced 2025-01-05 10:27:10 +08:00
Fix cChunkMap issues below with coords below y=0 (#5397)
* return false in cChunkMap::GetBlockTypeMeta if requested height is invalid * add checks to users of cWorld::GetBlockTypeMeta * add checks for invalid height to cChunkMap::GetBlock and cChunkMap::GetBlockMeta * add hle0 to CONTRIBUTORS * Fix merge conflict with isValidHeight * Add initialisation contract and fulfil it. --------- Co-authored-by: Alexander Harkness <me@bearbin.net>
This commit is contained in:
parent
8ca73f1929
commit
33b9c5dc6d
@ -48,8 +48,12 @@ void cBlockPistonHandler::ExtendPiston(Vector3i a_BlockPos, cWorld & a_World)
|
||||
|
||||
BLOCKTYPE pistonBlock;
|
||||
NIBBLETYPE pistonMeta;
|
||||
a_World.GetBlockTypeMeta(a_BlockPos, pistonBlock, pistonMeta);
|
||||
a_World.BroadcastBlockAction(a_BlockPos, PistonExtendAction, pistonMeta, pistonBlock);
|
||||
if (a_World.GetBlockTypeMeta(a_BlockPos, pistonBlock, pistonMeta))
|
||||
{
|
||||
a_World.BroadcastBlockAction(
|
||||
a_BlockPos, PistonExtendAction, pistonMeta, pistonBlock
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Client expects the server to "play" the animation before setting the final blocks
|
||||
@ -60,9 +64,12 @@ void cBlockPistonHandler::ExtendPiston(Vector3i a_BlockPos, cWorld & a_World)
|
||||
{
|
||||
BLOCKTYPE pistonBlock;
|
||||
NIBBLETYPE pistonMeta;
|
||||
World.GetBlockTypeMeta(a_BlockPos, pistonBlock, pistonMeta);
|
||||
|
||||
if ((pistonBlock != E_BLOCK_PISTON) && !IsSticky(pistonBlock))
|
||||
|
||||
if (
|
||||
!World.GetBlockTypeMeta(a_BlockPos, pistonBlock, pistonMeta) ||
|
||||
((pistonBlock != E_BLOCK_PISTON) && !IsSticky(pistonBlock))
|
||||
)
|
||||
{
|
||||
// Ensure we operate on a piston to avoid spurious behaviour
|
||||
// Note that the scheduled task may result in the block type of a_BlockPos changing
|
||||
@ -104,17 +111,23 @@ void cBlockPistonHandler::RetractPiston(Vector3i a_BlockPos, cWorld & a_World)
|
||||
{
|
||||
BLOCKTYPE pistonBlock;
|
||||
NIBBLETYPE pistonMeta;
|
||||
a_World.GetBlockTypeMeta(a_BlockPos, pistonBlock, pistonMeta);
|
||||
a_World.BroadcastBlockAction(a_BlockPos, PistonRetractAction, pistonMeta, pistonBlock);
|
||||
if (a_World.GetBlockTypeMeta(a_BlockPos, pistonBlock, pistonMeta))
|
||||
{
|
||||
a_World.BroadcastBlockAction(
|
||||
a_BlockPos, PistonRetractAction, pistonMeta, pistonBlock
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
a_World.ScheduleTask(1_tick, [a_BlockPos](cWorld & World)
|
||||
{
|
||||
BLOCKTYPE pistonBlock;
|
||||
NIBBLETYPE pistonMeta;
|
||||
World.GetBlockTypeMeta(a_BlockPos, pistonBlock, pistonMeta);
|
||||
|
||||
if ((pistonBlock != E_BLOCK_PISTON) && !IsSticky(pistonBlock))
|
||||
if (
|
||||
!World.GetBlockTypeMeta(a_BlockPos, pistonBlock, pistonMeta) ||
|
||||
((pistonBlock != E_BLOCK_PISTON) && !IsSticky(pistonBlock))
|
||||
)
|
||||
{
|
||||
// Ensure we operate on a piston to avoid spurious behaviour
|
||||
// Note that the scheduled task may result in the block type of a_BlockPos changing
|
||||
@ -189,19 +202,20 @@ void cBlockPistonHandler::PushBlocks(
|
||||
NIBBLETYPE moveMeta;
|
||||
for (auto & moveBlockPos : sortedBlocks)
|
||||
{
|
||||
a_World.GetBlockTypeMeta(moveBlockPos, moveBlock, moveMeta);
|
||||
|
||||
if (cBlockInfo::IsPistonBreakable(moveBlock))
|
||||
if (a_World.GetBlockTypeMeta(moveBlockPos, moveBlock, moveMeta))
|
||||
{
|
||||
// Block is breakable, drop it:
|
||||
a_World.DropBlockAsPickups(moveBlockPos, nullptr, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not breakable, just move it
|
||||
a_World.SetBlock(moveBlockPos, E_BLOCK_AIR, 0);
|
||||
moveBlockPos += a_PushDir;
|
||||
a_World.SetBlock(moveBlockPos, moveBlock, moveMeta);
|
||||
if (cBlockInfo::IsPistonBreakable(moveBlock))
|
||||
{
|
||||
// Block is breakable, drop it:
|
||||
a_World.DropBlockAsPickups(moveBlockPos, nullptr, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not breakable, just move it
|
||||
a_World.SetBlock(moveBlockPos, E_BLOCK_AIR, 0);
|
||||
moveBlockPos += a_PushDir;
|
||||
a_World.SetBlock(moveBlockPos, moveBlock, moveMeta);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -232,7 +246,10 @@ bool cBlockPistonHandler::CanPushBlock(
|
||||
|
||||
BLOCKTYPE currBlock;
|
||||
NIBBLETYPE currMeta;
|
||||
a_World.GetBlockTypeMeta(a_BlockPos, currBlock, currMeta);
|
||||
if (!a_World.GetBlockTypeMeta(a_BlockPos, currBlock, currMeta))
|
||||
{
|
||||
return !a_RequirePushable;
|
||||
}
|
||||
|
||||
if (currBlock == E_BLOCK_AIR)
|
||||
{
|
||||
|
@ -474,6 +474,11 @@ void cChunkMap::CollectPickupsByEntity(cEntity & a_Entity)
|
||||
|
||||
BLOCKTYPE cChunkMap::GetBlock(Vector3i a_BlockPos) const
|
||||
{
|
||||
if (!cChunkDef::IsValidHeight(a_BlockPos))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto chunkPos = cChunkDef::BlockToChunk(a_BlockPos);
|
||||
auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkPos);
|
||||
|
||||
@ -493,6 +498,11 @@ BLOCKTYPE cChunkMap::GetBlock(Vector3i a_BlockPos) const
|
||||
|
||||
NIBBLETYPE cChunkMap::GetBlockMeta(Vector3i a_BlockPos) const
|
||||
{
|
||||
if (!cChunkDef::IsValidHeight(a_BlockPos))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto chunkPos = cChunkDef::BlockToChunk(a_BlockPos);
|
||||
auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkPos);
|
||||
|
||||
@ -585,6 +595,14 @@ void cChunkMap::SetBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE
|
||||
|
||||
bool cChunkMap::GetBlockTypeMeta(Vector3i a_BlockPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const
|
||||
{
|
||||
if (!cChunkDef::IsValidHeight(a_BlockPos))
|
||||
{
|
||||
// Initialise the params to fulfil our contract.
|
||||
a_BlockType = 0;
|
||||
a_BlockMeta = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto chunkCoord = cChunkDef::BlockToChunk(a_BlockPos);
|
||||
auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkCoord);
|
||||
|
||||
@ -595,6 +613,10 @@ bool cChunkMap::GetBlockTypeMeta(Vector3i a_BlockPos, BLOCKTYPE & a_BlockType, N
|
||||
Chunk->GetBlockTypeMeta(relPos, a_BlockType, a_BlockMeta);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Initialise the params to fulfil our contract.
|
||||
a_BlockType = 0;
|
||||
a_BlockMeta = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -115,6 +115,10 @@ public:
|
||||
void SetBlockMeta(Vector3i a_BlockPos, NIBBLETYPE a_BlockMeta);
|
||||
|
||||
void SetBlock (Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
|
||||
/** Get the block type and meta at the specified coords
|
||||
Will always initialise a_BlockType and a_BlockMeta if called.
|
||||
Returns false if the data could not be retrieved, either because the chunk is invalid or the height is invalid.
|
||||
Otherwise, returns true. */
|
||||
bool GetBlockTypeMeta (Vector3i a_BlockPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const;
|
||||
bool GetBlockInfo (Vector3i, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_Meta, NIBBLETYPE & a_SkyLight, NIBBLETYPE & a_BlockLight) const;
|
||||
|
||||
|
@ -1254,7 +1254,10 @@ void cClientHandle::HandleBlockDigStarted(Vector3i a_BlockPos, eBlockFace a_Bloc
|
||||
|
||||
BLOCKTYPE DiggingBlock;
|
||||
NIBBLETYPE DiggingMeta;
|
||||
m_Player->GetWorld()->GetBlockTypeMeta(a_BlockPos, DiggingBlock, DiggingMeta);
|
||||
if (!m_Player->GetWorld()->GetBlockTypeMeta(a_BlockPos, DiggingBlock, DiggingMeta))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
m_Player->IsGameModeCreative() &&
|
||||
@ -1322,7 +1325,10 @@ void cClientHandle::HandleBlockDigFinished(Vector3i a_BlockPos, eBlockFace a_Blo
|
||||
|
||||
BLOCKTYPE DugBlock;
|
||||
NIBBLETYPE DugMeta;
|
||||
m_Player->GetWorld()->GetBlockTypeMeta(a_BlockPos, DugBlock, DugMeta);
|
||||
if (!m_Player->GetWorld()->GetBlockTypeMeta(a_BlockPos, DugBlock, DugMeta))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_Player->IsGameModeCreative())
|
||||
{
|
||||
|
@ -2594,9 +2594,10 @@ bool cPlayer::IsInsideWater()
|
||||
|
||||
BLOCKTYPE Block;
|
||||
NIBBLETYPE Meta;
|
||||
m_World->GetBlockTypeMeta(EyePos, Block, Meta);
|
||||
|
||||
if ((Block != E_BLOCK_WATER) && (Block != E_BLOCK_STATIONARY_WATER))
|
||||
if (
|
||||
!m_World->GetBlockTypeMeta(GetEyePosition().Floor(), Block, Meta) ||
|
||||
((Block != E_BLOCK_WATER) && (Block != E_BLOCK_STATIONARY_WATER))
|
||||
)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -27,7 +27,10 @@ public:
|
||||
auto & World = *a_Player.GetWorld();
|
||||
BLOCKTYPE HeadType;
|
||||
NIBBLETYPE HeadMeta;
|
||||
World.GetBlockTypeMeta(HeadPosition, HeadType, HeadMeta);
|
||||
if (!World.GetBlockTypeMeta(HeadPosition, HeadType, HeadMeta))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Vanilla only allows beds to be placed into air.
|
||||
// Check if there is empty space for the "head" block:
|
||||
|
@ -29,7 +29,10 @@ public:
|
||||
const auto TopPos = a_PlacePosition.addedY(1);
|
||||
BLOCKTYPE TopType;
|
||||
NIBBLETYPE TopMeta;
|
||||
World.GetBlockTypeMeta(TopPos, TopType, TopMeta);
|
||||
if (!World.GetBlockTypeMeta(TopPos, TopType, TopMeta))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!cBlockHandler::For(TopType).DoesIgnoreBuildCollision(World, a_HeldItem, TopPos, TopMeta, a_ClickedBlockFace, false))
|
||||
{
|
||||
|
@ -54,7 +54,10 @@ public:
|
||||
{
|
||||
BLOCKTYPE TopType;
|
||||
NIBBLETYPE TopMeta;
|
||||
World.GetBlockTypeMeta(UpperBlockPosition, TopType, TopMeta);
|
||||
if (!World.GetBlockTypeMeta(UpperBlockPosition, TopType, TopMeta))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!cBlockHandler::For(TopType).DoesIgnoreBuildCollision(World, a_HeldItem, UpperBlockPosition, TopMeta, a_ClickedBlockFace, false))
|
||||
{
|
||||
|
@ -54,10 +54,12 @@ public:
|
||||
// Cocoa (brown dye) can be planted on jungle logs:
|
||||
BLOCKTYPE BlockType;
|
||||
NIBBLETYPE BlockMeta;
|
||||
a_World->GetBlockTypeMeta(a_ClickedBlockPos, BlockType, BlockMeta);
|
||||
|
||||
// Check if the block that the player clicked is a jungle log.
|
||||
if ((BlockType != E_BLOCK_LOG) || ((BlockMeta & 0x03) != E_META_LOG_JUNGLE))
|
||||
if (
|
||||
!a_World->GetBlockTypeMeta(a_ClickedBlockPos, BlockType, BlockMeta) ||
|
||||
((BlockType != E_BLOCK_LOG) || ((BlockMeta & 0x03) != E_META_LOG_JUNGLE))
|
||||
)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -35,8 +35,8 @@ public:
|
||||
{
|
||||
BLOCKTYPE FacingBlock;
|
||||
NIBBLETYPE FacingMeta;
|
||||
a_World->GetBlockTypeMeta(a_ClickedBlockPos, FacingBlock, FacingMeta);
|
||||
if (FacingBlock == E_BLOCK_END_PORTAL_FRAME)
|
||||
|
||||
if (a_World->GetBlockTypeMeta(a_ClickedBlockPos, FacingBlock, FacingMeta) && (FacingBlock == E_BLOCK_END_PORTAL_FRAME))
|
||||
{
|
||||
// Fill the portal frame. E_META_END_PORTAL_EYE is the bit for holding the eye of ender.
|
||||
if ((FacingMeta & E_META_END_PORTAL_FRAME_EYE) != E_META_END_PORTAL_FRAME_EYE)
|
||||
|
@ -46,7 +46,10 @@ public:
|
||||
// Can only transform dirt or grass blocks:
|
||||
BLOCKTYPE BlockType;
|
||||
NIBBLETYPE BlockMeta;
|
||||
a_World->GetBlockTypeMeta(a_ClickedBlockPos, BlockType, BlockMeta);
|
||||
if (!a_World->GetBlockTypeMeta(a_ClickedBlockPos, BlockType, BlockMeta))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if ((BlockType != E_BLOCK_DIRT) && (BlockType != E_BLOCK_GRASS))
|
||||
{
|
||||
return false;
|
||||
|
@ -32,7 +32,10 @@ public:
|
||||
{
|
||||
BLOCKTYPE Block;
|
||||
NIBBLETYPE BlockMeta;
|
||||
a_World->GetBlockTypeMeta(a_ClickedBlockPos, Block, BlockMeta);
|
||||
if (!a_World->GetBlockTypeMeta(a_ClickedBlockPos, Block, BlockMeta))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((Block == E_BLOCK_LEAVES) || (Block == E_BLOCK_NEW_LEAVES))
|
||||
{
|
||||
|
@ -1065,9 +1065,12 @@ void cSlotAreaAnvil::OnTakeResult(cPlayer & a_Player)
|
||||
|
||||
BLOCKTYPE Block;
|
||||
NIBBLETYPE BlockMeta;
|
||||
a_Player.GetWorld()->GetBlockTypeMeta(BlockPos, Block, BlockMeta);
|
||||
|
||||
if (!a_Player.IsGameModeCreative() && (Block == E_BLOCK_ANVIL) && GetRandomProvider().RandBool(0.12))
|
||||
if (
|
||||
a_Player.GetWorld()->GetBlockTypeMeta(BlockPos, Block, BlockMeta) &&
|
||||
!a_Player.IsGameModeCreative() && (Block == E_BLOCK_ANVIL) &&
|
||||
GetRandomProvider().RandBool(0.12)
|
||||
)
|
||||
{
|
||||
NIBBLETYPE Orientation = BlockMeta & 0x3;
|
||||
NIBBLETYPE AnvilDamage = BlockMeta >> 2;
|
||||
|
@ -1539,8 +1539,7 @@ bool cWorld::GetLargeTreeAdjustment(Vector3i & a_BlockPos, NIBBLETYPE a_Meta)
|
||||
{
|
||||
NIBBLETYPE meta;
|
||||
BLOCKTYPE type;
|
||||
GetBlockTypeMeta(a_BlockPos.addedXZ(x, z), type, meta);
|
||||
IsLarge = IsLarge && (type == E_BLOCK_SAPLING) && ((meta & 0x07) == a_Meta);
|
||||
IsLarge = IsLarge && GetBlockTypeMeta(a_BlockPos.addedXZ(x, z), type, meta) && (type == E_BLOCK_SAPLING) && ((meta & 0x07) == a_Meta);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1557,8 +1556,7 @@ bool cWorld::GetLargeTreeAdjustment(Vector3i & a_BlockPos, NIBBLETYPE a_Meta)
|
||||
{
|
||||
NIBBLETYPE meta;
|
||||
BLOCKTYPE type;
|
||||
GetBlockTypeMeta(a_BlockPos.addedXZ(x, z), type, meta);
|
||||
IsLarge = IsLarge && (type == E_BLOCK_SAPLING) && ((meta & 0x07) == a_Meta);
|
||||
IsLarge = IsLarge && GetBlockTypeMeta(a_BlockPos.addedXZ(x, z), type, meta) && (type == E_BLOCK_SAPLING) && ((meta & 0x07) == a_Meta);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1576,8 +1574,7 @@ bool cWorld::GetLargeTreeAdjustment(Vector3i & a_BlockPos, NIBBLETYPE a_Meta)
|
||||
{
|
||||
NIBBLETYPE meta;
|
||||
BLOCKTYPE type;
|
||||
GetBlockTypeMeta(a_BlockPos.addedXZ(x, z), type, meta);
|
||||
IsLarge = IsLarge && (type == E_BLOCK_SAPLING) && ((meta & 0x07) == a_Meta);
|
||||
IsLarge = IsLarge && GetBlockTypeMeta(a_BlockPos.addedXZ(x, z), type, meta) && (type == E_BLOCK_SAPLING) && ((meta & 0x07) == a_Meta);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1596,8 +1593,7 @@ bool cWorld::GetLargeTreeAdjustment(Vector3i & a_BlockPos, NIBBLETYPE a_Meta)
|
||||
{
|
||||
NIBBLETYPE meta;
|
||||
BLOCKTYPE type;
|
||||
GetBlockTypeMeta(a_BlockPos.addedXZ(x, z), type, meta);
|
||||
IsLarge = IsLarge && (type == E_BLOCK_SAPLING) && ((meta & 0x07) == a_Meta);
|
||||
IsLarge = IsLarge && GetBlockTypeMeta(a_BlockPos.addedXZ(x, z), type, meta) && (type == E_BLOCK_SAPLING) && ((meta & 0x07) == a_Meta);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2044,7 +2040,10 @@ void cWorld::PlaceBlock(const Vector3i a_Position, const BLOCKTYPE a_BlockType,
|
||||
{
|
||||
BLOCKTYPE BlockType;
|
||||
NIBBLETYPE BlockMeta;
|
||||
GetBlockTypeMeta(a_Position, BlockType, BlockMeta);
|
||||
if (!GetBlockTypeMeta(a_Position, BlockType, BlockMeta))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SetBlock(a_Position, a_BlockType, a_BlockMeta);
|
||||
|
||||
@ -2070,7 +2069,10 @@ bool cWorld::DigBlock(Vector3i a_BlockPos, const cEntity * a_Digger)
|
||||
{
|
||||
BLOCKTYPE BlockType;
|
||||
NIBBLETYPE BlockMeta;
|
||||
GetBlockTypeMeta(a_BlockPos, BlockType, BlockMeta);
|
||||
if (!GetBlockTypeMeta(a_BlockPos, BlockType, BlockMeta))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_ChunkMap.DigBlock(a_BlockPos))
|
||||
{
|
||||
@ -2617,7 +2619,11 @@ bool cWorld::IsTrapdoorOpen(int a_BlockX, int a_BlockY, int a_BlockZ)
|
||||
{
|
||||
BLOCKTYPE Block;
|
||||
NIBBLETYPE Meta;
|
||||
GetBlockTypeMeta({ a_BlockX, a_BlockY, a_BlockZ }, Block, Meta);
|
||||
if (!GetBlockTypeMeta({ a_BlockX, a_BlockY, a_BlockZ }, Block, Meta))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((Block != E_BLOCK_TRAPDOOR) && (Block != E_BLOCK_IRON_TRAPDOOR))
|
||||
{
|
||||
return false;
|
||||
@ -2634,7 +2640,11 @@ bool cWorld::SetTrapdoorOpen(int a_BlockX, int a_BlockY, int a_BlockZ, bool a_Op
|
||||
{
|
||||
BLOCKTYPE Block;
|
||||
NIBBLETYPE Meta;
|
||||
GetBlockTypeMeta({ a_BlockX, a_BlockY, a_BlockZ }, Block, Meta);
|
||||
if (!GetBlockTypeMeta({ a_BlockX, a_BlockY, a_BlockZ }, Block, Meta))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((Block != E_BLOCK_TRAPDOOR) && (Block != E_BLOCK_IRON_TRAPDOOR))
|
||||
{
|
||||
return false;
|
||||
|
@ -109,6 +109,7 @@ static void TestParser5(void)
|
||||
|
||||
|
||||
|
||||
|
||||
static void TestParser6(void)
|
||||
{
|
||||
cCompositeChat Msg;
|
||||
|
Loading…
Reference in New Issue
Block a user