added reloading server scores after download has finished
[rocksndiamonds.git] / src / files.c
index eb47c4efd0e8c4c7073e5ba5e9a41a95780c894a..b3aa171bcde56917c7d3080478ab3b0c23d87702 100644 (file)
@@ -8438,6 +8438,9 @@ static void setScoreInfoToDefaultsExt(struct ScoreInfo *scores)
 
   scores->num_entries = 0;
   scores->last_added = -1;
+  scores->last_added_local = -1;
+
+  scores->updated = FALSE;
 }
 
 static void setScoreInfoToDefaults(void)
@@ -8904,6 +8907,24 @@ 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)
@@ -8966,6 +8987,8 @@ static void DownloadServerScoreToCacheExt(struct HttpRequest *request,
   fclose(file);
 
   SetFilePermissions(filename, PERMS_PRIVATE);
+
+  server_scores.updated = TRUE;
 }
 
 static void DownloadServerScoreToCache(int nr)
@@ -8979,6 +9002,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;
@@ -9045,14 +9082,23 @@ static void LoadServerScoreFromCache(int nr)
   freeSetupFileHash(score_hash);
 }
 
-void LoadServerScore(int nr)
+void LoadServerScore(int nr, boolean download_score)
 {
   // 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)
+  {
+    // 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);
+  }
+
+  // merge local scores with scores from server
   MergeServerScore();
 }
 
@@ -9191,9 +9237,37 @@ 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);
+  UploadScoreToServerAsThread(nr);
+}
+
+void LoadLocalAndServerScore(int nr, boolean download_score)
+{
+  int last_added_local = scores.last_added_local;
+
+  LoadScore(nr);
+
+  // restore last added local score entry (before merging server scores)
+  scores.last_added = scores.last_added_local = last_added_local;
+
+  LoadServerScore(nr, download_score);
+
+  MergeServerScore();
 }