From 12deaca1cfb92c04abec8234395e6e283f10cd6a Mon Sep 17 00:00:00 2001 From: EJHacks Date: Thu, 12 Mar 2026 08:45:21 -0400 Subject: [PATCH] fix: resolve "Course data can't be loaded" on 3DS Recommended Courses (#21) - Use LEFT JOIN instead of INNER JOIN in GetRandomCoursesWithLimit so courses without custom ranking entries (unrated) are included in results - Use COALESCE(ranking.value, 0) to default unrated courses to score 0 - Move object filters from JOIN ON clause to WHERE clause - Add input length validation to CTRPickUpCourseSearchObject (cap at 25) - Remove unreachable sql.ErrNoRows check (Query never returns it) --- .../get_random_courses_with_limit.go | 15 +++++---------- .../ctr_pick_up_course_search_object.go | 9 ++++++++- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/database/datastore/super-mario-maker/get_random_courses_with_limit.go b/database/datastore/super-mario-maker/get_random_courses_with_limit.go index 103bd5a..02fb39c 100644 --- a/database/datastore/super-mario-maker/get_random_courses_with_limit.go +++ b/database/datastore/super-mario-maker/get_random_courses_with_limit.go @@ -1,7 +1,6 @@ package datastore_smm_db import ( - "database/sql" "time" "github.com/PretendoNetwork/nex-go/v2" @@ -35,26 +34,22 @@ func GetRandomCoursesWithLimit(limit int) (types.List[datastore_super_mario_make object.tags, object.creation_date, object.update_date, - ranking.value + COALESCE(ranking.value, 0) FROM datastore.objects object - JOIN datastore.object_custom_rankings ranking + LEFT JOIN datastore.object_custom_rankings ranking ON object.data_id = ranking.data_id AND + ranking.application_id = 0 + WHERE object.upload_completed = TRUE AND object.deleted = FALSE AND - object.under_review = FALSE AND - ranking.application_id = 0 + object.under_review = FALSE ORDER BY RANDOM() LIMIT $1 `, limit) if err != nil { - if err == sql.ErrNoRows { - return nil, nex.NewError(nex.ResultCodes.DataStore.NotFound, "Object not found") - } - globals.Logger.Error(err.Error()) - // TODO - Send more specific errors? return nil, nex.NewError(nex.ResultCodes.DataStore.Unknown, err.Error()) } diff --git a/nex/datastore/super-mario-maker/ctr_pick_up_course_search_object.go b/nex/datastore/super-mario-maker/ctr_pick_up_course_search_object.go index d3591c5..4157fd2 100644 --- a/nex/datastore/super-mario-maker/ctr_pick_up_course_search_object.go +++ b/nex/datastore/super-mario-maker/ctr_pick_up_course_search_object.go @@ -30,7 +30,14 @@ func CTRPickUpCourseSearchObject(err error, packet nex.PacketInterface, callID u // TODO - Research extraData // TODO - Use the offet? Real client never uses it, but might be nice for completeness sake? - pRankingResults, nexError := datastore_smm_db.GetRandomCoursesWithLimit(int(param.ResultRange.Length)) + length := int(param.ResultRange.Length) + maxLength := 25 + if length <= 0 || length > maxLength { + globals.Logger.Warningf("Limiting request to %d courses (was %d)", maxLength, length) + length = maxLength + } + + pRankingResults, nexError := datastore_smm_db.GetRandomCoursesWithLimit(length) if nexError != nil { return nil, nexError }