Valid Height is now checked by vector.

This commit is contained in:
x12xx12x 2022-04-20 00:10:35 +02:00 committed by Alexander Harkness
parent 5ea7675eca
commit fe983a1a45
44 changed files with 202 additions and 211 deletions

View File

@ -500,7 +500,7 @@ static int tolua_cWorld_SetSignLines(lua_State * tolua_S)
} }
#endif #endif
{ {
bool res = self->SetSignLines(BlockX, BlockY, BlockZ, Line1, Line2, Line3, Line4, Player); bool res = self->SetSignLines({BlockX, BlockY, BlockZ}, Line1, Line2, Line3, Line4, Player);
tolua_pushboolean(LuaState, res ? 1 : 0); tolua_pushboolean(LuaState, res ? 1 : 0);
} }
} }

View File

@ -1638,7 +1638,7 @@ static int tolua_cPlayer_PlaceBlock(lua_State * tolua_S)
NIBBLETYPE BlockMeta; NIBBLETYPE BlockMeta;
L.GetStackValues(1, Self, Position, BlockType, BlockMeta); L.GetStackValues(1, Self, Position, BlockType, BlockMeta);
if (!cChunkDef::IsValidHeight(Position.y)) if (!cChunkDef::IsValidHeight(Position))
{ {
return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'position'"); return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'position'");
} }

View File

@ -747,7 +747,7 @@ static int tolua_cWorld_FastSetBlock(lua_State * tolua_S)
return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'"); return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'");
} }
if (!cChunkDef::IsValidHeight(Position.y)) if (!cChunkDef::IsValidHeight(Position))
{ {
return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'position'"); return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'position'");
} }
@ -903,7 +903,7 @@ static int tolua_cWorld_GetBlock(lua_State * tolua_S)
return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'"); return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'");
} }
if (!cChunkDef::IsValidHeight(Position.y)) if (!cChunkDef::IsValidHeight(Position))
{ {
L.Push(E_BLOCK_AIR); L.Push(E_BLOCK_AIR);
return 1; return 1;
@ -959,7 +959,7 @@ static int tolua_cWorld_GetBlockBlockLight(lua_State * tolua_S)
return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'"); return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'");
} }
if (!cChunkDef::IsValidHeight(Position.y)) if (!cChunkDef::IsValidHeight(Position))
{ {
return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'position'"); return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'position'");
} }
@ -1016,7 +1016,7 @@ static int tolua_cWorld_GetBlockInfo(lua_State * tolua_S)
return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'"); return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'");
} }
if (!cChunkDef::IsValidHeight(Position.y)) if (!cChunkDef::IsValidHeight(Position))
{ {
return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'position'"); return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'position'");
} }
@ -1083,7 +1083,7 @@ static int tolua_cWorld_GetBlockMeta(lua_State * tolua_S)
return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'"); return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'");
} }
if (!cChunkDef::IsValidHeight(Position.y)) if (!cChunkDef::IsValidHeight(Position))
{ {
L.Push(0); L.Push(0);
return 1; return 1;
@ -1139,7 +1139,7 @@ static int tolua_cWorld_GetBlockSkyLight(lua_State * tolua_S)
return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'"); return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'");
} }
if (!cChunkDef::IsValidHeight(Position.y)) if (!cChunkDef::IsValidHeight(Position))
{ {
return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'position'"); return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'position'");
} }
@ -1196,7 +1196,7 @@ static int tolua_cWorld_GetBlockTypeMeta(lua_State * tolua_S)
return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'"); return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'");
} }
if (!cChunkDef::IsValidHeight(Position.y)) if (!cChunkDef::IsValidHeight(Position))
{ {
L.Push(E_BLOCK_AIR, 0); L.Push(E_BLOCK_AIR, 0);
return 2; return 2;
@ -1470,7 +1470,7 @@ static int tolua_cWorld_SetBlock(lua_State * tolua_S)
return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'"); return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'");
} }
if (!cChunkDef::IsValidHeight(Position.y)) if (!cChunkDef::IsValidHeight(Position))
{ {
return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'position'"); return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'position'");
} }
@ -1528,7 +1528,7 @@ static int tolua_cWorld_SetBlockMeta(lua_State * tolua_S)
return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'"); return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'");
} }
if (!cChunkDef::IsValidHeight(Position.y)) if (!cChunkDef::IsValidHeight(Position))
{ {
return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'position'"); return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'position'");
} }
@ -1570,7 +1570,7 @@ static int tolua_cWorld_SetSignLines(lua_State * tolua_S)
} }
// Call the function: // Call the function:
bool res = Self->SetSignLines(BlockX, BlockY, BlockZ, Line1, Line2, Line3, Line4); bool res = Self->SetSignLines({BlockX, BlockY, BlockZ}, Line1, Line2, Line3, Line4);
// Push the returned values: // Push the returned values:
L.Push(res); L.Push(res);

View File

@ -445,8 +445,8 @@ bool cBlockArea::IsValidCoords(const Vector3i & a_Coords) const
bool cBlockArea::Read(cForEachChunkProvider & a_ForEachChunkProvider, int a_MinBlockX, int a_MaxBlockX, int a_MinBlockY, int a_MaxBlockY, int a_MinBlockZ, int a_MaxBlockZ, int a_DataTypes) bool cBlockArea::Read(cForEachChunkProvider & a_ForEachChunkProvider, int a_MinBlockX, int a_MaxBlockX, int a_MinBlockY, int a_MaxBlockY, int a_MinBlockZ, int a_MaxBlockZ, int a_DataTypes)
{ {
ASSERT(IsValidDataTypeCombination(a_DataTypes)); ASSERT(IsValidDataTypeCombination(a_DataTypes));
ASSERT(cChunkDef::IsValidHeight(a_MinBlockY)); ASSERT(cChunkDef::IsValidHeight({a_MinBlockX, a_MinBlockY, a_MinBlockZ}));
ASSERT(cChunkDef::IsValidHeight(a_MaxBlockY)); ASSERT(cChunkDef::IsValidHeight({a_MaxBlockX, a_MaxBlockY, a_MaxBlockZ}));
ASSERT(a_MinBlockX <= a_MaxBlockX); ASSERT(a_MinBlockX <= a_MaxBlockX);
ASSERT(a_MinBlockY <= a_MaxBlockY); ASSERT(a_MinBlockY <= a_MaxBlockY);
ASSERT(a_MinBlockZ <= a_MaxBlockZ); ASSERT(a_MinBlockZ <= a_MaxBlockZ);
@ -518,8 +518,8 @@ bool cBlockArea::Read(cForEachChunkProvider & a_ForEachChunkProvider, const Vect
bool cBlockArea::Write(cForEachChunkProvider & a_ForEachChunkProvider, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes) bool cBlockArea::Write(cForEachChunkProvider & a_ForEachChunkProvider, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes)
{ {
ASSERT((a_DataTypes & GetDataTypes()) == a_DataTypes); // Are you requesting only the data that I have? ASSERT((a_DataTypes & GetDataTypes()) == a_DataTypes); // Are you requesting only the data that I have?
ASSERT(cChunkDef::IsValidHeight(a_MinBlockY)); ASSERT(cChunkDef::IsValidHeight({a_MinBlockX, a_MinBlockY, a_MinBlockZ}));
ASSERT(cChunkDef::IsValidHeight(a_MinBlockY + m_Size.y - 1)); ASSERT(cChunkDef::IsValidHeight({a_MinBlockX, a_MinBlockY + m_Size.y - 1, a_MinBlockZ}));
return a_ForEachChunkProvider.WriteBlockArea(*this, a_MinBlockX, a_MinBlockY, a_MinBlockZ, a_DataTypes); return a_ForEachChunkProvider.WriteBlockArea(*this, a_MinBlockX, a_MinBlockY, a_MinBlockZ, a_DataTypes);
} }

View File

@ -16,7 +16,7 @@ cSignEntity::cSignEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i
Super(a_BlockType, a_BlockMeta, a_Pos, a_World) Super(a_BlockType, a_BlockMeta, a_Pos, a_World)
{ {
ASSERT((a_BlockType == E_BLOCK_WALLSIGN) || (a_BlockType == E_BLOCK_SIGN_POST)); ASSERT((a_BlockType == E_BLOCK_WALLSIGN) || (a_BlockType == E_BLOCK_SIGN_POST));
ASSERT(cChunkDef::IsValidHeight(a_Pos.y)); ASSERT(cChunkDef::IsValidHeight(a_Pos));
} }

View File

@ -127,7 +127,7 @@ private:
virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
{ {
auto SupportRelPos = AddFaceDirection(a_Position, BlockMetaDataToBlockFace(a_Meta), true); auto SupportRelPos = AddFaceDirection(a_Position, BlockMetaDataToBlockFace(a_Meta), true);
if (!cChunkDef::IsValidHeight(SupportRelPos.y)) if (!cChunkDef::IsValidHeight(SupportRelPos))
{ {
return false; return false;
} }

View File

@ -61,7 +61,7 @@ private:
} }
// Farmland too dry. If nothing is growing on top, turn back to dirt: // Farmland too dry. If nothing is growing on top, turn back to dirt:
auto UpperBlock = cChunkDef::IsValidHeight(a_RelPos.y + 1) ? a_Chunk.GetBlock(a_RelPos.addedY(1)) : E_BLOCK_AIR; auto UpperBlock = cChunkDef::IsValidHeight(a_RelPos.addedY(1)) ? a_Chunk.GetBlock(a_RelPos.addedY(1)) : E_BLOCK_AIR;
switch (UpperBlock) switch (UpperBlock)
{ {
case E_BLOCK_BEETROOTS: case E_BLOCK_BEETROOTS:

View File

@ -88,7 +88,7 @@ private:
// Check if it's fuel: // Check if it's fuel:
BLOCKTYPE BlockType; BLOCKTYPE BlockType;
if ( if (
!cChunkDef::IsValidHeight(Pos.y) || !cChunkDef::IsValidHeight(Pos) ||
!a_Chunk.UnboundedRelGetBlockType(Pos, BlockType) || !a_Chunk.UnboundedRelGetBlockType(Pos, BlockType) ||
!cFireSimulator::IsFuel(BlockType) !cFireSimulator::IsFuel(BlockType)
) )
@ -110,7 +110,7 @@ private:
{ {
auto NeighborPos = Pos + CrossCoords[i]; auto NeighborPos = Pos + CrossCoords[i];
if ( if (
cChunkDef::IsValidHeight(NeighborPos.y) && cChunkDef::IsValidHeight(NeighborPos) &&
a_Chunk.UnboundedRelGetBlockType(NeighborPos, BlockType) && a_Chunk.UnboundedRelGetBlockType(NeighborPos, BlockType) &&
(BlockType == E_BLOCK_AIR) (BlockType == E_BLOCK_AIR)
) )

View File

@ -99,7 +99,7 @@ private:
static Survivability DetermineSurvivability(cChunk & a_Chunk, const Vector3i a_RelPos) static Survivability DetermineSurvivability(cChunk & a_Chunk, const Vector3i a_RelPos)
{ {
const auto AbovePos = a_RelPos.addedY(1); const auto AbovePos = a_RelPos.addedY(1);
if (!cChunkDef::IsValidHeight(AbovePos.y)) if (!cChunkDef::IsValidHeight(AbovePos))
{ {
return Survivability::CanSpread; return Survivability::CanSpread;
} }
@ -126,7 +126,7 @@ private:
/** Attempt to spread grass to a block at the given position. */ /** Attempt to spread grass to a block at the given position. */
static void TrySpreadTo(cChunk & a_Chunk, Vector3i a_RelPos) static void TrySpreadTo(cChunk & a_Chunk, Vector3i a_RelPos)
{ {
if (!cChunkDef::IsValidHeight(a_RelPos.y)) if (!cChunkDef::IsValidHeight(a_RelPos))
{ {
// Y Coord out of range // Y Coord out of range
return; return;

View File

@ -486,7 +486,7 @@ void cBlockHandler::OnNeighborChanged(cChunkInterface & a_ChunkInterface, Vector
void cBlockHandler::NeighborChanged(cChunkInterface & a_ChunkInterface, Vector3i a_NeighborPos, eBlockFace a_WhichNeighbor) void cBlockHandler::NeighborChanged(cChunkInterface & a_ChunkInterface, Vector3i a_NeighborPos, eBlockFace a_WhichNeighbor)
{ {
if (!cChunkDef::IsValidHeight(a_NeighborPos.y)) if (!cChunkDef::IsValidHeight(a_NeighborPos))
{ {
return; return;
} }

View File

@ -94,7 +94,7 @@ private:
// Find the type of block the lever is attached to: // Find the type of block the lever is attached to:
auto NeighborFace = BlockMetaDataToBlockFace(a_Meta); auto NeighborFace = BlockMetaDataToBlockFace(a_Meta);
auto NeighborPos = AddFaceDirection(a_Position, NeighborFace, true); auto NeighborPos = AddFaceDirection(a_Position, NeighborFace, true);
if (!cChunkDef::IsValidHeight(NeighborPos.y)) if (!cChunkDef::IsValidHeight(NeighborPos))
{ {
return false; return false;
} }

View File

@ -31,7 +31,7 @@ private:
virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
{ {
auto UnderPos = a_Position.addedY(-1); auto UnderPos = a_Position.addedY(-1);
if (!cChunkDef::IsValidHeight(UnderPos.y)) if (!cChunkDef::IsValidHeight(UnderPos))
{ {
return false; return false;
} }

View File

@ -215,7 +215,7 @@ bool cBlockPistonHandler::CanPushBlock(
Vector3iSet & a_BlocksPushed, const Vector3i & a_PushDir Vector3iSet & a_BlocksPushed, const Vector3i & a_PushDir
) )
{ {
if (!cChunkDef::IsValidHeight(a_BlockPos.y)) if (!cChunkDef::IsValidHeight(a_BlockPos))
{ {
// Can't push a void block. // Can't push a void block.
return false; return false;
@ -299,7 +299,7 @@ void cBlockPistonHandler::OnBroken(
const auto Extension = a_BlockPos + MetadataToOffset(a_OldBlockMeta); const auto Extension = a_BlockPos + MetadataToOffset(a_OldBlockMeta);
if ( if (
cChunkDef::IsValidHeight(Extension.y) && cChunkDef::IsValidHeight(Extension) &&
(a_ChunkInterface.GetBlock(Extension) == E_BLOCK_PISTON_EXTENSION) (a_ChunkInterface.GetBlock(Extension) == E_BLOCK_PISTON_EXTENSION)
) )
{ {
@ -324,7 +324,7 @@ void cBlockPistonHeadHandler::OnBroken(
{ {
UNUSED(a_Digger); UNUSED(a_Digger);
const auto Base = a_BlockPos - cBlockPistonHandler::MetadataToOffset(a_OldBlockMeta); const auto Base = a_BlockPos - cBlockPistonHandler::MetadataToOffset(a_OldBlockMeta);
if (!cChunkDef::IsValidHeight(Base.y)) if (!cChunkDef::IsValidHeight(Base))
{ {
return; return;
} }

View File

@ -199,7 +199,7 @@ private:
// Vine cannot grow down if at the bottom: // Vine cannot grow down if at the bottom:
auto GrowPos = a_RelPos.addedY(-1); auto GrowPos = a_RelPos.addedY(-1);
if (!cChunkDef::IsValidHeight(GrowPos.y)) if (!cChunkDef::IsValidHeight(GrowPos))
{ {
return; return;
} }

View File

@ -1022,7 +1022,7 @@ int cChunk::GrowPlantAt(Vector3i a_RelPos, int a_NumStages)
bool cChunk::UnboundedRelGetBlock(Vector3i a_RelPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const bool cChunk::UnboundedRelGetBlock(Vector3i a_RelPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const
{ {
if (!cChunkDef::IsValidHeight(a_RelPos.y)) if (!cChunkDef::IsValidHeight(a_RelPos))
{ {
LOGWARNING("%s: requesting a block with a_RelY out of range: %d", __FUNCTION__, a_RelPos.y); LOGWARNING("%s: requesting a block with a_RelY out of range: %d", __FUNCTION__, a_RelPos.y);
return false; return false;
@ -1043,7 +1043,7 @@ bool cChunk::UnboundedRelGetBlock(Vector3i a_RelPos, BLOCKTYPE & a_BlockType, NI
bool cChunk::UnboundedRelGetBlockType(Vector3i a_RelPos, BLOCKTYPE & a_BlockType) const bool cChunk::UnboundedRelGetBlockType(Vector3i a_RelPos, BLOCKTYPE & a_BlockType) const
{ {
if (!cChunkDef::IsValidHeight(a_RelPos.y)) if (!cChunkDef::IsValidHeight(a_RelPos))
{ {
LOGWARNING("%s: requesting a block with a_RelY out of range: %d", __FUNCTION__, a_RelPos.y); LOGWARNING("%s: requesting a block with a_RelY out of range: %d", __FUNCTION__, a_RelPos.y);
return false; return false;
@ -1064,7 +1064,7 @@ bool cChunk::UnboundedRelGetBlockType(Vector3i a_RelPos, BLOCKTYPE & a_BlockType
bool cChunk::UnboundedRelGetBlockMeta(Vector3i a_RelPos, NIBBLETYPE & a_BlockMeta) const bool cChunk::UnboundedRelGetBlockMeta(Vector3i a_RelPos, NIBBLETYPE & a_BlockMeta) const
{ {
if (!cChunkDef::IsValidHeight(a_RelPos.y)) if (!cChunkDef::IsValidHeight(a_RelPos))
{ {
LOGWARNING("%s: requesting a block with a_RelY out of range: %d", __FUNCTION__, a_RelPos.y); LOGWARNING("%s: requesting a block with a_RelY out of range: %d", __FUNCTION__, a_RelPos.y);
return false; return false;
@ -1085,7 +1085,7 @@ bool cChunk::UnboundedRelGetBlockMeta(Vector3i a_RelPos, NIBBLETYPE & a_BlockMet
bool cChunk::UnboundedRelGetBlockBlockLight(Vector3i a_RelPos, NIBBLETYPE & a_BlockBlockLight) const bool cChunk::UnboundedRelGetBlockBlockLight(Vector3i a_RelPos, NIBBLETYPE & a_BlockBlockLight) const
{ {
if (!cChunkDef::IsValidHeight(a_RelPos.y)) if (!cChunkDef::IsValidHeight(a_RelPos))
{ {
LOGWARNING("%s: requesting a block with a_RelY out of range: %d", __FUNCTION__, a_RelPos.y); LOGWARNING("%s: requesting a block with a_RelY out of range: %d", __FUNCTION__, a_RelPos.y);
return false; return false;
@ -1106,7 +1106,7 @@ bool cChunk::UnboundedRelGetBlockBlockLight(Vector3i a_RelPos, NIBBLETYPE & a_Bl
bool cChunk::UnboundedRelGetBlockSkyLight(Vector3i a_RelPos, NIBBLETYPE & a_BlockSkyLight) const bool cChunk::UnboundedRelGetBlockSkyLight(Vector3i a_RelPos, NIBBLETYPE & a_BlockSkyLight) const
{ {
if (!cChunkDef::IsValidHeight(a_RelPos.y)) if (!cChunkDef::IsValidHeight(a_RelPos))
{ {
LOGWARNING("%s: requesting a block with a_RelY out of range: %d", __FUNCTION__, a_RelPos.y); LOGWARNING("%s: requesting a block with a_RelY out of range: %d", __FUNCTION__, a_RelPos.y);
return false; return false;
@ -1127,7 +1127,7 @@ bool cChunk::UnboundedRelGetBlockSkyLight(Vector3i a_RelPos, NIBBLETYPE & a_Bloc
bool cChunk::UnboundedRelGetBlockLights(Vector3i a_RelPos, NIBBLETYPE & a_BlockLight, NIBBLETYPE & a_SkyLight) const bool cChunk::UnboundedRelGetBlockLights(Vector3i a_RelPos, NIBBLETYPE & a_BlockLight, NIBBLETYPE & a_SkyLight) const
{ {
if (!cChunkDef::IsValidHeight(a_RelPos.y)) if (!cChunkDef::IsValidHeight(a_RelPos))
{ {
LOGWARNING("%s: requesting a block with a_RelY out of range: %d", __FUNCTION__, a_RelPos.y); LOGWARNING("%s: requesting a block with a_RelY out of range: %d", __FUNCTION__, a_RelPos.y);
return false; return false;
@ -1149,7 +1149,7 @@ bool cChunk::UnboundedRelGetBlockLights(Vector3i a_RelPos, NIBBLETYPE & a_BlockL
bool cChunk::UnboundedRelSetBlock(Vector3i a_RelPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) bool cChunk::UnboundedRelSetBlock(Vector3i a_RelPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{ {
if (!cChunkDef::IsValidHeight(a_RelPos.y)) if (!cChunkDef::IsValidHeight(a_RelPos))
{ {
LOGWARNING("%s: requesting a block with a_RelY out of range: %d", __FUNCTION__, a_RelPos.y); LOGWARNING("%s: requesting a block with a_RelY out of range: %d", __FUNCTION__, a_RelPos.y);
return false; return false;
@ -1170,7 +1170,7 @@ bool cChunk::UnboundedRelSetBlock(Vector3i a_RelPos, BLOCKTYPE a_BlockType, NIBB
bool cChunk::UnboundedRelFastSetBlock(Vector3i a_RelPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) bool cChunk::UnboundedRelFastSetBlock(Vector3i a_RelPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{ {
if (!cChunkDef::IsValidHeight(a_RelPos.y)) if (!cChunkDef::IsValidHeight(a_RelPos))
{ {
LOGWARNING("%s: requesting a block with a_RelY out of range: %d", __FUNCTION__, a_RelPos.y); LOGWARNING("%s: requesting a block with a_RelY out of range: %d", __FUNCTION__, a_RelPos.y);
return false; return false;

View File

@ -164,15 +164,10 @@ public:
} }
/** Validates a height-coordinate. Returns false if height-coordiante is out of height bounds */ /** Validates a height-coordinate. Returns false if height-coordinate is out of height bounds */
inline static bool IsValidHeight(int a_Height)
{
return ((a_Height >= 0) && (a_Height < Height));
}
inline static bool IsValidHeight(Vector3i a_BlockPosition) inline static bool IsValidHeight(Vector3i a_BlockPosition)
{ {
return IsValidHeight(a_BlockPosition.y); return ((a_BlockPosition.y >= 0) && (a_BlockPosition.y < Height));
} }
@ -188,7 +183,7 @@ public:
{ {
return ( return (
IsValidWidth(a_RelPos.x) && IsValidWidth(a_RelPos.x) &&
IsValidHeight(a_RelPos.y) && IsValidHeight(a_RelPos) &&
IsValidWidth(a_RelPos.z) IsValidWidth(a_RelPos.z)
); );
} }

View File

@ -748,7 +748,7 @@ bool cChunkMap::GetBlocks(sSetBlockVector & a_Blocks, bool a_ContinueOnFailure)
res = false; res = false;
continue; continue;
} }
if (!cChunkDef::IsValidHeight(itr->m_RelY)) if (!cChunkDef::IsValidHeight(itr->GetRelativePos()))
{ {
continue; continue;
} }

View File

@ -61,6 +61,8 @@ int cClientHandle::s_ClientCount = 0;
float cClientHandle::FASTBREAK_PERCENTAGE; float cClientHandle::FASTBREAK_PERCENTAGE;
Vector3i cClientHandle::s_IllegalPosition = {0, cChunkDef::Height + 1, 0};
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -81,16 +83,16 @@ cClientHandle::cClientHandle(const AString & a_IPString, int a_ViewDistance) :
m_PingID(1), m_PingID(1),
m_BlockDigAnimStage(-1), m_BlockDigAnimStage(-1),
m_BlockDigAnimSpeed(0), m_BlockDigAnimSpeed(0),
m_BlockDigAnimPos(), m_BlockDigAnimPos(s_IllegalPosition),
m_HasStartedDigging(false), m_HasStartedDigging(false),
m_LastDigBlockPos(), m_LastDigBlockPos(s_IllegalPosition),
m_State(csConnected), m_State(csConnected),
m_NumExplosionsThisTick(0), m_NumExplosionsThisTick(0),
m_NumBlockChangeInteractionsThisTick(0), m_NumBlockChangeInteractionsThisTick(0),
m_UniqueID(0), m_UniqueID(0),
m_HasSentPlayerChunk(false), m_HasSentPlayerChunk(false),
m_Locale("en_GB"), m_Locale("en_GB"),
m_LastPlacedSign(0, -1, 0), m_LastPlacedSign(s_IllegalPosition),
m_ProtocolVersion(0) m_ProtocolVersion(0)
{ {
s_ClientCount++; // Not protected by CS because clients are always constructed from the same thread s_ClientCount++; // Not protected by CS because clients are always constructed from the same thread
@ -1119,16 +1121,13 @@ void cClientHandle::HandleLeftClick(Vector3i a_BlockPos, eBlockFace a_BlockFace,
Vector3i BlockPos = a_BlockPos; Vector3i BlockPos = a_BlockPos;
AddFaceDirection(BlockPos, a_BlockFace); AddFaceDirection(BlockPos, a_BlockFace);
if (cChunkDef::IsValidHeight(BlockPos.y) && cBlockInfo::IsClickedThrough(m_Player->GetWorld()->GetBlock(BlockPos))) if (cChunkDef::IsValidHeight(BlockPos) && cBlockInfo::IsClickedThrough(m_Player->GetWorld()->GetBlock(BlockPos)))
{ {
a_BlockPos = BlockPos; a_BlockPos = BlockPos;
} }
if ( constexpr double MaxBlockDistance = 6.0;
(Diff(m_Player->GetPosX(), static_cast<double>(a_BlockPos.x)) > 6) || if (!cBoundingBox(m_Player->GetPosition(), MaxBlockDistance).IsInside(a_BlockPos))
(Diff(m_Player->GetPosY(), static_cast<double>(a_BlockPos.y)) > 6) ||
(Diff(m_Player->GetPosZ(), static_cast<double>(a_BlockPos.z)) > 6)
)
{ {
m_Player->SendBlocksAround(a_BlockPos, 2); m_Player->SendBlocksAround(a_BlockPos, 2);
return; return;
@ -1176,11 +1175,11 @@ void cClientHandle::HandleLeftClick(Vector3i a_BlockPos, eBlockFace a_BlockFace,
// When bow is in off-hand / shield slot // When bow is in off-hand / shield slot
if (m_Player->GetInventory().GetShieldSlot().m_ItemType == E_ITEM_BOW) if (m_Player->GetInventory().GetShieldSlot().m_ItemType == E_ITEM_BOW)
{ {
m_Player->GetInventory().GetShieldSlot().GetHandler().OnItemShoot(m_Player, {a_BlockPos}, a_BlockFace); m_Player->GetInventory().GetShieldSlot().GetHandler().OnItemShoot(m_Player, a_BlockPos, a_BlockFace);
} }
else else
{ {
ItemHandler.OnItemShoot(m_Player, {a_BlockPos}, a_BlockFace); ItemHandler.OnItemShoot(m_Player, a_BlockPos, a_BlockFace);
} }
} }
return; return;
@ -1271,11 +1270,8 @@ void cClientHandle::HandleBlockDigStarted(Vector3i a_BlockPos, eBlockFace a_Bloc
return; return;
} }
if ( constexpr double MaxBlockDistance = 6.0;
(Diff(m_Player->GetPosX(), static_cast<double>(a_BlockPos.x)) > 6) || if (!cBoundingBox(m_Player->GetPosition(), MaxBlockDistance).IsInside(a_BlockPos))
(Diff(m_Player->GetPosY(), static_cast<double>(a_BlockPos.y)) > 6) ||
(Diff(m_Player->GetPosZ(), static_cast<double>(a_BlockPos.z)) > 6)
)
{ {
m_Player->SendBlocksAround(a_BlockPos, 2); m_Player->SendBlocksAround(a_BlockPos, 2);
return; return;
@ -1309,9 +1305,9 @@ void cClientHandle::HandleBlockDigStarted(Vector3i a_BlockPos, eBlockFace a_Bloc
cWorld * World = m_Player->GetWorld(); cWorld * World = m_Player->GetWorld();
cChunkInterface ChunkInterface(World->GetChunkMap()); cChunkInterface ChunkInterface(World->GetChunkMap());
cBlockHandler::For(DiggingBlock).OnDigging(ChunkInterface, *World, *m_Player, {a_BlockPos}); cBlockHandler::For(DiggingBlock).OnDigging(ChunkInterface, *World, *m_Player, a_BlockPos);
m_Player->GetEquippedItem().GetHandler().OnDiggingBlock(World, m_Player, m_Player->GetEquippedItem(), {a_BlockPos}, a_BlockFace); m_Player->GetEquippedItem().GetHandler().OnDiggingBlock(World, m_Player, m_Player->GetEquippedItem(), a_BlockPos, a_BlockFace);
} }
@ -1337,7 +1333,7 @@ void cClientHandle::HandleBlockDigFinished(Vector3i a_BlockPos, eBlockFace a_Blo
BLOCKTYPE DugBlock; BLOCKTYPE DugBlock;
NIBBLETYPE DugMeta; NIBBLETYPE DugMeta;
m_Player->GetWorld()->GetBlockTypeMeta({ a_BlockPos }, DugBlock, DugMeta); m_Player->GetWorld()->GetBlockTypeMeta(a_BlockPos, DugBlock, DugMeta);
if (!m_Player->IsGameModeCreative()) if (!m_Player->IsGameModeCreative())
{ {
@ -1411,14 +1407,14 @@ void cClientHandle::FinishDigAnimation()
m_Player->GetWorld()->BroadcastBlockBreakAnimation(static_cast<UInt32>(m_UniqueID), m_LastDigBlockPos, 10, this); m_Player->GetWorld()->BroadcastBlockBreakAnimation(static_cast<UInt32>(m_UniqueID), m_LastDigBlockPos, 10, this);
} }
m_LastDigBlockPos = {-1, -1, -1}; m_LastDigBlockPos = s_IllegalPosition;
} }
void cClientHandle::HandleRightClick(Vector3i a_BlockPos, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, bool a_UsedMainHand) void cClientHandle::HandleRightClick(Vector3i a_BlockPos, eBlockFace a_BlockFace, Vector3i a_CursorPos, bool a_UsedMainHand)
{ {
/* This function handles three actions: /* This function handles three actions:
(1) Place a block; (1) Place a block;
@ -1443,12 +1439,10 @@ void cClientHandle::HandleRightClick(Vector3i a_BlockPos, eBlockFace a_BlockFace
// TODO: We are still consuming the items in main hand. Remove this override when the off-hand consumption is handled correctly. // TODO: We are still consuming the items in main hand. Remove this override when the off-hand consumption is handled correctly.
a_UsedMainHand = true; a_UsedMainHand = true;
const Vector3i ClickedPosition(a_BlockPos);
const Vector3i CursorPosition(a_CursorX, a_CursorY, a_CursorZ);
const cItem & HeldItem = a_UsedMainHand ? m_Player->GetEquippedItem() : m_Player->GetInventory().GetShieldSlot(); const cItem & HeldItem = a_UsedMainHand ? m_Player->GetEquippedItem() : m_Player->GetInventory().GetShieldSlot();
// Distance from the block's center to the player's eye height. // Distance from the block's center to the player's eye height.
const double Dist = (Vector3d(0.5, 0.5, 0.5) + ClickedPosition - m_Player->GetEyePosition()).SqrLength(); const double Dist = (Vector3d(0.5, 0.5, 0.5) + a_BlockPos - m_Player->GetEyePosition()).SqrLength();
// Check the reach distance: // Check the reach distance:
// _X 2014-11-25: I've maxed at 5.26 with a Survival client and 5.78 with a Creative client in my tests // _X 2014-11-25: I've maxed at 5.26 with a Survival client and 5.78 with a Creative client in my tests
@ -1456,21 +1450,21 @@ void cClientHandle::HandleRightClick(Vector3i a_BlockPos, eBlockFace a_BlockFace
bool IsWithinReach = (Dist <= MaxDist); bool IsWithinReach = (Dist <= MaxDist);
FLOGD("HandleRightClick: {0}, face {1}, Cursor {2}, Hand: {3}, HeldItem: {4}; Dist: {5:.02f}", FLOGD("HandleRightClick: {0}, face {1}, Cursor {2}, Hand: {3}, HeldItem: {4}; Dist: {5:.02f}",
ClickedPosition, a_BlockFace, CursorPosition, a_UsedMainHand, ItemToFullString(HeldItem), Dist a_BlockPos, a_BlockFace, a_CursorPos, a_UsedMainHand, ItemToFullString(HeldItem), Dist
); );
cWorld * World = m_Player->GetWorld(); cWorld * World = m_Player->GetWorld();
cPluginManager * PlgMgr = cRoot::Get()->GetPluginManager(); cPluginManager * PlgMgr = cRoot::Get()->GetPluginManager();
if ( if (
!PlgMgr->CallHookPlayerRightClick(*m_Player, a_BlockPos, a_BlockFace, CursorPosition) && !PlgMgr->CallHookPlayerRightClick(*m_Player, a_BlockPos, a_BlockFace, a_CursorPos) &&
IsWithinReach && !m_Player->IsFrozen() IsWithinReach && !m_Player->IsFrozen()
) )
{ {
BLOCKTYPE BlockType; BLOCKTYPE BlockType;
NIBBLETYPE BlockMeta; NIBBLETYPE BlockMeta;
if (!World->GetBlockTypeMeta(ClickedPosition, BlockType, BlockMeta)) if (!World->GetBlockTypeMeta(a_BlockPos, BlockType, BlockMeta))
{ {
return; return;
} }
@ -1484,12 +1478,12 @@ void cClientHandle::HandleRightClick(Vector3i a_BlockPos, eBlockFace a_BlockFace
if (BlockUsable) if (BlockUsable)
{ {
cChunkInterface ChunkInterface(World->GetChunkMap()); cChunkInterface ChunkInterface(World->GetChunkMap());
if (!PlgMgr->CallHookPlayerUsingBlock(*m_Player, a_BlockPos, a_BlockFace, CursorPosition, BlockType, BlockMeta)) if (!PlgMgr->CallHookPlayerUsingBlock(*m_Player, a_BlockPos, a_BlockFace, a_CursorPos, BlockType, BlockMeta))
{ {
// Use a block: // Use a block:
if (BlockHandler.OnUse(ChunkInterface, *World, *m_Player, ClickedPosition, a_BlockFace, CursorPosition)) if (BlockHandler.OnUse(ChunkInterface, *World, *m_Player, a_BlockPos, a_BlockFace, a_CursorPos))
{ {
PlgMgr->CallHookPlayerUsedBlock(*m_Player, a_BlockPos, a_BlockFace, CursorPosition, BlockType, BlockMeta); PlgMgr->CallHookPlayerUsedBlock(*m_Player, a_BlockPos, a_BlockFace, a_CursorPos, BlockType, BlockMeta);
return; // Block use was successful, we're done. return; // Block use was successful, we're done.
} }
@ -1497,7 +1491,7 @@ void cClientHandle::HandleRightClick(Vector3i a_BlockPos, eBlockFace a_BlockFace
if (ItemPlaceable) if (ItemPlaceable)
{ {
// Place a block: // Place a block:
ItemHandler.OnPlayerPlace(*m_Player, HeldItem, ClickedPosition, BlockType, BlockMeta, a_BlockFace, CursorPosition); ItemHandler.OnPlayerPlace(*m_Player, HeldItem, a_BlockPos, BlockType, BlockMeta, a_BlockFace, a_CursorPos);
} }
return; return;
@ -1514,19 +1508,19 @@ void cClientHandle::HandleRightClick(Vector3i a_BlockPos, eBlockFace a_BlockFace
} }
// Place a block: // Place a block:
ItemHandler.OnPlayerPlace(*m_Player, HeldItem, ClickedPosition, BlockType, BlockMeta, a_BlockFace, CursorPosition); ItemHandler.OnPlayerPlace(*m_Player, HeldItem, a_BlockPos, BlockType, BlockMeta, a_BlockFace, a_CursorPos);
return; return;
} }
else if (ItemUseable) else if (ItemUseable)
{ {
if (!PlgMgr->CallHookPlayerUsingItem(*m_Player, a_BlockPos, a_BlockFace, CursorPosition)) if (!PlgMgr->CallHookPlayerUsingItem(*m_Player, a_BlockPos, a_BlockFace, a_CursorPos))
{ {
// All plugins agree with using the item. // All plugins agree with using the item.
// Use an item in hand with a target block. // Use an item in hand with a target block.
cBlockInServerPluginInterface PluginInterface(*World); cBlockInServerPluginInterface PluginInterface(*World);
ItemHandler.OnItemUse(World, m_Player, PluginInterface, HeldItem, ClickedPosition, a_BlockFace); ItemHandler.OnItemUse(World, m_Player, PluginInterface, HeldItem, a_BlockPos, a_BlockFace);
PlgMgr->CallHookPlayerUsedItem(*m_Player, a_BlockPos, a_BlockFace, CursorPosition); PlgMgr->CallHookPlayerUsedItem(*m_Player, a_BlockPos, a_BlockFace, a_CursorPos);
return; return;
} }
} }
@ -1609,9 +1603,8 @@ void cClientHandle::HandlePlayerLook(float a_Rotation, float a_Pitch, bool a_IsO
void cClientHandle::HandlePlayerMove(double a_PosX, double a_PosY, double a_PosZ, bool a_IsOnGround) void cClientHandle::HandlePlayerMove(Vector3d a_Pos, bool a_IsOnGround)
{ {
const Vector3d NewPosition(a_PosX, a_PosY, a_PosZ);
const Vector3d OldPosition = GetPlayer()->GetPosition(); const Vector3d OldPosition = GetPlayer()->GetPosition();
const auto PreviousIsOnGround = GetPlayer()->IsOnGround(); const auto PreviousIsOnGround = GetPlayer()->IsOnGround();
@ -1621,7 +1614,7 @@ void cClientHandle::HandlePlayerMove(double a_PosX, double a_PosY, double a_PosZ
#endif #endif
if ( if (
(OldPosition == NewPosition) && (OldPosition == a_Pos) &&
(PreviousIsOnGround == a_IsOnGround) (PreviousIsOnGround == a_IsOnGround)
) )
{ {
@ -1641,14 +1634,14 @@ void cClientHandle::HandlePlayerMove(double a_PosX, double a_PosY, double a_PosZ
} }
// If the player has moved too far, "repair" them: // If the player has moved too far, "repair" them:
if ((OldPosition - NewPosition).SqrLength() > 100 * 100) if ((OldPosition - a_Pos).SqrLength() > 100 * 100)
{ {
LOGD("Too far away (%0.2f), \"repairing\" the client", (OldPosition - NewPosition).Length()); LOGD("Too far away (%0.2f), \"repairing\" the client", (OldPosition - a_Pos).Length());
SendPlayerMoveLook(); SendPlayerMoveLook();
return; return;
} }
if (cRoot::Get()->GetPluginManager()->CallHookPlayerMoving(*m_Player, OldPosition, NewPosition, PreviousIsOnGround)) if (cRoot::Get()->GetPluginManager()->CallHookPlayerMoving(*m_Player, OldPosition, a_Pos, PreviousIsOnGround))
{ {
SendPlayerMoveLook(); SendPlayerMoveLook();
return; return;
@ -1657,18 +1650,18 @@ void cClientHandle::HandlePlayerMove(double a_PosX, double a_PosY, double a_PosZ
// TODO: should do some checks to see if player is not moving through terrain // TODO: should do some checks to see if player is not moving through terrain
// TODO: Official server refuses position packets too far away from each other, kicking "hacked" clients; we should, too // TODO: Official server refuses position packets too far away from each other, kicking "hacked" clients; we should, too
m_Player->SetPosition(NewPosition); m_Player->SetPosition(a_Pos);
m_Player->SetTouchGround(a_IsOnGround); m_Player->SetTouchGround(a_IsOnGround);
m_Player->UpdateMovementStats(NewPosition - OldPosition, PreviousIsOnGround); m_Player->UpdateMovementStats(a_Pos - OldPosition, PreviousIsOnGround);
} }
void cClientHandle::HandlePlayerMoveLook(double a_PosX, double a_PosY, double a_PosZ, float a_Rotation, float a_Pitch, bool a_IsOnGround) void cClientHandle::HandlePlayerMoveLook(Vector3d a_Pos, float a_Rotation, float a_Pitch, bool a_IsOnGround)
{ {
HandlePlayerMove(a_PosX, a_PosY, a_PosZ, a_IsOnGround); HandlePlayerMove(a_Pos, a_IsOnGround);
HandlePlayerLook(a_Rotation, a_Pitch, a_IsOnGround); HandlePlayerLook(a_Rotation, a_Pitch, a_IsOnGround);
} }
@ -1768,7 +1761,7 @@ void cClientHandle::HandleUpdateSign(
const AString & a_Line3, const AString & a_Line4 const AString & a_Line3, const AString & a_Line4
) )
{ {
if (m_LastPlacedSign.Equals(Vector3i(a_BlockPos))) if (m_LastPlacedSign.Equals(a_BlockPos))
{ {
m_LastPlacedSign.Set(0, -1, 0); m_LastPlacedSign.Set(0, -1, 0);
m_Player->GetWorld()->SetSignLines(a_BlockPos, a_Line1, a_Line2, a_Line3, a_Line4, m_Player); m_Player->GetWorld()->SetSignLines(a_BlockPos, a_Line1, a_Line2, a_Line3, a_Line4, m_Player);
@ -1865,7 +1858,10 @@ void cClientHandle::HandleUseItem(bool a_UsedMainHand)
LOGD("HandleUseItem: Hand: %d; HeldItem: %s", a_UsedMainHand, ItemToFullString(HeldItem).c_str()); LOGD("HandleUseItem: Hand: %d; HeldItem: %s", a_UsedMainHand, ItemToFullString(HeldItem).c_str());
if (PlgMgr->CallHookPlayerRightClick(*m_Player, {-1, 255, -1}, BLOCK_FACE_NONE, {0, 0, 0})) constexpr Vector3i DefaultBlockPos(-1, 255, -1);
constexpr Vector3i DefaultCursorPos(0, 0, 0);
if (PlgMgr->CallHookPlayerRightClick(*m_Player, DefaultBlockPos, BLOCK_FACE_NONE, DefaultCursorPos))
{ {
return; // Plugin denied click action return; // Plugin denied click action
} }
@ -1897,12 +1893,12 @@ void cClientHandle::HandleUseItem(bool a_UsedMainHand)
else else
{ {
// Use an item in hand without a target block // Use an item in hand without a target block
if (!PlgMgr->CallHookPlayerUsingItem(*m_Player, {-1, 255, -1}, BLOCK_FACE_NONE, {0, 0, 0})) if (!PlgMgr->CallHookPlayerUsingItem(*m_Player, DefaultBlockPos, BLOCK_FACE_NONE, DefaultCursorPos))
{ {
// All plugins agree with using the item // All plugins agree with using the item
cBlockInServerPluginInterface PluginInterface(*World); cBlockInServerPluginInterface PluginInterface(*World);
ItemHandler.OnItemUse(World, m_Player, PluginInterface, HeldItem, {-1, 255, -1}, BLOCK_FACE_NONE); ItemHandler.OnItemUse(World, m_Player, PluginInterface, HeldItem, DefaultBlockPos, BLOCK_FACE_NONE);
PlgMgr->CallHookPlayerUsedItem(*m_Player, {-1, 255, -1}, BLOCK_FACE_NONE, {0, 0, 0}); PlgMgr->CallHookPlayerUsedItem(*m_Player, DefaultBlockPos, BLOCK_FACE_NONE, DefaultCursorPos);
} }
} }
} }
@ -2687,13 +2683,13 @@ void cClientHandle::SendExplosion(const Vector3f a_Position, const float a_Power
auto ParticleCount = std::min(static_cast<int>(ParticleFormula * 125), 600); auto ParticleCount = std::min(static_cast<int>(ParticleFormula * 125), 600);
// Dark smoke particles: // Dark smoke particles:
SendParticleEffect("largesmoke", a_Position, Vector3f(), Spread, static_cast<int>(ParticleCount)); SendParticleEffect("largesmoke", a_Position, {0.f, 0.f, 0.f,}, Spread, static_cast<int>(ParticleCount));
Spread = ParticleFormula * 0.35f; Spread = ParticleFormula * 0.35f;
ParticleCount = std::min(static_cast<int>(ParticleFormula * 550), 1800); ParticleCount = std::min(static_cast<int>(ParticleFormula * 550), 1800);
// Light smoke particles: // Light smoke particles:
SendParticleEffect("explode", a_Position, Vector3f(), Spread, static_cast<int>(ParticleCount)); SendParticleEffect("explode", a_Position, {0.f, 0.f, 0.f,}, Spread, static_cast<int>(ParticleCount));
// Shockwave effect: // Shockwave effect:
m_Protocol->SendExplosion(a_Position, a_Power); m_Protocol->SendExplosion(a_Position, a_Power);

View File

@ -370,14 +370,14 @@ public: // tolua_export
/** Verifies and sets player position, performing relevant checks. /** Verifies and sets player position, performing relevant checks.
Calls relevant methods to process movement related statistics. Calls relevant methods to process movement related statistics.
Requires state of previous position and on-ground status, so must be called when these are still intact. */ Requires state of previous position and on-ground status, so must be called when these are still intact. */
void HandlePlayerMove(double a_PosX, double a_PosY, double a_PosZ, bool a_IsOnGround); void HandlePlayerMove(Vector3d a_Pos, bool a_IsOnGround);
void HandlePlayerMoveLook(double a_PosX, double a_PosY, double a_PosZ, float a_Rotation, float a_Pitch, bool a_IsOnGround); void HandlePlayerMoveLook(Vector3d a_Pos, float a_Rotation, float a_Pitch, bool a_IsOnGround);
void HandlePluginMessage (const AString & a_Channel, ContiguousByteBufferView a_Message); void HandlePluginMessage (const AString & a_Channel, ContiguousByteBufferView a_Message);
void HandleRespawn (void); void HandleRespawn (void);
void HandleRightClick (Vector3i a_BlockPos, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, bool a_UsedMainHand); void HandleRightClick (Vector3i a_BlockPos, eBlockFace a_BlockFace, Vector3i a_Cursor, bool a_UsedMainHand);
void HandleSlotSelected (Int16 a_SlotNum); void HandleSlotSelected (Int16 a_SlotNum);
void HandleSpectate (const cUUID & a_PlayerUUID); void HandleSpectate (const cUUID & a_PlayerUUID);
@ -540,6 +540,8 @@ private:
static int s_ClientCount; static int s_ClientCount;
static Vector3i s_IllegalPosition;
/** ID used for identification during authenticating. Assigned sequentially for each new instance. */ /** ID used for identification during authenticating. Assigned sequentially for each new instance. */
int m_UniqueID; int m_UniqueID;

View File

@ -95,7 +95,7 @@ void cEnderCrystal::KilledBy(TakeDamageInfo & a_TDI)
m_World->DoExplosionAt(6.0, GetPosX(), GetPosY() + GetHeight() / 2, GetPosZ(), true, esEnderCrystal, this); m_World->DoExplosionAt(6.0, GetPosX(), GetPosY() + GetHeight() / 2, GetPosZ(), true, esEnderCrystal, this);
const auto Position = GetPosition().Floor(); const auto Position = GetPosition().Floor();
if (cChunkDef::IsValidHeight(Position.y)) if (cChunkDef::IsValidHeight(Position))
{ {
m_World->SetBlock(Position, E_BLOCK_FIRE, 0); m_World->SetBlock(Position, E_BLOCK_FIRE, 0);
} }

View File

@ -1131,7 +1131,7 @@ void cEntity::HandlePhysics(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
} }
// Get water direction // Get water direction
Vector3f WaterDir = m_World->GetWaterSimulator()->GetFlowingDirection(BlockX, BlockY, BlockZ); Vector3f WaterDir = m_World->GetWaterSimulator()->GetFlowingDirection({BlockX, BlockY, BlockZ});
m_WaterSpeed *= 0.9; // Reduce speed each tick m_WaterSpeed *= 0.9; // Reduce speed each tick
@ -1433,7 +1433,7 @@ bool cEntity::DetectPortal()
return false; return false;
} }
if (const auto Position = m_Position.Floor(); cChunkDef::IsValidHeight(Position.y)) if (const auto Position = m_Position.Floor(); cChunkDef::IsValidHeight(Position))
{ {
switch (GetWorld()->GetBlock(Position)) switch (GetWorld()->GetBlock(Position))
{ {

View File

@ -320,7 +320,7 @@ void cPawn::HandleFalling(void)
With this in mind, we first check the block at the player's feet, then the one below that (because fences), With this in mind, we first check the block at the player's feet, then the one below that (because fences),
and decide which behaviour we want to go with. and decide which behaviour we want to go with.
*/ */
BLOCKTYPE BlockAtFoot = (cChunkDef::IsValidHeight(POSY_TOINT)) ? GetWorld()->GetBlock(POS_TOINT) : static_cast<BLOCKTYPE>(E_BLOCK_AIR); BLOCKTYPE BlockAtFoot = (cChunkDef::IsValidHeight(POS_TOINT)) ? GetWorld()->GetBlock(POS_TOINT) : static_cast<BLOCKTYPE>(E_BLOCK_AIR);
/* We initialize these with what the foot is really IN, because for sampling we will move down with the epsilon above */ /* We initialize these with what the foot is really IN, because for sampling we will move down with the epsilon above */
bool IsFootInWater = IsBlockWater(BlockAtFoot); bool IsFootInWater = IsBlockWater(BlockAtFoot);
@ -364,7 +364,7 @@ void cPawn::HandleFalling(void)
{ {
Vector3i BlockTestPosition = CrossTestPosition.Floor() + BlockSampleOffsets[j]; Vector3i BlockTestPosition = CrossTestPosition.Floor() + BlockSampleOffsets[j];
if (!cChunkDef::IsValidHeight(BlockTestPosition.y)) if (!cChunkDef::IsValidHeight(BlockTestPosition))
{ {
continue; continue;
} }

View File

@ -2192,7 +2192,7 @@ bool cPlayer::IsClimbing(void) const
{ {
const auto Position = GetPosition().Floor(); const auto Position = GetPosition().Floor();
if (!cChunkDef::IsValidHeight(Position.y)) if (!cChunkDef::IsValidHeight(Position))
{ {
return false; return false;
} }
@ -2579,7 +2579,7 @@ bool cPlayer::IsInsideWater()
{ {
const auto EyePos = GetEyePosition().Floor(); const auto EyePos = GetEyePosition().Floor();
if (!cChunkDef::IsValidHeight(EyePos.y)) if (!cChunkDef::IsValidHeight(EyePos))
{ {
// Not in water if in void. // Not in water if in void.
return false; return false;

View File

@ -555,7 +555,7 @@ void cFinishGenTallGrass::GenFinish(cChunkDesc & a_ChunkDesc)
) )
{ {
y--; y--;
if (!cChunkDef::IsValidHeight(y - 1)) if (!cChunkDef::IsValidHeight({x, y - 1, z}))
{ {
failed = true; failed = true;
break; break;
@ -1986,7 +1986,7 @@ void cFinishGenOreNests::GenerateOre(
for (int y = ysize; y >= 0; --y) for (int y = ysize; y >= 0; --y)
{ {
int BlockY = BaseY + y; int BlockY = BaseY + y;
if (!cChunkDef::IsValidHeight(BlockY)) if (!cChunkDef::IsValidHeight({BlockX, BlockY, BaseZ}))
{ {
Num++; // So that the cycle finishes even if the base coords wander away from the chunk Num++; // So that the cycle finishes even if the base coords wander away from the chunk
continue; continue;

View File

@ -70,7 +70,7 @@ public:
// Block above must be air to spawn a boat (prevents spawning a boat underwater) // Block above must be air to spawn a boat (prevents spawning a boat underwater)
auto PosAbove = Callbacks.m_Pos.Floor().addedY(1); auto PosAbove = Callbacks.m_Pos.Floor().addedY(1);
if (!cChunkDef::IsValidHeight(PosAbove.y)) if (!cChunkDef::IsValidHeight(PosAbove))
{ {
return false; return false;
} }

View File

@ -365,7 +365,7 @@ public:
) )
{ {
if ( if (
!cChunkDef::IsValidHeight(Position.y) || !cChunkDef::IsValidHeight(Position) ||
(a_World.GetBlock(Position) != E_BLOCK_GRASS) // Are we looking at grass? (a_World.GetBlock(Position) != E_BLOCK_GRASS) // Are we looking at grass?
) )
{ {

View File

@ -1063,7 +1063,7 @@ void cItemHandler::OnPlayerPlace(cPlayer & a_Player, const cItem & a_HeldItem, c
NIBBLETYPE PlaceMeta; NIBBLETYPE PlaceMeta;
const auto PlacePosition = AddFaceDirection(a_ClickedPosition, a_ClickedBlockFace); const auto PlacePosition = AddFaceDirection(a_ClickedPosition, a_ClickedBlockFace);
if (!cChunkDef::IsValidHeight(PlacePosition.y) || !World.GetBlockTypeMeta(PlacePosition, PlaceBlock, PlaceMeta)) if (!cChunkDef::IsValidHeight(PlacePosition) || !World.GetBlockTypeMeta(PlacePosition, PlaceBlock, PlaceMeta))
{ {
// The block is being placed outside the world, ignore this packet altogether (GH #128): // The block is being placed outside the world, ignore this packet altogether (GH #128):
return; return;

View File

@ -57,7 +57,7 @@ public:
} }
const auto FirePos = AddFaceDirection(a_ClickedBlockPos, a_ClickedBlockFace); const auto FirePos = AddFaceDirection(a_ClickedBlockPos, a_ClickedBlockFace);
if (!cChunkDef::IsValidHeight(FirePos.y)) if (!cChunkDef::IsValidHeight(FirePos))
{ {
return false; return false;
} }

View File

@ -79,7 +79,7 @@ bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, Vector3i a_RelPos, eMonsterType
return false; return false;
} }
if (cChunkDef::IsValidHeight(a_RelPos.y - 1) && (a_Chunk->GetBlock(a_RelPos.addedY(-1)) == E_BLOCK_BEDROCK)) if (cChunkDef::IsValidHeight(a_RelPos.addedY(-1)) && (a_Chunk->GetBlock(a_RelPos.addedY(-1)) == E_BLOCK_BEDROCK))
{ {
return false; // Make sure mobs do not spawn on bedrock. return false; // Make sure mobs do not spawn on bedrock.
} }

View File

@ -480,7 +480,7 @@ void cPath::FillCellAttributes(cPathCell & a_Cell)
ASSERT(m_Chunk != nullptr); ASSERT(m_Chunk != nullptr);
if (!cChunkDef::IsValidHeight(Location.y)) if (!cChunkDef::IsValidHeight(Location))
{ {
// Players can't build outside the game height, so it must be air // Players can't build outside the game height, so it must be air
a_Cell.m_IsSolid = false; a_Cell.m_IsSolid = false;

View File

@ -185,74 +185,78 @@ bool cPathFinder::EnsureProperPoint(Vector3d & a_Vector, cChunk & a_Chunk)
return false; return false;
} }
int RelX = FloorC(a_Vector.x) - Chunk->GetPosX() * cChunkDef::Width;
int RelZ = FloorC(a_Vector.z) - Chunk->GetPosZ() * cChunkDef::Width;
// If destination in the air, first try to go 1 block north, or east, or west. // If destination in the air, first try to go 1 block north, or east, or west.
// This fixes the player leaning issue. // This fixes the player leaning issue.
// If that failed, we instead go down to the lowest air block. // If that failed, we instead go down to the lowest air block.
int YBelowUs = FloorC(a_Vector.y) - 1; auto Below = a_Vector.Floor().addedY(-1);
if (!cChunkDef::IsValidHeight(YBelowUs)) if (!cChunkDef::IsValidHeight(Below))
{ {
return false; return false;
} }
Chunk->GetBlockTypeMeta(RelX, YBelowUs, RelZ, BlockType, BlockMeta); auto BelowRel = cChunkDef::AbsoluteToRelative(Below);
Chunk->GetBlockTypeMeta(BelowRel, BlockType, BlockMeta);
if (!(IsWaterOrSolid(BlockType))) if (!(IsWaterOrSolid(BlockType)))
{ {
bool InTheAir = true; constexpr std::array<Vector3i, 8> Offsets =
int x, z;
for (z = -1; z <= 1; ++z)
{ {
for (x = -1; x <= 1; ++x)
{ {
if ((x == 0) && (z == 0)) {-1, 0, 0},
{ {1, 0, 0},
continue; {0, 0, -1},
} {0, 0, 1},
Chunk = a_Chunk.GetNeighborChunk(FloorC(a_Vector.x+x), FloorC(a_Vector.z+z)); {-1, 0, -1},
if ((Chunk == nullptr) || !Chunk->IsValid()) {-1, 0, 1},
{ {1, 0, -1},
return false; {1, 0, 1},
} }
RelX = FloorC(a_Vector.x+x) - Chunk->GetPosX() * cChunkDef::Width; };
RelZ = FloorC(a_Vector.z+z) - Chunk->GetPosZ() * cChunkDef::Width;
Chunk->GetBlockTypeMeta(RelX, YBelowUs, RelZ, BlockType, BlockMeta); // Looks for a neighbouring block one block in x or z direction that is water or solid.
if (IsWaterOrSolid((BlockType))) bool InTheAir = true;
{ for (const auto & Offset : Offsets)
a_Vector.x += x; {
a_Vector.z += z; auto InspectPos = Below + Offset;
InTheAir = false; Chunk = a_Chunk.GetNeighborChunk(InspectPos.x, InspectPos.z);
goto breakBothLoops; if ((Chunk == nullptr) || !Chunk->IsValid())
} {
return false;
}
auto InspectRel = cChunkDef::AbsoluteToRelative(InspectPos);
Chunk->GetBlockTypeMeta(InspectRel, BlockType, BlockMeta);
if (IsWaterOrSolid((BlockType)))
{
BelowRel = InspectRel;
InTheAir = false;
break;
} }
} }
breakBothLoops:
// Go down to the lowest air block. // Go down to the lowest air block.
if (InTheAir) if (InTheAir)
{ {
while (a_Vector.y > 0) while (cChunkDef::IsValidHeight(a_Vector.addedY(-1)))
{ {
Chunk->GetBlockTypeMeta(RelX, FloorC(a_Vector.y) - 1, RelZ, BlockType, BlockMeta); Chunk->GetBlockTypeMeta(BelowRel.addedY(-1), BlockType, BlockMeta);
if (IsWaterOrSolid(BlockType)) if (IsWaterOrSolid(BlockType))
{ {
break; break;
} }
a_Vector.y -= 1; BelowRel.y -= 1;
} }
} }
} }
// If destination in water or solid, go up to the first air block. // If destination in water or solid, go up to the first air block.
while (a_Vector.y < cChunkDef::Height) while (BelowRel.y < cChunkDef::Height)
{ {
Chunk->GetBlockTypeMeta(RelX, FloorC(a_Vector.y), RelZ, BlockType, BlockMeta); Chunk->GetBlockTypeMeta(BelowRel, BlockType, BlockMeta);
if (!IsWaterOrSolid(BlockType)) if (!IsWaterOrSolid(BlockType))
{ {
break; break;
} }
a_Vector.y += 1; BelowRel.y += 1;
} }
return true; return true;

View File

@ -342,7 +342,7 @@ namespace Explodinator
while (a_Intensity > 0) while (a_Intensity > 0)
{ {
auto Position = Checkpoint.Floor(); auto Position = Checkpoint.Floor();
if (!cChunkDef::IsValidHeight(Position.y)) if (!cChunkDef::IsValidHeight(Position))
{ {
break; break;
} }

View File

@ -600,7 +600,7 @@ void cProtocol_1_11_0::HandlePacketBlockPlace(cByteBuffer & a_ByteBuffer)
HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, CursorY); HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, CursorY);
HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, CursorZ); HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, CursorZ);
m_Client->HandleRightClick(Position, FaceIntToBlockFace(Face), FloorC(CursorX * 16), FloorC(CursorY * 16), FloorC(CursorZ * 16), Hand == 0); m_Client->HandleRightClick(Position, FaceIntToBlockFace(Face), {FloorC(CursorX * 16), FloorC(CursorY * 16), FloorC(CursorZ * 16)}, Hand == 0);
} }

View File

@ -2381,7 +2381,7 @@ void cProtocol_1_8_0::HandlePacketBlockPlace(cByteBuffer & a_ByteBuffer)
} }
else else
{ {
m_Client->HandleRightClick(BlockPos, blockFace, CursorX, CursorY, CursorZ, true); m_Client->HandleRightClick(BlockPos, blockFace, {CursorX, CursorY, CursorZ}, true);
} }
} }
@ -2553,7 +2553,7 @@ void cProtocol_1_8_0::HandlePacketPlayerPos(cByteBuffer & a_ByteBuffer)
HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, PosZ); HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, PosZ);
HANDLE_READ(a_ByteBuffer, ReadBool, bool, IsOnGround); HANDLE_READ(a_ByteBuffer, ReadBool, bool, IsOnGround);
m_Client->HandlePlayerMove(PosX, PosY, PosZ, IsOnGround); m_Client->HandlePlayerMove({PosX, PosY, PosZ}, IsOnGround);
} }
@ -2569,7 +2569,7 @@ void cProtocol_1_8_0::HandlePacketPlayerPosLook(cByteBuffer & a_ByteBuffer)
HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, Pitch); HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, Pitch);
HANDLE_READ(a_ByteBuffer, ReadBool, bool, IsOnGround); HANDLE_READ(a_ByteBuffer, ReadBool, bool, IsOnGround);
m_Client->HandlePlayerMoveLook(PosX, PosY, PosZ, Yaw, Pitch, IsOnGround); m_Client->HandlePlayerMoveLook({PosX, PosY, PosZ}, Yaw, Pitch, IsOnGround);
} }

View File

@ -901,7 +901,7 @@ void cProtocol_1_9_0::HandlePacketBlockPlace(cByteBuffer & a_ByteBuffer)
HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, CursorY); HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, CursorY);
HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, CursorZ); HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, CursorZ);
m_Client->HandleRightClick(Position, FaceIntToBlockFace(Face), CursorX, CursorY, CursorZ, Hand == MAIN_HAND); m_Client->HandleRightClick(Position, FaceIntToBlockFace(Face), {CursorX, CursorY, CursorZ}, Hand == MAIN_HAND);
} }
@ -1003,7 +1003,7 @@ void cProtocol_1_9_0::HandlePacketPlayerPos(cByteBuffer & a_ByteBuffer)
if (m_IsTeleportIdConfirmed) if (m_IsTeleportIdConfirmed)
{ {
m_Client->HandlePlayerMove(PosX, PosY, PosZ, IsOnGround); m_Client->HandlePlayerMove({PosX, PosY, PosZ}, IsOnGround);
} }
} }
@ -1022,7 +1022,7 @@ void cProtocol_1_9_0::HandlePacketPlayerPosLook(cByteBuffer & a_ByteBuffer)
if (m_IsTeleportIdConfirmed) if (m_IsTeleportIdConfirmed)
{ {
m_Client->HandlePlayerMoveLook(PosX, PosY, PosZ, Yaw, Pitch, IsOnGround); m_Client->HandlePlayerMoveLook({PosX, PosY, PosZ}, Yaw, Pitch, IsOnGround);
} }
} }

View File

@ -145,7 +145,7 @@ void cDelayedFluidSimulator::AddBlock(cChunk & a_Chunk, Vector3i a_Position, BLO
void cDelayedFluidSimulator::WakeUp(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block) void cDelayedFluidSimulator::WakeUp(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block)
{ {
if (!cChunkDef::IsValidHeight(a_Position.y)) if (!cChunkDef::IsValidHeight(a_Position))
{ {
// Not inside the world (may happen when rclk with a full bucket - the client sends Y = -1) // Not inside the world (may happen when rclk with a full bucket - the client sends Y = -1)
return; return;

View File

@ -130,14 +130,14 @@ bool cFluidSimulator::IsHigherMeta(NIBBLETYPE a_Meta1, NIBBLETYPE a_Meta2)
Vector3f cFluidSimulator::GetFlowingDirection(int a_X, int a_Y, int a_Z) Vector3f cFluidSimulator::GetFlowingDirection(Vector3i a_Pos)
{ {
if (!cChunkDef::IsValidHeight(a_Y)) if (!cChunkDef::IsValidHeight(a_Pos))
{ {
return {}; return {};
} }
if (!IsAllowedBlock(m_World.GetBlock({ a_X, a_Y, a_Z }))) // No Fluid -> No Flowing direction :D if (!IsAllowedBlock(m_World.GetBlock(a_Pos))) // No Fluid -> No Flowing direction :D
{ {
return {}; return {};
} }
@ -148,24 +148,24 @@ Vector3f cFluidSimulator::GetFlowingDirection(int a_X, int a_Y, int a_Z)
return ((a_BlockMeta & 0x08) != 0) ? 0 : a_BlockMeta; return ((a_BlockMeta & 0x08) != 0) ? 0 : a_BlockMeta;
}; };
auto BlockMeta = m_World.GetBlockMeta({ a_X, a_Y, a_Z }); auto BlockMeta = m_World.GetBlockMeta(a_Pos);
NIBBLETYPE CentralPoint = HeightFromMeta(BlockMeta); NIBBLETYPE CentralPoint = HeightFromMeta(BlockMeta);
NIBBLETYPE LevelPoint[4]; NIBBLETYPE LevelPoint[4];
// blocks around the checking pos // blocks around the checking pos
Vector3i Points[] std::array<Vector3i, 4> Offsets {
{ {
{ a_X + 1, a_Y, a_Z }, { 1, 0, 0 },
{ a_X, a_Y, a_Z + 1 }, { 0, 0, 1 },
{ a_X - 1, a_Y, a_Z }, { 1, 0, 0 },
{ a_X, a_Y, a_Z - 1 } { 0, 0, 1 }
}; }};
for (size_t i = 0; i < ARRAYCOUNT(LevelPoint); i++) for (size_t i = 0; i < Offsets.size(); i++)
{ {
if (IsAllowedBlock(m_World.GetBlock(Points[i]))) if (IsAllowedBlock(m_World.GetBlock(a_Pos + Offsets[i])))
{ {
LevelPoint[i] = HeightFromMeta(m_World.GetBlockMeta(Points[i])); LevelPoint[i] = HeightFromMeta(m_World.GetBlockMeta(Offsets[i]));
} }
else else
{ {

View File

@ -44,7 +44,7 @@ public:
cFluidSimulator(cWorld & a_World, BLOCKTYPE a_Fluid, BLOCKTYPE a_StationaryFluid); cFluidSimulator(cWorld & a_World, BLOCKTYPE a_Fluid, BLOCKTYPE a_StationaryFluid);
/** Returns a unit vector in the direction the fluid is flowing or a zero-vector if not flowing. */ /** Returns a unit vector in the direction the fluid is flowing or a zero-vector if not flowing. */
virtual Vector3f GetFlowingDirection(int a_X, int a_Y, int a_Z); virtual Vector3f GetFlowingDirection(Vector3i a_Pos);
/** Creates a ChunkData object for the simulator to use. The simulator returns the correct object type. */ /** Creates a ChunkData object for the simulator to use. The simulator returns the correct object type. */
virtual cFluidSimulatorData * CreateChunkData(void) = 0; virtual cFluidSimulatorData * CreateChunkData(void) = 0;

View File

@ -26,7 +26,7 @@ ForEachSourceCallback::ForEachSourceCallback(const cChunk & Chunk, const Vector3
void ForEachSourceCallback::operator()(Vector3i Location) void ForEachSourceCallback::operator()(Vector3i Location)
{ {
if (!cChunkDef::IsValidHeight(Location.y)) if (!cChunkDef::IsValidHeight(Location))
{ {
return; return;
} }
@ -96,7 +96,7 @@ PowerLevel ForEachSourceCallback::QueryLinkedPower(const cChunk & Chunk, const V
for (const auto & Offset : cSimulator::GetLinkedOffsets(SolidBlockPosition - QueryPosition)) for (const auto & Offset : cSimulator::GetLinkedOffsets(SolidBlockPosition - QueryPosition))
{ {
auto SourcePosition = QueryPosition + Offset; auto SourcePosition = QueryPosition + Offset;
if (!cChunkDef::IsValidHeight(SourcePosition.y)) if (!cChunkDef::IsValidHeight(SourcePosition))
{ {
continue; continue;
} }

View File

@ -217,7 +217,7 @@ void cIncrementalRedstoneSimulator::WakeUp(cChunk & a_Chunk, Vector3i a_Position
for (const auto & Offset : cSimulator::GetLinkedOffsets(a_Offset)) for (const auto & Offset : cSimulator::GetLinkedOffsets(a_Offset))
{ {
auto Relative = a_Position - a_Offset + Offset; auto Relative = a_Position - a_Offset + Offset;
if (!cChunkDef::IsValidHeight(Relative.y)) if (!cChunkDef::IsValidHeight(Relative))
{ {
continue; continue;
} }

View File

@ -313,7 +313,7 @@ namespace RedstoneWireHandler
const auto YMDiagonalPosition = Relative + OffsetYM; const auto YMDiagonalPosition = Relative + OffsetYM;
if ( if (
BLOCKTYPE QueryBlock; BLOCKTYPE QueryBlock;
cChunkDef::IsValidHeight(YMDiagonalPosition.y) && cChunkDef::IsValidHeight(YMDiagonalPosition) &&
a_Chunk.UnboundedRelGetBlockType(YMDiagonalPosition, QueryBlock) && a_Chunk.UnboundedRelGetBlockType(YMDiagonalPosition, QueryBlock) &&
(QueryBlock == E_BLOCK_REDSTONE_WIRE) (QueryBlock == E_BLOCK_REDSTONE_WIRE)
) )

View File

@ -71,7 +71,7 @@ void cSimulatorManager::WakeUp(cChunk & a_Chunk, Vector3i a_Position)
for (const auto & Offset : cSimulator::AdjacentOffsets) for (const auto & Offset : cSimulator::AdjacentOffsets)
{ {
auto Relative = a_Position + Offset; auto Relative = a_Position + Offset;
if (!cChunkDef::IsValidHeight(Relative.y)) if (!cChunkDef::IsValidHeight(Relative))
{ {
continue; continue;
} }

View File

@ -850,42 +850,37 @@ bool cWorld::CanSpawnAt(int a_X, int & a_Y, int a_Z)
bool cWorld::CheckPlayerSpawnPoint(int a_PosX, int a_PosY, int a_PosZ) bool cWorld::CheckPlayerSpawnPoint(Vector3i a_Pos)
{ {
// Check height bounds // Check height bounds
if (!cChunkDef::IsValidHeight(a_PosY)) if (!cChunkDef::IsValidHeight(a_Pos))
{ {
return false; return false;
} }
// Check that surrounding blocks are neither solid or liquid // Check that surrounding blocks are neither solid or liquid
static const Vector3i SurroundingCoords[] = constexpr std::array<Vector3i, 8> SurroundingCoords =
{{
{0, 0, 1},
{1, 0, 1},
{1, 0, 0},
{1, 0, -1},
{0, 0, -1},
{-1, 0, -1},
{-1, 0, 0},
{-1, 0, 1},
}};
for (const auto & Offset : SurroundingCoords)
{ {
Vector3i(0, 0, 1), const BLOCKTYPE BlockType = GetBlock(a_Pos + Offset);
Vector3i(1, 0, 1),
Vector3i(1, 0, 0),
Vector3i(1, 0, -1),
Vector3i(0, 0, -1),
Vector3i(-1, 0, -1),
Vector3i(-1, 0, 0),
Vector3i(-1, 0, 1),
};
static const int SurroundingCoordsCount = ARRAYCOUNT(SurroundingCoords);
for (int CoordIndex = 0; CoordIndex < SurroundingCoordsCount; ++CoordIndex)
{
const int XPos = a_PosX + SurroundingCoords[CoordIndex].x;
const int ZPos = a_PosZ + SurroundingCoords[CoordIndex].z;
const BLOCKTYPE BlockType = GetBlock({ XPos, a_PosY, ZPos });
if (cBlockInfo::IsSolid(BlockType) || IsBlockLiquid(BlockType)) if (cBlockInfo::IsSolid(BlockType) || IsBlockLiquid(BlockType))
{ {
return false; return true;
} }
} }
return true; return false;
} }

View File

@ -311,12 +311,7 @@ public:
void ChunkLoadFailed(int a_ChunkX, int a_ChunkZ); void ChunkLoadFailed(int a_ChunkX, int a_ChunkZ);
/** Sets the sign text, asking plugins for permission first. a_Player is the player who this change belongs to, may be nullptr. Returns true if sign text changed. */ /** Sets the sign text, asking plugins for permission first. a_Player is the player who this change belongs to, may be nullptr. Returns true if sign text changed. */
bool SetSignLines(Vector3i a_BlockPos, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player = nullptr); bool SetSignLines(Vector3i a_BlockPos, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player = nullptr); // Exported in ManualBindings.cpp
bool SetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player = nullptr) // Exported in ManualBindings.cpp
{
return SetSignLines({a_BlockX, a_BlockY, a_BlockZ}, a_Line1, a_Line2, a_Line3, a_Line4, a_Player);
}
/** Sets the command block command. Returns true if command changed. */ /** Sets the command block command. Returns true if command changed. */
bool SetCommandBlockCommand(int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Command); // tolua_export bool SetCommandBlockCommand(int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Command); // tolua_export
@ -1137,7 +1132,11 @@ private:
bool CanSpawnAt(int a_X, int & a_Y, int a_Z); bool CanSpawnAt(int a_X, int & a_Y, int a_Z);
/** Check if player starting point is acceptable */ /** Check if player starting point is acceptable */
bool CheckPlayerSpawnPoint(int a_PosX, int a_PosY, int a_PosZ); bool CheckPlayerSpawnPoint(int a_PosX, int a_PosY, int a_PosZ)
{
return CheckPlayerSpawnPoint({a_PosX, a_PosY, a_PosZ});
}
bool CheckPlayerSpawnPoint(Vector3i a_Pos);
/** Chooses a reasonable transition from the current weather to a new weather */ /** Chooses a reasonable transition from the current weather to a new weather */
eWeather ChooseNewWeather(void); eWeather ChooseNewWeather(void);