Skip to content

Commit

Permalink
Allow the player to dig the node the camera is into
Browse files Browse the repository at this point in the history
That allows them to escape from being unable to move due to being trapped with the camera inside a node (assuming the node is diggable).

Note: The implementation is a bit of a hack. It doesn't consider the lookAt direction.
  • Loading branch information
Pedro Gimeno authored and Unarelith committed Feb 18, 2020
1 parent e5b5ba9 commit ae9b47e
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 6 deletions.
40 changes: 35 additions & 5 deletions client/source/hud/BlockCursor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,19 +250,49 @@ void BlockCursor::draw(gk::RenderTarget &target, gk::RenderStates states) const
}

glm::ivec4 BlockCursor::findSelectedBlock() const {
glm::dvec3 lookAt{m_player.pointTargetedX() - m_player.camera().getPosition().x,
m_player.pointTargetedY() - m_player.camera().getPosition().y,
m_player.pointTargetedZ() - m_player.camera().getPosition().z};

glm::dvec3 position{m_player.camera().getPosition().x,
m_player.camera().getPosition().y,
m_player.camera().getPosition().z};

int_fast32_t bestX = int_fast32_t(floor(position.x));
int_fast32_t bestY = int_fast32_t(floor(position.y));
int_fast32_t bestZ = int_fast32_t(floor(position.z));

// Deal with a degenerate case: camera in the middle of a block
uint_fast32_t blockID = m_world.getBlock(bestX, bestY, bestZ);
const Block &block = Registry::getInstance().getBlock(blockID);
if(blockID && block.drawType() != BlockDrawType::Liquid) {
// We're inside a node, therefore there's no face, but we still need
// to return a valid block. We use face 6 for that. For rightclicks,
// it should attempt to place the block on the same node clicked, and
// fail because it's already occupied. For digs, it should just dig
// the node.
return glm::ivec4{bestX, bestY, bestZ, 6};
}

// Still the degenerate case, but this time for the sub-case where
// the coordinates of the player are exact integers, thus lying exactly
// between two faces (or four, if it's in a corner). In this situation,
// the raycasting algorithm allows us to get rid of all blocks except for
// the one in the northwest corner. Deal with that case here.
// NOTE: We don't deal with height because it's unlikely that the
// camera ends up being at an integer position.
if(double(bestX) == position.x && double(bestZ) == position.z) {
blockID = m_world.getBlock(bestX - 1, bestY, bestZ - 1);
const Block &block = Registry::getInstance().getBlock(blockID);
if(blockID && block.drawType() != BlockDrawType::Liquid) {
return glm::ivec4{bestX - 1, bestY, bestZ - 1, 6};
}
}

glm::dvec3 lookAt{m_player.pointTargetedX() - m_player.camera().getPosition().x,
m_player.pointTargetedY() - m_player.camera().getPosition().y,
m_player.pointTargetedZ() - m_player.camera().getPosition().z};

// Ray casting algorithm to find out which block we are looking at
const double maxReach = 10.;
double bestDepth;
int_fast8_t bestFace = -1;
int_fast32_t bestX = 0, bestY = 0, bestZ = 0;

glm::dvec3 lookAtN = glm::normalize(lookAt);

Expand Down
2 changes: 1 addition & 1 deletion client/source/math/BlockCursorRaycast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ void BlockCursorRaycast::rayCastToAxis(const Axis axis, const glm::dvec3 &positi
break;
}

int_fast32_t firstNodeRow = int_fast32_t(floor(posCoord));
int_fast32_t firstNodeRow = lookAtCoord < 0. ? int_fast32_t(floor(posCoord)) : int_fast32_t(ceil(posCoord)) - 1;
int_fast32_t lastNodeRow = int_fast32_t(floor(posCoord + lookAtCoord * maxReach));

int_fast8_t dir = (lookAtCoord > 0.) - (lookAtCoord < 0.);
Expand Down

0 comments on commit ae9b47e

Please sign in to comment.