X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Fscreens.c;h=a5b808a1969462bac0a1bc7b1aefd001a1b49cb3;hp=30bb2b20ee43b65fea9d8ed112b4aea9a694df89;hb=274876d86fc0cb9af7027df86bf4ac46020c1501;hpb=fa64f97687b19543379b872003cd66a2a351e326 diff --git a/src/screens.c b/src/screens.c index 30bb2b20..a5b808a1 100644 --- a/src/screens.c +++ b/src/screens.c @@ -63,30 +63,31 @@ #define SETUP_MODE_CHOOSE_OTHER 16 // sub-screens on the setup screen (specific) -#define SETUP_MODE_CHOOSE_GAME_SPEED 17 -#define SETUP_MODE_CHOOSE_SCROLL_DELAY 18 -#define SETUP_MODE_CHOOSE_SNAPSHOT_MODE 19 -#define SETUP_MODE_CHOOSE_WINDOW_SIZE 20 -#define SETUP_MODE_CHOOSE_SCALING_TYPE 21 -#define SETUP_MODE_CHOOSE_RENDERING 22 -#define SETUP_MODE_CHOOSE_VSYNC 23 -#define SETUP_MODE_CHOOSE_GRAPHICS 24 -#define SETUP_MODE_CHOOSE_SOUNDS 25 -#define SETUP_MODE_CHOOSE_MUSIC 26 -#define SETUP_MODE_CHOOSE_VOLUME_SIMPLE 27 -#define SETUP_MODE_CHOOSE_VOLUME_LOOPS 28 -#define SETUP_MODE_CHOOSE_VOLUME_MUSIC 29 -#define SETUP_MODE_CHOOSE_TOUCH_CONTROL 30 -#define SETUP_MODE_CHOOSE_MOVE_DISTANCE 31 -#define SETUP_MODE_CHOOSE_DROP_DISTANCE 32 -#define SETUP_MODE_CHOOSE_TRANSPARENCY 33 -#define SETUP_MODE_CHOOSE_GRID_XSIZE_0 34 -#define SETUP_MODE_CHOOSE_GRID_YSIZE_0 35 -#define SETUP_MODE_CHOOSE_GRID_XSIZE_1 36 -#define SETUP_MODE_CHOOSE_GRID_YSIZE_1 37 -#define SETUP_MODE_CONFIG_VIRT_BUTTONS 38 - -#define MAX_SETUP_MODES 39 +#define SETUP_MODE_CHOOSE_SCORES_TYPE 17 +#define SETUP_MODE_CHOOSE_GAME_SPEED 18 +#define SETUP_MODE_CHOOSE_SCROLL_DELAY 19 +#define SETUP_MODE_CHOOSE_SNAPSHOT_MODE 20 +#define SETUP_MODE_CHOOSE_WINDOW_SIZE 21 +#define SETUP_MODE_CHOOSE_SCALING_TYPE 22 +#define SETUP_MODE_CHOOSE_RENDERING 23 +#define SETUP_MODE_CHOOSE_VSYNC 24 +#define SETUP_MODE_CHOOSE_GRAPHICS 25 +#define SETUP_MODE_CHOOSE_SOUNDS 26 +#define SETUP_MODE_CHOOSE_MUSIC 27 +#define SETUP_MODE_CHOOSE_VOLUME_SIMPLE 28 +#define SETUP_MODE_CHOOSE_VOLUME_LOOPS 29 +#define SETUP_MODE_CHOOSE_VOLUME_MUSIC 30 +#define SETUP_MODE_CHOOSE_TOUCH_CONTROL 31 +#define SETUP_MODE_CHOOSE_MOVE_DISTANCE 32 +#define SETUP_MODE_CHOOSE_DROP_DISTANCE 33 +#define SETUP_MODE_CHOOSE_TRANSPARENCY 34 +#define SETUP_MODE_CHOOSE_GRID_XSIZE_0 35 +#define SETUP_MODE_CHOOSE_GRID_YSIZE_0 36 +#define SETUP_MODE_CHOOSE_GRID_XSIZE_1 37 +#define SETUP_MODE_CHOOSE_GRID_YSIZE_1 38 +#define SETUP_MODE_CONFIG_VIRT_BUTTONS 39 + +#define MAX_SETUP_MODES 40 #define MAX_MENU_MODES MAX(MAX_INFO_MODES, MAX_SETUP_MODES) @@ -104,6 +105,7 @@ #define STR_SETUP_EXIT "Exit" #define STR_SETUP_SAVE_AND_EXIT "Save and Exit" +#define STR_SETUP_CHOOSE_SCORES_TYPE "Scores Type" #define STR_SETUP_CHOOSE_GAME_SPEED "Game Speed" #define STR_SETUP_CHOOSE_SCROLL_DELAY "Scroll Delay" #define STR_SETUP_CHOOSE_SNAPSHOT_MODE "Snapshot Mode" @@ -282,6 +284,9 @@ static void MapScreenTreeGadgets(TreeInfo *); static void UpdateScreenMenuGadgets(int, boolean); +static boolean OfferUploadTapes(void); +static void execOfferUploadTapes(void); + static struct GadgetInfo *screen_gadget[NUM_SCREEN_GADGETS]; static int info_mode = INFO_MODE_MAIN; @@ -305,6 +310,9 @@ static TreeInfo *scroll_delay_current = NULL; static TreeInfo *snapshot_modes = NULL; static TreeInfo *snapshot_mode_current = NULL; +static TreeInfo *scores_types = NULL; +static TreeInfo *scores_type_current = NULL; + static TreeInfo *game_speeds_normal = NULL; static TreeInfo *game_speeds_extended = NULL; static TreeInfo *game_speeds = NULL; @@ -389,6 +397,15 @@ static struct StringValueTextInfo vsync_modes_list[] = { NULL, NULL }, }; +static struct StringValueTextInfo scores_types_list[] = +{ + { STR_SCORES_TYPE_LOCAL_ONLY, "Local scores only" }, + { STR_SCORES_TYPE_SERVER_ONLY, "Server scores only" }, + { STR_SCORES_TYPE_LOCAL_AND_SERVER, "Local and server scores" }, + + { NULL, NULL }, +}; + static struct ValueTextInfo game_speeds_list_normal[] = { { 30, "Very Slow" }, @@ -1740,6 +1757,9 @@ void DrawMainMenu(void) OpenDoor(DOOR_CLOSE_1 | DOOR_OPEN_2); SyncEmscriptenFilesystem(); + + // needed once after program start or after user change + CheckApiServerTasks(); } static void gotoTopLevelDir(void) @@ -2229,9 +2249,13 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button) SaveLevelSetup_LastSeries(); SaveLevelSetup_SeriesInfo(); +#if defined(PLATFORM_EMSCRIPTEN) + Request("Close the browser window to quit!", REQ_CONFIRM); +#else if (!setup.ask_on_quit_program || Request("Do you really want to quit?", REQ_ASK | REQ_STAY_CLOSED)) SetGameStatus(GAME_MODE_QUIT); +#endif } } } @@ -3235,7 +3259,7 @@ void HandleInfoScreen_Music(int button) { int sound = list->music; - if (sound_info[sound].loop) + if (IS_LOOP_SOUND(sound)) PlaySoundLoop(sound); else PlaySound(sound); @@ -3246,7 +3270,7 @@ void HandleInfoScreen_Music(int button) { int music = list->music; - if (music_info[music].loop) + if (IS_LOOP_MUSIC(music)) PlayMusicLoop(music); else PlayMusic(music); @@ -3314,7 +3338,7 @@ void HandleInfoScreen_Music(int button) FadeIn(REDRAW_FIELD); } - if (list != NULL && list->is_sound && sound_info[list->music].loop) + if (list != NULL && list->is_sound && IS_LOOP_SOUND(list->music)) PlaySoundLoop(list->music); } @@ -4036,14 +4060,42 @@ void HandleInfoScreen(int mx, int my, int dx, int dy, int button) // ============================================================================ -// change name functions +// rename player API functions // ============================================================================ -static void RenamePlayerOnServerExt(struct HttpRequest *request, - struct HttpResponse *response, - char *player_name_raw, - char *player_uuid_raw) +struct ApiRenamePlayerThreadData +{ + char *player_name; + char *player_uuid; +}; + +static void *CreateThreadData_ApiRenamePlayer(void) +{ + struct ApiRenamePlayerThreadData *data = + checked_malloc(sizeof(struct ApiRenamePlayerThreadData)); + + data->player_name = getStringCopy(setup.player_name); + data->player_uuid = getStringCopy(setup.player_uuid); + + return data; +} + +static void FreeThreadData_ApiRenamePlayer(void *data_raw) +{ + struct ApiRenamePlayerThreadData *data = data_raw; + + checked_free(data->player_name); + checked_free(data->player_uuid); + checked_free(data); +} + +static boolean SetRequest_ApiRenamePlayer(struct HttpRequest *request, + void *data_raw) { + struct ApiRenamePlayerThreadData *data = data_raw; + char *player_name_raw = data->player_name; + char *player_uuid_raw = data->player_uuid; + request->hostname = setup.api_server_hostname; request->port = API_SERVER_PORT; request->method = API_SERVER_METHOD; @@ -4056,11 +4108,13 @@ static void RenamePlayerOnServerExt(struct HttpRequest *request, "{\n" "%s" " \"game_version\": \"%s\",\n" + " \"game_platform\": \"%s\",\n" " \"name\": \"%s\",\n" " \"uuid\": \"%s\"\n" "}\n", getPasswordJSON(setup.api_server_password), getProgramRealVersionString(), + getProgramPlatformString(), player_name, player_uuid); @@ -4069,6 +4123,78 @@ static void RenamePlayerOnServerExt(struct HttpRequest *request, ConvertHttpRequestBodyToServerEncoding(request); + return TRUE; +} + +static void HandleResponse_ApiRenamePlayer(struct HttpResponse *response, + void *data_raw) +{ + // nothing to do here +} + +#if defined(PLATFORM_EMSCRIPTEN) +static void Emscripten_ApiRenamePlayer_Loaded(unsigned handle, void *data_raw, + void *buffer, unsigned int size) +{ + struct HttpResponse *response = GetHttpResponseFromBuffer(buffer, size); + + if (response != NULL) + { + HandleResponse_ApiRenamePlayer(response, data_raw); + + checked_free(response); + } + else + { + Error("server response too large to handle (%d bytes)", size); + } + + FreeThreadData_ApiRenamePlayer(data_raw); +} + +static void Emscripten_ApiRenamePlayer_Failed(unsigned handle, void *data_raw, + int code, const char *status) +{ + Error("server failed to handle request: %d %s", code, status); + + FreeThreadData_ApiRenamePlayer(data_raw); +} + +static void Emscripten_ApiRenamePlayer_Progress(unsigned handle, void *data_raw, + int bytes, int size) +{ + // nothing to do here +} + +static void Emscripten_ApiRenamePlayer_HttpRequest(struct HttpRequest *request, + void *data_raw) +{ + if (!SetRequest_ApiRenamePlayer(request, data_raw)) + { + FreeThreadData_ApiRenamePlayer(data_raw); + + return; + } + + emscripten_async_wget2_data(request->uri, + request->method, + request->body, + data_raw, + TRUE, + Emscripten_ApiRenamePlayer_Loaded, + Emscripten_ApiRenamePlayer_Failed, + Emscripten_ApiRenamePlayer_Progress); +} + +#else + +static void ApiRenamePlayer_HttpRequestExt(struct HttpRequest *request, + struct HttpResponse *response, + void *data_raw) +{ + if (!SetRequest_ApiRenamePlayer(request, data_raw)) + return; + if (!DoHttpRequest(request, response)) { Error("HTTP request failed: %s", GetHttpError()); @@ -4084,49 +4210,258 @@ static void RenamePlayerOnServerExt(struct HttpRequest *request, return; } + + HandleResponse_ApiRenamePlayer(response, data_raw); +} + +static void ApiRenamePlayer_HttpRequest(struct HttpRequest *request, + struct HttpResponse *response, + void *data_raw) +{ + ApiRenamePlayer_HttpRequestExt(request, response, data_raw); + + FreeThreadData_ApiRenamePlayer(data_raw); } +#endif -static void RenamePlayerOnServer(char *player_name, char *player_uuid) +static int ApiRenamePlayerThread(void *data_raw) { struct HttpRequest *request = checked_calloc(sizeof(struct HttpRequest)); struct HttpResponse *response = checked_calloc(sizeof(struct HttpResponse)); - RenamePlayerOnServerExt(request, response, player_name, player_uuid); + program.api_thread_count++; + +#if defined(PLATFORM_EMSCRIPTEN) + Emscripten_ApiRenamePlayer_HttpRequest(request, data_raw); +#else + ApiRenamePlayer_HttpRequest(request, response, data_raw); +#endif + + program.api_thread_count--; checked_free(request); checked_free(response); + + return 0; +} + +static void ApiRenamePlayerAsThread(void) +{ + struct ApiRenamePlayerThreadData *data = CreateThreadData_ApiRenamePlayer(); + + ExecuteAsThread(ApiRenamePlayerThread, + "ApiRenamePlayer", data, + "rename player on server"); } -struct RenamePlayerOnServerThreadData + +// ============================================================================ +// reset player UUID API functions +// ============================================================================ + +struct ApiResetUUIDThreadData { char *player_name; - char *player_uuid; + char *player_uuid_old; + char *player_uuid_new; }; -static int RenamePlayerOnServerThread(void *data_raw) +static void *CreateThreadData_ApiResetUUID(char *uuid_new) { - struct RenamePlayerOnServerThreadData *data = data_raw; + struct ApiResetUUIDThreadData *data = + checked_malloc(sizeof(struct ApiResetUUIDThreadData)); + + data->player_name = getStringCopy(setup.player_name); + data->player_uuid_old = getStringCopy(setup.player_uuid); + data->player_uuid_new = getStringCopy(uuid_new); - RenamePlayerOnServer(data->player_name, data->player_uuid); + return data; +} + +static void FreeThreadData_ApiResetUUID(void *data_raw) +{ + struct ApiResetUUIDThreadData *data = data_raw; checked_free(data->player_name); - checked_free(data->player_uuid); + checked_free(data->player_uuid_old); + checked_free(data->player_uuid_new); checked_free(data); +} - return 0; +static boolean SetRequest_ApiResetUUID(struct HttpRequest *request, + void *data_raw) +{ + struct ApiResetUUIDThreadData *data = data_raw; + char *player_name_raw = data->player_name; + char *player_uuid_old_raw = data->player_uuid_old; + char *player_uuid_new_raw = data->player_uuid_new; + + request->hostname = setup.api_server_hostname; + request->port = API_SERVER_PORT; + request->method = API_SERVER_METHOD; + request->uri = API_SERVER_URI_RESETUUID; + + char *player_name = getEscapedJSON(player_name_raw); + char *player_uuid_old = getEscapedJSON(player_uuid_old_raw); + char *player_uuid_new = getEscapedJSON(player_uuid_new_raw); + + snprintf(request->body, MAX_HTTP_BODY_SIZE, + "{\n" + "%s" + " \"game_version\": \"%s\",\n" + " \"game_platform\": \"%s\",\n" + " \"name\": \"%s\",\n" + " \"uuid_old\": \"%s\",\n" + " \"uuid_new\": \"%s\"\n" + "}\n", + getPasswordJSON(setup.api_server_password), + getProgramRealVersionString(), + getProgramPlatformString(), + player_name, + player_uuid_old, + player_uuid_new); + + checked_free(player_name); + checked_free(player_uuid_old); + checked_free(player_uuid_new); + + ConvertHttpRequestBodyToServerEncoding(request); + + return TRUE; } -static void RenamePlayerOnServerAsThread(void) +static void HandleResponse_ApiResetUUID(struct HttpResponse *response, + void *data_raw) { - struct RenamePlayerOnServerThreadData *data = - checked_malloc(sizeof(struct RenamePlayerOnServerThreadData)); + struct ApiResetUUIDThreadData *data = data_raw; - data->player_name = getStringCopy(setup.player_name); - data->player_uuid = getStringCopy(setup.player_uuid); + // upgrade player UUID in server setup file + setup.player_uuid = getStringCopy(data->player_uuid_new); + setup.player_version = 2; - ExecuteAsThread(RenamePlayerOnServerThread, - "RenamePlayerOnServer", data, - "rename player on server"); + SaveSetup_ServerSetup(); +} + +#if defined(PLATFORM_EMSCRIPTEN) +static void Emscripten_ApiResetUUID_Loaded(unsigned handle, void *data_raw, + void *buffer, unsigned int size) +{ + struct HttpResponse *response = GetHttpResponseFromBuffer(buffer, size); + + if (response != NULL) + { + HandleResponse_ApiResetUUID(response, data_raw); + + checked_free(response); + } + else + { + Error("server response too large to handle (%d bytes)", size); + } + + FreeThreadData_ApiResetUUID(data_raw); +} + +static void Emscripten_ApiResetUUID_Failed(unsigned handle, void *data_raw, + int code, const char *status) +{ + Error("server failed to handle request: %d %s", code, status); + + FreeThreadData_ApiResetUUID(data_raw); +} + +static void Emscripten_ApiResetUUID_Progress(unsigned handle, void *data_raw, + int bytes, int size) +{ + // nothing to do here +} + +static void Emscripten_ApiResetUUID_HttpRequest(struct HttpRequest *request, + void *data_raw) +{ + if (!SetRequest_ApiResetUUID(request, data_raw)) + { + FreeThreadData_ApiResetUUID(data_raw); + + return; + } + + emscripten_async_wget2_data(request->uri, + request->method, + request->body, + data_raw, + TRUE, + Emscripten_ApiResetUUID_Loaded, + Emscripten_ApiResetUUID_Failed, + Emscripten_ApiResetUUID_Progress); +} + +#else + +static void ApiResetUUID_HttpRequestExt(struct HttpRequest *request, + struct HttpResponse *response, + void *data_raw) +{ + if (!SetRequest_ApiResetUUID(request, data_raw)) + return; + + if (!DoHttpRequest(request, response)) + { + Error("HTTP request failed: %s", GetHttpError()); + + return; + } + + if (!HTTP_SUCCESS(response->status_code)) + { + Error("server failed to handle request: %d %s", + response->status_code, + response->status_text); + + return; + } + + HandleResponse_ApiResetUUID(response, data_raw); +} + +static void ApiResetUUID_HttpRequest(struct HttpRequest *request, + struct HttpResponse *response, + void *data_raw) +{ + ApiResetUUID_HttpRequestExt(request, response, data_raw); + + FreeThreadData_ApiResetUUID(data_raw); +} +#endif + +static int ApiResetUUIDThread(void *data_raw) +{ + struct HttpRequest *request = checked_calloc(sizeof(struct HttpRequest)); + struct HttpResponse *response = checked_calloc(sizeof(struct HttpResponse)); + + program.api_thread_count++; + +#if defined(PLATFORM_EMSCRIPTEN) + Emscripten_ApiResetUUID_HttpRequest(request, data_raw); +#else + ApiResetUUID_HttpRequest(request, response, data_raw); +#endif + + program.api_thread_count--; + + checked_free(request); + checked_free(response); + + return 0; +} + +static void ApiResetUUIDAsThread(char *uuid_new) +{ + struct ApiResetUUIDThreadData *data = CreateThreadData_ApiResetUUID(uuid_new); + + ExecuteAsThread(ApiResetUUIDThread, + "ApiResetUUID", data, + "reset UUID on server"); } @@ -4252,10 +4587,17 @@ static void setTypeNameValues(char *name, struct TextPosInfo *pos, // temporarily change active user to edited user user.nr = type_name_nr; - // load setup of edited user (unless creating user with current setup) - if (!create_user || - !Request("Use current setup values for the new player?", REQ_ASK)) + if (create_user && + Request("Use current setup values for the new player?", REQ_ASK)) + { + // use current setup values for new user, but create new player UUID + setup.player_uuid = getStringCopy(getUUID()); + } + else + { + // load setup for existing user (or start with defaults for new user) LoadSetup(); + } } char *setup_filename = getSetupFilename(); @@ -4268,7 +4610,7 @@ static void setTypeNameValues(char *name, struct TextPosInfo *pos, SaveSetup(); // change name of edited user on score server - RenamePlayerOnServerAsThread(); + ApiRenamePlayerAsThread(); if (game_status == GAME_MODE_PSEUDO_TYPENAMES || reset_setup) { @@ -4688,7 +5030,8 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button, } else if (game_status == GAME_MODE_SETUP) { - if (setup_mode == SETUP_MODE_CHOOSE_GAME_SPEED || + if (setup_mode == SETUP_MODE_CHOOSE_SCORES_TYPE || + setup_mode == SETUP_MODE_CHOOSE_GAME_SPEED || setup_mode == SETUP_MODE_CHOOSE_SCROLL_DELAY || setup_mode == SETUP_MODE_CHOOSE_SNAPSHOT_MODE) execSetupGame(); @@ -4855,7 +5198,8 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button, { if (game_status == GAME_MODE_SETUP) { - if (setup_mode == SETUP_MODE_CHOOSE_GAME_SPEED || + if (setup_mode == SETUP_MODE_CHOOSE_SCORES_TYPE || + setup_mode == SETUP_MODE_CHOOSE_GAME_SPEED || setup_mode == SETUP_MODE_CHOOSE_SCROLL_DELAY || setup_mode == SETUP_MODE_CHOOSE_SNAPSHOT_MODE) execSetupGame(); @@ -4927,7 +5271,8 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button, if (game_status == GAME_MODE_SETUP) { - if (setup_mode == SETUP_MODE_CHOOSE_GAME_SPEED || + if (setup_mode == SETUP_MODE_CHOOSE_SCORES_TYPE || + setup_mode == SETUP_MODE_CHOOSE_GAME_SPEED || setup_mode == SETUP_MODE_CHOOSE_SCROLL_DELAY || setup_mode == SETUP_MODE_CHOOSE_SNAPSHOT_MODE) execSetupGame(); @@ -5348,6 +5693,7 @@ static char *vsync_mode_text; static char *scroll_delay_text; static char *snapshot_mode_text; static char *game_speed_text; +static char *scores_type_text; static char *network_server_text; static char *graphics_set_name; static char *sounds_set_name; @@ -5368,6 +5714,56 @@ static void execSetupMain(void) DrawSetupScreen(); } +static void execSetupGame_setScoresType(void) +{ + if (scores_types == NULL) + { + int i; + + for (i = 0; scores_types_list[i].value != NULL; i++) + { + TreeInfo *ti = newTreeInfo_setDefaults(TREE_TYPE_UNDEFINED); + char identifier[32], name[32]; + char *value = scores_types_list[i].value; + char *text = scores_types_list[i].text; + + ti->node_top = &scores_types; + ti->sort_priority = i; + + sprintf(identifier, "%s", value); + sprintf(name, "%s", text); + + setString(&ti->identifier, identifier); + setString(&ti->name, name); + setString(&ti->name_sorting, name); + setString(&ti->infotext, STR_SETUP_CHOOSE_SCORES_TYPE); + + pushTreeInfo(&scores_types, ti); + } + + // sort scores type values to start with lowest scores type value + sortTreeInfo(&scores_types); + + // set current scores type value to configured scores type value + scores_type_current = + getTreeInfoFromIdentifier(scores_types, setup.scores_in_highscore_list); + + // if that fails, set current scores type to reliable default value + if (scores_type_current == NULL) + scores_type_current = + getTreeInfoFromIdentifier(scores_types, STR_SCORES_TYPE_DEFAULT); + + // if that also fails, set current scores type to first available value + if (scores_type_current == NULL) + scores_type_current = scores_types; + } + + setup.scores_in_highscore_list = scores_type_current->identifier; + + // needed for displaying scores type text instead of identifier + scores_type_text = scores_type_current->name; +} + static void execSetupGame_setGameSpeeds(boolean update_value) { if (setup.game_speed_extended) @@ -5561,11 +5957,15 @@ static void execSetupGame(void) boolean check_vsync_mode = (setup_mode == SETUP_MODE_CHOOSE_GAME_SPEED); execSetupGame_setGameSpeeds(FALSE); + execSetupGame_setScoresType(); execSetupGame_setScrollDelays(); execSetupGame_setSnapshotModes(); execSetupGame_setNetworkServerText(); + if (!setup.provide_uploading_tapes) + setHideSetupEntry(execOfferUploadTapes); + setup_mode = SETUP_MODE_GAME; DrawSetupScreen(); @@ -5575,6 +5975,13 @@ static void execSetupGame(void) DisableVsyncIfNeeded(); } +static void execSetupChooseScoresType(void) +{ + setup_mode = SETUP_MODE_CHOOSE_SCORES_TYPE; + + DrawSetupScreen(); +} + static void execSetupChooseGameSpeed(void) { setup_mode = SETUP_MODE_CHOOSE_GAME_SPEED; @@ -6651,6 +7058,11 @@ static void execGadgetNetworkServer(void) ClickOnGadget(gi, MB_LEFTBUTTON); } +static void execOfferUploadTapes(void) +{ + OfferUploadTapes(); +} + static void ToggleNetworkModeIfNeeded(void) { int font_title = FONT_TITLE_1; @@ -6709,6 +7121,17 @@ static void ToggleGameSpeedsListIfNeeded(void) DrawSetupScreen(); } +static void ToggleUseApiServerIfNeeded(void) +{ + if (runtime.use_api_server == setup.use_api_server) + return; + + runtime.use_api_server = setup.use_api_server; + + if (runtime.use_api_server) + CheckApiServerTasks(); +} + static void ModifyGameSpeedIfNeeded(void) { if (strEqual(setup.vsync_mode, STR_VSYNC_MODE_OFF) || @@ -6756,6 +7179,9 @@ static struct void *related_value; } hide_related_entry_list[] = { + { &setup.scores_in_highscore_list, execSetupChooseScoresType }, + { &setup.scores_in_highscore_list, &scores_type_text }, + { &setup.game_frame_delay, execSetupChooseGameSpeed }, { &setup.game_frame_delay, &game_speed_text }, @@ -6868,8 +7294,10 @@ static struct TokenInfo setup_info_game[] = { TYPE_PLAYER, &setup.network_player_nr,"Preferred Network Player:" }, { TYPE_TEXT_INPUT, execGadgetNetworkServer, "Network Server Hostname:" }, { TYPE_STRING, &network_server_text, "" }, - { TYPE_SWITCH, &setup.api_server, "Use Highscore Server:" }, - { TYPE_SWITCH, &setup.only_show_local_scores, "Only Show Local Scores:" }, + { TYPE_SWITCH, &setup.use_api_server, "Use Highscore Server:" }, + { TYPE_ENTER_LIST, execSetupChooseScoresType,"Scores in Highscore List:" }, + { TYPE_STRING, &scores_type_text, "" }, + { TYPE_ENTER_LIST, execOfferUploadTapes, "Upload Tapes to Server" }, { TYPE_SWITCH, &setup.multiple_users, "Multiple Users/Teams:" }, { TYPE_YES_NO, &setup.input_on_focus, "Only Move Focussed Player:" }, { TYPE_SWITCH, &setup.time_limit, "Time Limit:" }, @@ -7473,8 +7901,8 @@ static void changeSetupValue(int screen_pos, int setup_info_pos_raw, int dx) ToggleNetworkModeIfNeeded(); // API server mode may have changed at this point - if (si->value == &setup.api_server) - runtime.api_server = setup.api_server; + if (si->value == &setup.use_api_server) + ToggleUseApiServerIfNeeded(); // game speed list may have changed at this point if (si->value == &setup.game_speed_extended) @@ -8891,6 +9319,8 @@ void DrawSetupScreen(void) if (setup_mode == SETUP_MODE_INPUT) DrawSetupScreen_Input(); + else if (setup_mode == SETUP_MODE_CHOOSE_SCORES_TYPE) + DrawChooseTree(&scores_type_current); else if (setup_mode == SETUP_MODE_CHOOSE_GAME_SPEED) DrawChooseTree(&game_speed_current); else if (setup_mode == SETUP_MODE_CHOOSE_SCROLL_DELAY) @@ -8973,6 +9403,8 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button) { if (setup_mode == SETUP_MODE_INPUT) HandleSetupScreen_Input(mx, my, dx, dy, button); + else if (setup_mode == SETUP_MODE_CHOOSE_SCORES_TYPE) + HandleChooseTree(mx, my, dx, dy, button, &scores_type_current); else if (setup_mode == SETUP_MODE_CHOOSE_GAME_SPEED) HandleChooseTree(mx, my, dx, dy, button, &game_speed_current); else if (setup_mode == SETUP_MODE_CHOOSE_SCROLL_DELAY) @@ -9859,29 +10291,108 @@ static int UploadTapes(void) return num_tapes_uploaded; } -void CheckUploadTapes(void) +static boolean OfferUploadTapes(void) +{ + if (!Request(setup.has_remaining_tapes ? + "Upload missing tapes to the high score server now?" : + "Upload all your tapes to the high score server now?", REQ_ASK)) + return FALSE; + + int num_tapes_uploaded = UploadTapes(); + char message[100]; + + if (num_tapes_uploaded < 0) + { + num_tapes_uploaded = -num_tapes_uploaded - 1; + + if (num_tapes_uploaded == 0) + sprintf(message, "Upload failed! No tapes uploaded!"); + else if (num_tapes_uploaded == 1) + sprintf(message, "Upload failed! Only 1 tape uploaded!"); + else + sprintf(message, "Upload failed! Only %d tapes uploaded!", + num_tapes_uploaded); + + Request(message, REQ_CONFIRM); + + // if uploading tapes failed, add tape upload entry to setup menu + setup.provide_uploading_tapes = TRUE; + setup.has_remaining_tapes = TRUE; + + SaveSetup_ServerSetup(); + + return FALSE; + } + + if (num_tapes_uploaded == 0) + sprintf(message, "No tapes uploaded!"); + else if (num_tapes_uploaded == 1) + sprintf(message, "1 tape uploaded!"); + else + sprintf(message, "%d tapes uploaded!", num_tapes_uploaded); + + Request(message, REQ_CONFIRM); + + if (num_tapes_uploaded > 0) + Request("New scores will be visible after a few minutes!", REQ_CONFIRM); + + // after all tapes have been uploaded, remove entry from setup menu + setup.provide_uploading_tapes = FALSE; + setup.has_remaining_tapes = FALSE; + + SaveSetup_ServerSetup(); + + return TRUE; +} + +static void CheckUploadTapes(void) { if (!setup.ask_for_uploading_tapes) return; + // after asking for uploading tapes, do not ask again + setup.ask_for_uploading_tapes = FALSE; + setup.ask_for_remaining_tapes = FALSE; + if (directoryExists(getTapeDir(NULL))) { - if (Request("Upload all your tapes to the high score server now?", REQ_ASK)) - { - int num_tapes_uploaded = UploadTapes(); - char message[100]; - - sprintf(message, "%d tapes uploaded!", num_tapes_uploaded); + boolean tapes_uploaded = OfferUploadTapes(); - Request(message, REQ_CONFIRM); - } - else + if (!tapes_uploaded) { - Request("You can upload your tapes from the setup menu later!", REQ_CONFIRM); + Request(setup.has_remaining_tapes ? + "You can upload missing tapes from the setup menu later!" : + "You can upload your tapes from the setup menu later!", + REQ_CONFIRM); } } + else + { + // if tapes directory does not exist yet, never offer uploading all tapes + setup.provide_uploading_tapes = FALSE; + } - setup.ask_for_uploading_tapes = FALSE; + SaveSetup_ServerSetup(); +} - SaveSetup(); +static void UpgradePlayerUUID(void) +{ + ApiResetUUIDAsThread(getUUID()); +} + +static void CheckUpgradePlayerUUID(void) +{ + if (setup.player_version > 1) + return; + + UpgradePlayerUUID(); +} + +void CheckApiServerTasks(void) +{ + // check if the player's UUID has to be upgraded + CheckUpgradePlayerUUID(); + + // check if there are any tapes to be uploaded + CheckUploadTapes(); }