Просмотр исходного кода

save/load player context as intended

jblanked 1 год назад
Родитель
Сommit
fce65e31c9
3 измененных файлов с 128 добавлено и 43 удалено
  1. 11 5
      game/game.c
  2. 61 31
      game/player.c
  3. 56 7
      game/storage.c

+ 11 - 5
game/game.c

@@ -39,6 +39,7 @@ static void game_start(GameManager *game_manager, void *ctx)
     furi_string_free(world_list);
     furi_string_free(world_list);
 
 
     game_context->current_level = 0;
     game_context->current_level = 0;
+    FURI_LOG_I("Game", "Level count: %d", game_context->level_count);
 }
 }
 
 
 /*
 /*
@@ -53,11 +54,16 @@ static void game_stop(void *ctx)
         FURI_LOG_E("Game", "Invalid game context");
         FURI_LOG_E("Game", "Invalid game context");
         return;
         return;
     }
     }
-    // GameContext *game_context = ctx;
-    // if (game_context->player_context)
-    // {
-    //     save_player_context(game_context->player_context);
-    // }
+
+    GameContext *game_context = ctx;
+    if (game_context && game_context->player_context)
+    {
+        easy_flipper_dialog("Game Over", "Thanks for playing Flip World!\nHit BACK then wait for\nthe game to save.");
+        FURI_LOG_I("Game", "Saving player context");
+        save_player_context(game_context->player_context);
+        FURI_LOG_I("Game", "Player context saved");
+        easy_flipper_dialog("Game Saved", "Hit BACK to exit.");
+    }
 }
 }
 
 
 /*
 /*

+ 61 - 31
game/player.c

@@ -21,55 +21,85 @@ static Level *get_next_level(GameManager *manager)
 
 
 void player_spawn(Level *level, GameManager *manager)
 void player_spawn(Level *level, GameManager *manager)
 {
 {
+    if (!level || !manager)
+    {
+        FURI_LOG_E(TAG, "Invalid arguments to player_spawn");
+        return;
+    }
+
     GameContext *game_context = game_manager_game_context_get(manager);
     GameContext *game_context = game_manager_game_context_get(manager);
+    if (!game_context)
+    {
+        FURI_LOG_E(TAG, "Failed to get game context");
+        return;
+    }
+
     game_context->players[0] = level_add_entity(level, &player_desc);
     game_context->players[0] = level_add_entity(level, &player_desc);
+    if (!game_context->players[0])
+    {
+        FURI_LOG_E(TAG, "Failed to add player entity to level");
+        return;
+    }
 
 
     // Set player position.
     // Set player position.
     entity_pos_set(game_context->players[0], (Vector){WORLD_WIDTH / 2, WORLD_HEIGHT / 2});
     entity_pos_set(game_context->players[0], (Vector){WORLD_WIDTH / 2, WORLD_HEIGHT / 2});
 
 
     // Add collision box to player entity
     // Add collision box to player entity
-    // Box is centered in player x and y, and it's size is 10x10
+    // Box is centered in player x and y, and its size is 10x10
     entity_collider_add_rect(game_context->players[0], 10, 10);
     entity_collider_add_rect(game_context->players[0], 10, 10);
 
 
     // Get player context
     // Get player context
     PlayerContext *player_context = entity_context_get(game_context->players[0]);
     PlayerContext *player_context = entity_context_get(game_context->players[0]);
-    // if (!load_player_context(player_context))
-    //  {
-    // Load player sprite
-    player_context->sprite_right = game_manager_sprite_load(manager, "player_right_naked_10x10px.fxbm");
-    player_context->sprite_left = game_manager_sprite_load(manager, "player_left_naked_10x10px.fxbm");
-    player_context->direction = PLAYER_RIGHT; // default direction
-    player_context->health = 100;
-    player_context->strength = 10;
-    player_context->level = 1;
-    player_context->xp = 0;
-    player_context->start_position = entity_pos_get(game_context->players[0]);
-    player_context->attack_timer = 0.1f;
-    player_context->elapsed_attack_timer = player_context->attack_timer;
-    player_context->health_regen = 1; // 1 health per second
-    player_context->elapsed_health_regen = 0;
-    player_context->max_health = 100 + ((player_context->level - 1) * 10); // 10 health per level
-
-    // Set player username
-    if (!load_char("Flip-Social-Username", player_context->username, 32))
+    if (!player_context)
     {
     {
-        snprintf(player_context->username, 32, "Player");
+        FURI_LOG_E(TAG, "Failed to get player context");
+        return;
     }
     }
 
 
-    game_context->player_context = player_context;
-    // save_player_context(player_context);
-    //   return;
-    //   }
+    FURI_LOG_I(TAG, "Loading player context");
+    if (!load_player_context(player_context))
+    {
+        FURI_LOG_E(TAG, "Loading player context failed. Initializing default values.");
+
+        // Initialize default player context
+        player_context->sprite_right = game_manager_sprite_load(manager, "player_right_naked_10x10px.fxbm");
+        player_context->sprite_left = game_manager_sprite_load(manager, "player_left_naked_10x10px.fxbm");
+        player_context->direction = PLAYER_RIGHT; // default direction
+        player_context->health = 100;
+        player_context->strength = 10;
+        player_context->level = 1;
+        player_context->xp = 0;
+        player_context->start_position = entity_pos_get(game_context->players[0]);
+        player_context->attack_timer = 0.1f;
+        player_context->elapsed_attack_timer = player_context->attack_timer;
+        player_context->health_regen = 1; // 1 health per second
+        player_context->elapsed_health_regen = 0;
+        player_context->max_health = 100 + ((player_context->level - 1) * 10); // 10 health per level
+
+        // Set player username
+        if (!load_char("Flip-Social-Username", player_context->username, sizeof(player_context->username)))
+        {
+            // If loading username fails, default to "Player"
+            snprintf(player_context->username, sizeof(player_context->username), "Player");
+        }
 
 
-    // Copy loaded player context to player context
-    // game_context->player_context = player_context;
+        game_context->player_context = player_context;
 
 
+        // Save the initialized context
+        if (!save_player_context(player_context))
+        {
+            FURI_LOG_E(TAG, "Failed to save player context after initialization");
+        }
+
+        return;
+    }
+    FURI_LOG_I(TAG, "Player context loaded successfully");
     // Load player sprite (we'll add this to the JSON later when players can choose their sprite)
     // Load player sprite (we'll add this to the JSON later when players can choose their sprite)
-    // player_context->sprite_right = game_manager_sprite_load(manager, "player_right_naked_10x10px.fxbm");
-    // player_context->sprite_left = game_manager_sprite_load(manager, "player_left_naked_10x10px.fxbm");
+    player_context->sprite_right = game_manager_sprite_load(manager, "player_right_naked_10x10px.fxbm");
+    player_context->sprite_left = game_manager_sprite_load(manager, "player_left_naked_10x10px.fxbm");
 
 
-    // save the player context to storage
-    // save_player_context(player_context);
+    // Assign loaded player context to game context
+    game_context->player_context = player_context;
 }
 }
 
 
 // Modify player_update to track direction
 // Modify player_update to track direction

+ 56 - 7
game/storage.c

@@ -204,6 +204,37 @@ bool save_player_context(PlayerContext *player_context)
     return true;
     return true;
 }
 }
 
 
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+// Helper function to load a string safely
+bool load_string(const char *path_name, char *buffer, size_t buffer_size)
+{
+    if (!path_name || !buffer || buffer_size == 0)
+    {
+        FURI_LOG_E(TAG, "Invalid arguments to load_string");
+        return false;
+    }
+
+    // Initialize buffer to zero
+    memset(buffer, 0, buffer_size);
+
+    if (!load_char(path_name, buffer, buffer_size))
+    {
+        FURI_LOG_E(TAG, "Failed to load string from path: %s", path_name);
+        return false;
+    }
+
+    // Ensure null-termination
+    buffer[buffer_size - 1] = '\0';
+
+    return true;
+}
+
 // Helper function to load an integer
 // Helper function to load an integer
 bool load_number(const char *path_name, int *value)
 bool load_number(const char *path_name, int *value)
 {
 {
@@ -214,12 +245,16 @@ bool load_number(const char *path_name, int *value)
     }
     }
 
 
     char buffer[32];
     char buffer[32];
+    memset(buffer, 0, sizeof(buffer)); // Initialize buffer
+
     if (!load_char(path_name, buffer, sizeof(buffer)))
     if (!load_char(path_name, buffer, sizeof(buffer)))
     {
     {
         FURI_LOG_E(TAG, "Failed to load number from path: %s", path_name);
         FURI_LOG_E(TAG, "Failed to load number from path: %s", path_name);
         return false;
         return false;
     }
     }
 
 
+    buffer[sizeof(buffer) - 1] = '\0'; // Ensure null-termination
+
     *value = atoi(buffer);
     *value = atoi(buffer);
     return true;
     return true;
 }
 }
@@ -234,15 +269,21 @@ bool load_float(const char *path_name, float *value)
     }
     }
 
 
     char buffer[32];
     char buffer[32];
+    memset(buffer, 0, sizeof(buffer)); // Initialize buffer
+
     if (!load_char(path_name, buffer, sizeof(buffer)))
     if (!load_char(path_name, buffer, sizeof(buffer)))
     {
     {
         FURI_LOG_E(TAG, "Failed to load float from path: %s", path_name);
         FURI_LOG_E(TAG, "Failed to load float from path: %s", path_name);
         return false;
         return false;
     }
     }
 
 
+    buffer[sizeof(buffer) - 1] = '\0'; // Ensure null-termination
+
     *value = strtof(buffer, NULL);
     *value = strtof(buffer, NULL);
     return true;
     return true;
 }
 }
+
+// Helper function to load an int8_t
 bool load_int8(const char *path_name, int8_t *value)
 bool load_int8(const char *path_name, int8_t *value)
 {
 {
     if (!path_name || !value)
     if (!path_name || !value)
@@ -252,12 +293,16 @@ bool load_int8(const char *path_name, int8_t *value)
     }
     }
 
 
     char buffer[32];
     char buffer[32];
+    memset(buffer, 0, sizeof(buffer)); // Initialize buffer
+
     if (!load_char(path_name, buffer, sizeof(buffer)))
     if (!load_char(path_name, buffer, sizeof(buffer)))
     {
     {
         FURI_LOG_E(TAG, "Failed to load int8 from path: %s", path_name);
         FURI_LOG_E(TAG, "Failed to load int8 from path: %s", path_name);
         return false;
         return false;
     }
     }
 
 
+    buffer[sizeof(buffer) - 1] = '\0'; // Ensure null-termination
+
     long temp = strtol(buffer, NULL, 10);
     long temp = strtol(buffer, NULL, 10);
     if (temp < INT8_MIN || temp > INT8_MAX)
     if (temp < INT8_MIN || temp > INT8_MAX)
     {
     {
@@ -268,6 +313,8 @@ bool load_int8(const char *path_name, int8_t *value)
     *value = (int8_t)temp;
     *value = (int8_t)temp;
     return true;
     return true;
 }
 }
+
+// Helper function to load a uint32_t
 bool load_uint32(const char *path_name, uint32_t *value)
 bool load_uint32(const char *path_name, uint32_t *value)
 {
 {
     if (!path_name || !value)
     if (!path_name || !value)
@@ -277,12 +324,16 @@ bool load_uint32(const char *path_name, uint32_t *value)
     }
     }
 
 
     char buffer[32];
     char buffer[32];
+    memset(buffer, 0, sizeof(buffer)); // Initialize buffer
+
     if (!load_char(path_name, buffer, sizeof(buffer)))
     if (!load_char(path_name, buffer, sizeof(buffer)))
     {
     {
         FURI_LOG_E(TAG, "Failed to load uint32 from path: %s", path_name);
         FURI_LOG_E(TAG, "Failed to load uint32 from path: %s", path_name);
         return false;
         return false;
     }
     }
 
 
+    buffer[sizeof(buffer) - 1] = '\0'; // Ensure null-termination
+
     *value = (uint32_t)strtoul(buffer, NULL, 10);
     *value = (uint32_t)strtoul(buffer, NULL, 10);
     return true;
     return true;
 }
 }
@@ -298,7 +349,7 @@ bool load_player_context(PlayerContext *player_context)
     // Load each field and check for success
     // Load each field and check for success
 
 
     // 1. Username (String)
     // 1. Username (String)
-    if (!load_char("player/username", player_context->username, sizeof(player_context->username)))
+    if (!load_string("player/username", player_context->username, sizeof(player_context->username)))
     {
     {
         FURI_LOG_E(TAG, "Failed to load player username");
         FURI_LOG_E(TAG, "Failed to load player username");
         return false;
         return false;
@@ -369,14 +420,13 @@ bool load_player_context(PlayerContext *player_context)
 
 
     // 11. Direction (enum PlayerDirection)
     // 11. Direction (enum PlayerDirection)
     {
     {
-        char direction_str[2];
-        if (!load_char("player/direction", direction_str, sizeof(direction_str)))
+        int direction_int = 0;
+        if (!load_number("player/direction", &direction_int))
         {
         {
             FURI_LOG_E(TAG, "Failed to load player direction");
             FURI_LOG_E(TAG, "Failed to load player direction");
             return false;
             return false;
         }
         }
 
 
-        int direction_int = atoi(direction_str);
         switch (direction_int)
         switch (direction_int)
         {
         {
         case 0:
         case 0:
@@ -400,14 +450,13 @@ bool load_player_context(PlayerContext *player_context)
 
 
     // 12. State (enum PlayerState)
     // 12. State (enum PlayerState)
     {
     {
-        char state_str[2];
-        if (!load_char("player/state", state_str, sizeof(state_str)))
+        int state_int = 0;
+        if (!load_number("player/state", &state_int))
         {
         {
             FURI_LOG_E(TAG, "Failed to load player state");
             FURI_LOG_E(TAG, "Failed to load player state");
             return false;
             return false;
         }
         }
 
 
-        int state_int = atoi(state_str);
         switch (state_int)
         switch (state_int)
         {
         {
         case 0:
         case 0: