X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Ffiles.c;h=b43b89c8035cfa8646e4f0220260515f9371f71f;hb=380f1f693d72b034d9b56dbc9c974ba8c6c490e7;hp=1adbfd740c72d7127d35043d538a6014d8123d90;hpb=d29d345324b2af238f39e1ee3b71d38b2eee9b4e;p=rocksndiamonds.git diff --git a/src/files.c b/src/files.c index 1adbfd74..b43b89c8 100644 --- a/src/files.c +++ b/src/files.c @@ -7656,10 +7656,33 @@ void DumpLevel(struct LevelInfo *level) Print("SP player blocks last field: %s\n", (level->sp_block_last_field ? "yes" : "no")); Print("use spring bug: %s\n", (level->use_spring_bug ? "yes" : "no")); Print("use step counter: %s\n", (level->use_step_counter ? "yes" : "no")); + Print("rate time over score: %s\n", (level->rate_time_over_score ? "yes" : "no")); PrintLine("-", 79); } +void DumpLevels(void) +{ + static LevelDirTree *dumplevel_leveldir = NULL; + + dumplevel_leveldir = getTreeInfoFromIdentifier(leveldir_first, + global.dumplevel_leveldir); + + if (dumplevel_leveldir == NULL) + Fail("no such level identifier: '%s'", global.dumplevel_leveldir); + + if (global.dumplevel_level_nr < dumplevel_leveldir->first_level || + global.dumplevel_level_nr > dumplevel_leveldir->last_level) + Fail("no such level number: %d", global.dumplevel_level_nr); + + leveldir_current = dumplevel_leveldir; + + LoadLevel(global.dumplevel_level_nr); + DumpLevel(&level); + + CloseAllAndExit(0); +} + // ============================================================================ // tape file functions @@ -8419,6 +8442,32 @@ void DumpTape(struct TapeInfo *tape) PrintLine("-", 79); } +void DumpTapes(void) +{ + static LevelDirTree *dumptape_leveldir = NULL; + + dumptape_leveldir = getTreeInfoFromIdentifier(leveldir_first, + global.dumptape_leveldir); + + if (dumptape_leveldir == NULL) + Fail("no such level identifier: '%s'", global.dumptape_leveldir); + + if (global.dumptape_level_nr < dumptape_leveldir->first_level || + global.dumptape_level_nr > dumptape_leveldir->last_level) + Fail("no such level number: %d", global.dumptape_level_nr); + + leveldir_current = dumptape_leveldir; + + if (options.mytapes) + LoadTape(global.dumptape_level_nr); + else + LoadSolutionTape(global.dumptape_level_nr); + + DumpTape(&tape); + + CloseAllAndExit(0); +} + // ============================================================================ // score file functions @@ -8439,6 +8488,9 @@ static void setScoreInfoToDefaultsExt(struct ScoreInfo *scores) scores->num_entries = 0; scores->last_added = -1; scores->last_added_local = -1; + + scores->updated = FALSE; + scores->force_last_added = FALSE; } static void setScoreInfoToDefaults(void) @@ -8740,7 +8792,6 @@ void LoadScore(int nr) void SaveScore_OLD(int nr) { int i; - int permissions = (program.global_scores ? PERMS_PUBLIC : PERMS_PRIVATE); char *filename = getScoreFilename(nr); FILE *file; @@ -8761,7 +8812,7 @@ void SaveScore_OLD(int nr) fclose(file); - SetFilePermissions(filename, permissions); + SetFilePermissions(filename, PERMS_PRIVATE); } #endif @@ -8830,7 +8881,6 @@ static void SaveScore_TAPE(FILE *file, struct ScoreInfo *scores) static void SaveScoreToFilename(char *filename) { FILE *file; - int permissions = (program.global_scores ? PERMS_PUBLIC : PERMS_PRIVATE); int info_chunk_size; int name_chunk_size; int scor_chunk_size; @@ -8873,7 +8923,7 @@ static void SaveScoreToFilename(char *filename) fclose(file); - SetFilePermissions(filename, permissions); + SetFilePermissions(filename, PERMS_PRIVATE); } void SaveScore(int nr) @@ -8905,11 +8955,29 @@ void SaveScore(int nr) SaveScoreToFilename(filename); } +static void ExecuteAsThread(SDL_ThreadFunction function, char *name, int data, + char *error) +{ + static int data_static; + + data_static = data; + + SDL_Thread *thread = SDL_CreateThread(function, name, &data_static); + + if (thread != NULL) + SDL_DetachThread(thread); + else + Error("Cannot create thread to %s!", error); + + // nasty kludge to lower probability of intermingled thread error messages + Delay(1); +} + static void DownloadServerScoreToCacheExt(struct HttpRequest *request, struct HttpResponse *response, int nr) { - request->hostname = API_SERVER_HOSTNAME; + request->hostname = setup.api_server_hostname; request->port = API_SERVER_PORT; request->method = API_SERVER_METHOD; request->uri = API_SERVER_URI_GET; @@ -8967,6 +9035,8 @@ static void DownloadServerScoreToCacheExt(struct HttpRequest *request, fclose(file); SetFilePermissions(filename, PERMS_PRIVATE); + + server_scores.updated = TRUE; } static void DownloadServerScoreToCache(int nr) @@ -8980,6 +9050,20 @@ static void DownloadServerScoreToCache(int nr) checked_free(response); } +static int DownloadServerScoreToCacheThread(void *data) +{ + DownloadServerScoreToCache(*(int *)data); + + return 0; +} + +static void DownloadServerScoreToCacheAsThread(int nr) +{ + ExecuteAsThread(DownloadServerScoreToCacheThread, + "DownloadServerScoreToCache", nr, + "download scores from server"); +} + static void LoadServerScoreFromCache(int nr) { struct ScoreEntry score_entry; @@ -9046,13 +9130,24 @@ static void LoadServerScoreFromCache(int nr) freeSetupFileHash(score_hash); } -void LoadServerScore(int nr) +void LoadServerScore(int nr, boolean download_score) { + if (!setup.api_server) + return; + // always start with reliable default values setServerScoreInfoToDefaults(); - DownloadServerScoreToCache(nr); + // 1st step: load server scores from cache file (which may not exist) + // (this should prevent reading it while the thread is writing to it) LoadServerScoreFromCache(nr); + + if (download_score && runtime.api_server) + { + // 2nd step: download server scores from score server to cache file + // (as thread, as it might time out if the server is not reachable) + DownloadServerScoreToCacheAsThread(nr); + } } static char *get_file_base64(char *filename) @@ -9115,7 +9210,7 @@ static void UploadScoreToServerExt(struct HttpRequest *request, { struct ScoreEntry *score_entry = &scores.entry[scores.last_added]; - request->hostname = API_SERVER_HOSTNAME; + request->hostname = setup.api_server_hostname; request->port = API_SERVER_PORT; request->method = API_SERVER_METHOD; request->uri = API_SERVER_URI_ADD; @@ -9190,12 +9285,29 @@ static void UploadScoreToServer(int nr) checked_free(response); } +static int UploadScoreToServerThread(void *data) +{ + UploadScoreToServer(*(int *)data); + + return 0; +} + +static void UploadScoreToServerAsThread(int nr) +{ + ExecuteAsThread(UploadScoreToServerThread, + "UploadScoreToServer", nr, + "upload score to server"); +} + void SaveServerScore(int nr) { - UploadScoreToServer(nr); + if (!runtime.api_server) + return; + + UploadScoreToServerAsThread(nr); } -void LoadLocalAndServerScore(int nr) +void LoadLocalAndServerScore(int nr, boolean download_score) { int last_added_local = scores.last_added_local; @@ -9204,9 +9316,14 @@ void LoadLocalAndServerScore(int nr) // restore last added local score entry (before merging server scores) scores.last_added = scores.last_added_local = last_added_local; - LoadServerScore(nr); + if (setup.api_server && !setup.only_show_local_scores) + { + // load server scores from cache file and trigger update from server + LoadServerScore(nr, download_score); - MergeServerScore(); + // merge local scores with scores from server + MergeServerScore(); + } } @@ -9395,6 +9512,10 @@ static struct TokenInfo global_setup_tokens[] = TYPE_SWITCH, &setup.show_snapshot_buttons, "show_snapshot_buttons" }, + { + TYPE_SWITCH, + &setup.only_show_local_scores, "only_show_local_scores" + }, { TYPE_STRING, &setup.graphics_set, "graphics_set" @@ -9443,6 +9564,14 @@ static struct TokenInfo global_setup_tokens[] = TYPE_STRING, &setup.network_server_hostname, "network_server_hostname" }, + { + TYPE_SWITCH, + &setup.api_server, "api_server" + }, + { + TYPE_STRING, + &setup.api_server_hostname, "api_server_hostname" + }, { TYPE_STRING, &setup.touch.control_type, "touch.control_type" @@ -10059,6 +10188,7 @@ static void setSetupInfoToDefaults(struct SetupInfo *si) si->sp_show_border_elements = FALSE; si->small_game_graphics = FALSE; si->show_snapshot_buttons = FALSE; + si->only_show_local_scores = FALSE; si->graphics_set = getStringCopy(GFX_CLASSIC_SUBDIR); si->sounds_set = getStringCopy(SND_CLASSIC_SUBDIR); @@ -10076,6 +10206,9 @@ static void setSetupInfoToDefaults(struct SetupInfo *si) si->network_player_nr = 0; // first player si->network_server_hostname = getStringCopy(STR_NETWORK_AUTO_DETECT); + si->api_server = TRUE; + si->api_server_hostname = getStringCopy(API_SERVER_HOSTNAME); + si->touch.control_type = getStringCopy(TOUCH_CONTROL_DEFAULT); si->touch.move_distance = TOUCH_MOVE_DISTANCE_DEFAULT; // percent si->touch.drop_distance = TOUCH_DROP_DISTANCE_DEFAULT; // percent @@ -10691,6 +10824,7 @@ void SaveSetup(void) global_setup_tokens[i].value == &setup.graphics_set || global_setup_tokens[i].value == &setup.volume_simple || global_setup_tokens[i].value == &setup.network_mode || + global_setup_tokens[i].value == &setup.api_server || global_setup_tokens[i].value == &setup.touch.control_type || global_setup_tokens[i].value == &setup.touch.grid_xsize[0] || global_setup_tokens[i].value == &setup.touch.grid_xsize[1])