Also index on xf_resource (resource_state, resource_category_id) yes that way round, for:
SELECT resource.*,
category.*, category.last_update AS category_last_update, resource.last_update,
version.version_string,
version.release_date,
version.download_url,
version.rating_count AS version_rating_count,
version.rating_sum AS version_rating_sum,
version.download_count AS version_download_count,
user.*, user_profile.*, IF(user.username IS NULL, resource.username, user.username) AS username,
feature.feature_date
FROM xf_resource AS resource
LEFT JOIN xf_resource_category AS category ON
(category.resource_category_id = resource.resource_category_id)
LEFT JOIN xf_resource_version AS version ON
(version.resource_version_id = resource.current_version_id)
LEFT JOIN xf_user AS user ON
(user.user_id = resource.user_id)
LEFT JOIN xf_user_profile AS user_profile ON
(user_profile.user_id = resource.user_id)
LEFT JOIN xf_resource_feature AS feature ON
(feature.resource_id = resource.resource_id)
WHERE (resource.resource_category_id IN (4, 1, 12, 13, 2, 3, 5, 6, 7, 8, 9, 11, 10)) AND (resource.resource_state IN ('visible'))
ORDER BY resource.rating_weighted DESC, resource.last_update DESC
LIMIT 20;
For references this forum is running on MySQL 5.6