/** * Checks for blocks around the entity. * * @param origin The original position of the entity * @return True if the entity is colliding horizontally */ private boolean horizontalHitTest(Vector3d origin) { boolean result = false; ArrayList<BlockPosition> blockPositions = gatherAdjacentBlockPositions(origin); // Check each block position for collision for (int i = 0; i < blockPositions.size(); i++) { BlockPosition p = blockPositions.get(i); byte blockType = _parent.getWorldProvider().getBlockAtPosition(new Vector3d(p.x, p.y, p.z)); AABB blockAABB = Block.AABBForBlockAt(p.x, p.y, p.z); if (!BlockManager.getInstance().getBlock(blockType).isPenetrable()) { if (getAABB().overlaps(blockAABB)) { result = true; // Calculate the direction from the origin to the current position Vector3d direction = new Vector3d(getPosition().x, 0f, getPosition().z); direction.x -= origin.x; direction.z -= origin.z; // Calculate the point of intersection on the block's AABB Vector3d blockPoi = blockAABB.closestPointOnAABBToPoint(origin); Vector3d entityPoi = generateAABBForPosition(origin).closestPointOnAABBToPoint(blockPoi); Vector3d planeNormal = blockAABB.normalForPlaneClosestToOrigin(blockPoi, origin, true, false, true); // Find a vector parallel to the surface normal Vector3d slideVector = new Vector3d(planeNormal.z, 0, -planeNormal.x); Vector3d pushBack = new Vector3d(); pushBack.sub(blockPoi, entityPoi); // Calculate the intensity of the diversion alongside the block double length = slideVector.dot(direction); Vector3d newPosition = new Vector3d(); newPosition.z = origin.z + pushBack.z * 0.2 + length * slideVector.z; newPosition.x = origin.x + pushBack.x * 0.2 + length * slideVector.x; newPosition.y = origin.y; // Update the position getPosition().set(newPosition); } } } return result; }