added saving high scores to score server
authorHolger Schemel <info@artsoft.org>
Sat, 24 Apr 2021 23:45:52 +0000 (01:45 +0200)
committerHolger Schemel <info@artsoft.org>
Sat, 1 May 2021 13:38:31 +0000 (15:38 +0200)
src/files.c
src/files.h
src/game.c
src/libgame/system.h

index ab6a595876440efa5e72d350130cf8ced12b4b30..eab833048a1e18811c6e040928080818497ca9b1 100644 (file)
@@ -8899,6 +8899,144 @@ void SaveScore(int nr)
   SaveScoreToFilename(filename);
 }
 
+static char *get_file_base64(char *filename)
+{
+  struct stat file_status;
+
+  if (stat(filename, &file_status) != 0)
+  {
+    Error("cannot stat file '%s'\n", filename);
+
+    return NULL;
+  }
+
+  int buffer_size = file_status.st_size;
+  byte *buffer = checked_malloc(buffer_size);
+  FILE *file;
+  int i;
+
+  if (!(file = fopen(filename, MODE_READ)))
+  {
+    Error("cannot open file '%s'\n", filename);
+
+    checked_free(buffer);
+
+    return NULL;
+  }
+
+  for (i = 0; i < buffer_size; i++)
+  {
+    int c = fgetc(file);
+
+    if (c == EOF)
+    {
+      Error("cannot read from input file '%s'\n", filename);
+
+      fclose(file);
+      checked_free(buffer);
+
+      return NULL;
+    }
+
+    buffer[i] = (byte)c;
+  }
+
+  fclose(file);
+
+  int buffer_encoded_size = base64_encoded_size(buffer_size);
+  char *buffer_encoded = checked_malloc(buffer_encoded_size);
+
+  base64_encode(buffer_encoded, buffer, buffer_size);
+
+  checked_free(buffer);
+
+  return buffer_encoded;
+}
+
+static void UploadScoreToServerExt(struct HttpRequest *request,
+                                  struct HttpResponse *response,
+                                  int nr)
+{
+  struct ScoreEntry *score_entry = &scores.entry[scores.last_added];
+
+  request->hostname = API_SERVER_HOSTNAME;
+  request->port     = API_SERVER_PORT;
+  request->method   = API_SERVER_METHOD;
+  request->uri      = API_SERVER_URI_ADD;
+
+  char *tape_filename = getScoreTapeFilename(score_entry->tape_basename, nr);
+  char *tape_base64 = get_file_base64(tape_filename);
+
+  if (tape_base64 == NULL)
+  {
+    Error("loading and base64 encoding score tape file failed");
+
+    return;
+  }
+
+  snprintf(request->body, MAX_HTTP_BODY_SIZE,
+          "{\n"
+          "  \"game_version\":         \"%s\",\n"
+          "  \"levelset_identifier\":  \"%s\",\n"
+          "  \"levelset_name\":        \"%s\",\n"
+          "  \"levelset_author\":      \"%s\",\n"
+          "  \"levelset_num_levels\":  \"%d\",\n"
+          "  \"levelset_first_level\": \"%d\",\n"
+          "  \"level_nr\":             \"%d\",\n"
+          "  \"player_name\":          \"%s\",\n"
+          "  \"score\":                \"%d\",\n"
+          "  \"time\":                 \"%d\",\n"
+          "  \"tape_basename\":        \"%s\",\n"
+          "  \"tape\":                 \"%s\"\n"
+          "}\n",
+          getProgramRealVersionString(),
+          leveldir_current->identifier,
+          leveldir_current->name,
+          leveldir_current->author,
+          leveldir_current->levels,
+          leveldir_current->first_level,
+          level_nr,
+          score_entry->name,
+          score_entry->score,
+          score_entry->time,
+          score_entry->tape_basename,
+          tape_base64);
+
+  ConvertHttpRequestBodyToServerEncoding(request);
+
+  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;
+  }
+}
+
+static void UploadScoreToServer(int nr)
+{
+  struct HttpRequest *request = checked_calloc(sizeof(struct HttpRequest));
+  struct HttpResponse *response = checked_calloc(sizeof(struct HttpResponse));
+
+  UploadScoreToServerExt(request, response, nr);
+
+  checked_free(request);
+  checked_free(response);
+}
+
+void SaveServerScore(int nr)
+{
+  UploadScoreToServer(nr);
+}
+
 
 // ============================================================================
 // setup file functions
index ade7a8d51f24641fc7b23a47e0129afe071fe339..982f20ec0b8a4b9b6bc2c3fb208d20c64e79f72a 100644 (file)
@@ -62,6 +62,8 @@ boolean SaveTapeChecked_LevelSolved(int);
 void LoadScore(int);
 void SaveScore(int);
 
+void SaveServerScore(int);
+
 void LoadUserNames(void);
 
 void LoadSetupFromFilename(char *);
index 6976317a65e26ae36c580d21a947599e84dd3aa1..31ecdbdd6a551a580708cb332599b24c5df41865 100644 (file)
@@ -5126,7 +5126,10 @@ int NewHighScore(int level_nr)
     SaveScore(level_nr);
 
     if (game.LevelSolved_SaveTape)
+    {
       SaveScoreTape(level_nr);
+      SaveServerScore(level_nr);
+    }
   }
 
   return scores.last_added;
index 26254d9cd52d8c612db80c4da23a72da2db8c66f..8265773358ca9d1806dc39e69b3c78f39a9cf61e 100644 (file)
 #define STR_NETWORK_AUTO_DETECT                "auto_detect_network_server"
 #define STR_NETWORK_AUTO_DETECT_SETUP  "(auto detect network server)"
 
+// values for API server settings
+#define API_SERVER_HOSTNAME            "api.artsoft.org"
+#define API_SERVER_PORT                        80
+#define API_SERVER_METHOD              "POST"
+#define API_SERVER_URI_ADD             "/api/scores/add"
+
 // values for touch control
 #define TOUCH_CONTROL_OFF              "off"
 #define TOUCH_CONTROL_VIRTUAL_BUTTONS  "virtual_buttons"