Procházet zdrojové kódy

check each player field when loading

jblanked před 1 rokem
rodič
revize
13d20fc682
2 změnil soubory, kde provedl 421 přidání a 105 odebrání
  1. 1 1
      flip_storage/storage.c
  2. 420 104
      game/storage.c

+ 1 - 1
flip_storage/storage.c

@@ -249,7 +249,7 @@ bool load_char(
     storage_file_free(file);
     furi_record_close(RECORD_STORAGE);
 
-    return true;
+    return strlen(value) > 0;
 }
 
 bool save_world(

+ 420 - 104
game/storage.c

@@ -2,6 +2,12 @@
 #include <stdio.h>
 #include <furi.h>
 #include <furi_hal.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
 
 bool save_uint32(const char *path_name, uint32_t value)
 {
@@ -204,13 +210,6 @@ bool save_player_context(PlayerContext *player_context)
     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)
 {
@@ -220,18 +219,12 @@ bool load_string(const char *path_name, char *buffer, size_t buffer_size)
         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;
 }
 
@@ -244,8 +237,7 @@ bool load_number(const char *path_name, int *value)
         return false;
     }
 
-    char buffer[32];
-    memset(buffer, 0, sizeof(buffer)); // Initialize buffer
+    char buffer[64];
 
     if (!load_char(path_name, buffer, sizeof(buffer)))
     {
@@ -253,8 +245,6 @@ bool load_number(const char *path_name, int *value)
         return false;
     }
 
-    buffer[sizeof(buffer) - 1] = '\0'; // Ensure null-termination
-
     *value = atoi(buffer);
     return true;
 }
@@ -268,18 +258,22 @@ bool load_float(const char *path_name, float *value)
         return false;
     }
 
-    char buffer[32];
-    memset(buffer, 0, sizeof(buffer)); // Initialize buffer
-
+    char buffer[64];
     if (!load_char(path_name, buffer, sizeof(buffer)))
     {
         FURI_LOG_E(TAG, "Failed to load float from path: %s", path_name);
         return false;
     }
 
-    buffer[sizeof(buffer) - 1] = '\0'; // Ensure null-termination
+    // check if the string is a valid float
+    char *endptr;
+    *value = strtof(buffer, &endptr);
+    if (endptr == buffer)
+    {
+        FURI_LOG_E(TAG, "Failed to parse float from path: %s", path_name);
+        return false;
+    }
 
-    *value = strtof(buffer, NULL);
     return true;
 }
 
@@ -292,8 +286,7 @@ bool load_int8(const char *path_name, int8_t *value)
         return false;
     }
 
-    char buffer[32];
-    memset(buffer, 0, sizeof(buffer)); // Initialize buffer
+    char buffer[64];
 
     if (!load_char(path_name, buffer, sizeof(buffer)))
     {
@@ -301,8 +294,6 @@ bool load_int8(const char *path_name, int8_t *value)
         return false;
     }
 
-    buffer[sizeof(buffer) - 1] = '\0'; // Ensure null-termination
-
     long temp = strtol(buffer, NULL, 10);
     if (temp < INT8_MIN || temp > INT8_MAX)
     {
@@ -310,7 +301,14 @@ bool load_int8(const char *path_name, int8_t *value)
         return false;
     }
 
-    *value = (int8_t)temp;
+    // check if the string is a valid int8
+    char *endptr;
+    *value = (int8_t)strtol(buffer, &endptr, 10);
+    if (endptr == buffer)
+    {
+        FURI_LOG_E(TAG, "Failed to parse int8 from path: %s", path_name);
+        return false;
+    }
     return true;
 }
 
@@ -323,18 +321,387 @@ bool load_uint32(const char *path_name, uint32_t *value)
         return false;
     }
 
-    char buffer[32];
-    memset(buffer, 0, sizeof(buffer)); // Initialize buffer
-
+    char buffer[64];
     if (!load_char(path_name, buffer, sizeof(buffer)))
     {
         FURI_LOG_E(TAG, "Failed to load uint32 from path: %s", path_name);
         return false;
     }
 
-    buffer[sizeof(buffer) - 1] = '\0'; // Ensure null-termination
+    // check if the string is a valid uint32
+    char *endptr;
+    *value = strtoul(buffer, &endptr, 10);
+    if (endptr == buffer)
+    {
+        FURI_LOG_E(TAG, "Failed to parse uint32 from path: %s", path_name);
+        return false;
+    }
+
+    return true;
+}
+
+// 1. Username (String)
+static bool load_player_username(char *username, size_t username_size)
+{
+    if (!username || username_size == 0)
+    {
+        FURI_LOG_E(TAG, "Invalid username buffer");
+        return false;
+    }
+
+    // Try to load the string
+    if (!load_string("player/username", username, username_size))
+    {
+        // If loading failed, log a warning and set a default
+        FURI_LOG_W(TAG, "No data or parse error for username. Using default: 'Unknown'");
+        memset(username, 0, username_size);
+        strncpy(username, "Unknown", username_size - 1);
+    }
+
+    // Always return true unless pointer was invalid
+    return true;
+}
+
+// 2. Level (uint32_t)
+static bool load_player_level(uint32_t *level)
+{
+    if (!level)
+    {
+        FURI_LOG_E(TAG, "Invalid level pointer");
+        return false;
+    }
+
+    uint32_t temp = 1; // Default
+    if (!load_uint32("player/level", &temp))
+    {
+        FURI_LOG_W(TAG, "No data or parse error for level. Using default: 1");
+        temp = 1;
+    }
+
+    *level = temp;
+    return true;
+}
+
+// 3. XP (uint32_t)
+static bool load_player_xp(uint32_t *xp)
+{
+    if (!xp)
+    {
+        FURI_LOG_E(TAG, "Invalid xp pointer");
+        return false;
+    }
+
+    uint32_t temp = 0; // Default
+    if (!load_uint32("player/xp", &temp))
+    {
+        FURI_LOG_W(TAG, "No data or parse error for xp. Using default: 0");
+        temp = 0;
+    }
+
+    *xp = temp;
+    return true;
+}
+
+// 4. Health (uint32_t)
+static bool load_player_health(uint32_t *health)
+{
+    if (!health)
+    {
+        FURI_LOG_E(TAG, "Invalid health pointer");
+        return false;
+    }
+
+    uint32_t temp = 100; // Default
+    if (!load_uint32("player/health", &temp))
+    {
+        FURI_LOG_W(TAG, "No data or parse error for health. Using default: 100");
+        temp = 100;
+    }
 
-    *value = (uint32_t)strtoul(buffer, NULL, 10);
+    *health = temp;
+    return true;
+}
+
+// 5. Strength (uint32_t)
+static bool load_player_strength(uint32_t *strength)
+{
+    if (!strength)
+    {
+        FURI_LOG_E(TAG, "Invalid strength pointer");
+        return false;
+    }
+
+    uint32_t temp = 10; // Default
+    if (!load_uint32("player/strength", &temp))
+    {
+        FURI_LOG_W(TAG, "No data or parse error for strength. Using default: 10");
+        temp = 10;
+    }
+
+    *strength = temp;
+    return true;
+}
+
+// 6. Max Health (uint32_t)
+static bool load_player_max_health(uint32_t *max_health)
+{
+    if (!max_health)
+    {
+        FURI_LOG_E(TAG, "Invalid max_health pointer");
+        return false;
+    }
+
+    uint32_t temp = 100; // Default
+    if (!load_uint32("player/max_health", &temp))
+    {
+        FURI_LOG_W(TAG, "No data or parse error for max_health. Using default: 100");
+        temp = 100;
+    }
+
+    *max_health = temp;
+    return true;
+}
+
+// 7. Health Regen (uint32_t)
+static bool load_player_health_regen(uint32_t *health_regen)
+{
+    if (!health_regen)
+    {
+        FURI_LOG_E(TAG, "Invalid health_regen pointer");
+        return false;
+    }
+
+    uint32_t temp = 1; // Default
+    if (!load_uint32("player/health_regen", &temp))
+    {
+        FURI_LOG_W(TAG, "No data or parse error for health_regen. Using default: 0");
+        temp = 1;
+    }
+
+    *health_regen = temp;
+    return true;
+}
+
+// 8. Elapsed Health Regen (float)
+static bool load_player_elapsed_health_regen(float *elapsed_health_regen)
+{
+    if (!elapsed_health_regen)
+    {
+        FURI_LOG_E(TAG, "Invalid elapsed_health_regen pointer");
+        return false;
+    }
+
+    float temp = 0.0f; // Default
+    if (!load_float("player/elapsed_health_regen", &temp))
+    {
+        FURI_LOG_W(TAG, "No data or parse error for elapsed_health_regen. Using default: 0.0f");
+        temp = 0.0f;
+    }
+
+    *elapsed_health_regen = temp;
+    return true;
+}
+
+// 9. Attack Timer (float)
+static bool load_player_attack_timer(float *attack_timer)
+{
+    if (!attack_timer)
+    {
+        FURI_LOG_E(TAG, "Invalid attack_timer pointer");
+        return false;
+    }
+
+    float temp = 0.1f; // Default
+    if (!load_float("player/attack_timer", &temp))
+    {
+        FURI_LOG_W(TAG, "No data or parse error for attack_timer. Using default: 0.0f");
+        temp = 0.1f;
+    }
+
+    *attack_timer = temp;
+    return true;
+}
+
+// 10. Elapsed Attack Timer (float)
+static bool load_player_elapsed_attack_timer(float *elapsed_attack_timer)
+{
+    if (!elapsed_attack_timer)
+    {
+        FURI_LOG_E(TAG, "Invalid elapsed_attack_timer pointer");
+        return false;
+    }
+
+    float temp = 0.0f; // Default
+    if (!load_float("player/elapsed_attack_timer", &temp))
+    {
+        FURI_LOG_W(TAG, "No data or parse error for elapsed_attack_timer. Using default: 0.0f");
+        temp = 0.0f;
+    }
+
+    *elapsed_attack_timer = temp;
+    return true;
+}
+
+// 11. Direction (enum PlayerDirection)
+static bool load_player_direction(PlayerDirection *direction)
+{
+    if (!direction)
+    {
+        FURI_LOG_E(TAG, "Invalid direction pointer");
+        return false;
+    }
+
+    // Default to 3 -> PLAYER_RIGHT (adjust if you prefer another default)
+    int direction_int = 3;
+    if (!load_number("player/direction", &direction_int))
+    {
+        FURI_LOG_W(TAG, "No data or parse error for direction. Defaulting to PLAYER_RIGHT");
+        direction_int = 3;
+    }
+
+    switch (direction_int)
+    {
+    case 0:
+        *direction = PLAYER_UP;
+        break;
+    case 1:
+        *direction = PLAYER_DOWN;
+        break;
+    case 2:
+        *direction = PLAYER_LEFT;
+        break;
+    case 3:
+        *direction = PLAYER_RIGHT;
+        break;
+    default:
+        FURI_LOG_W(TAG, "Invalid direction value: %d. Defaulting to PLAYER_RIGHT", direction_int);
+        *direction = PLAYER_RIGHT;
+        break;
+    }
+
+    return true;
+}
+
+// 12. State (enum PlayerState)
+static bool load_player_state(PlayerState *state)
+{
+    if (!state)
+    {
+        FURI_LOG_E(TAG, "Invalid state pointer");
+        return false;
+    }
+
+    // Default to 0 -> PLAYER_IDLE
+    int state_int = 0;
+    if (!load_number("player/state", &state_int))
+    {
+        FURI_LOG_W(TAG, "No data or parse error for state. Defaulting to PLAYER_IDLE");
+        state_int = 0;
+    }
+
+    switch (state_int)
+    {
+    case 0:
+        *state = PLAYER_IDLE;
+        break;
+    case 1:
+        *state = PLAYER_MOVING;
+        break;
+    case 2:
+        *state = PLAYER_ATTACKING;
+        break;
+    case 3:
+        *state = PLAYER_ATTACKED;
+        break;
+    case 4:
+        *state = PLAYER_DEAD;
+        break;
+    default:
+        FURI_LOG_W(TAG, "Invalid state value: %d. Defaulting to PLAYER_IDLE", state_int);
+        *state = PLAYER_IDLE;
+        break;
+    }
+
+    return true;
+}
+
+// 13. Start Position X (float)
+static bool load_player_start_position_x(float *start_position_x)
+{
+    if (!start_position_x)
+    {
+        FURI_LOG_E(TAG, "Invalid start_position_x pointer");
+        return false;
+    }
+
+    float temp = 192.0f; // Default
+    if (!load_float("player/start_position_x", &temp))
+    {
+        FURI_LOG_W(TAG, "No data or parse error for start_position_x. Using default: 0.0f");
+        temp = 192.0f;
+    }
+
+    *start_position_x = temp;
+    return true;
+}
+
+// 14. Start Position Y (float)
+static bool load_player_start_position_y(float *start_position_y)
+{
+    if (!start_position_y)
+    {
+        FURI_LOG_E(TAG, "Invalid start_position_y pointer");
+        return false;
+    }
+
+    float temp = 96.0f; // Default
+    if (!load_float("player/start_position_y", &temp))
+    {
+        FURI_LOG_W(TAG, "No data or parse error for start_position_y. Using default: 0.0f");
+        temp = 96.0f;
+    }
+
+    *start_position_y = temp;
+    return true;
+}
+
+// 15. dx (int8_t)
+static bool load_player_dx(int8_t *dx)
+{
+    if (!dx)
+    {
+        FURI_LOG_E(TAG, "Invalid dx pointer");
+        return false;
+    }
+
+    int8_t temp = 1; // Default
+    if (!load_int8("player/dx", &temp))
+    {
+        FURI_LOG_W(TAG, "No data or parse error for dx. Using default: 0");
+        temp = 1;
+    }
+
+    *dx = temp;
+    return true;
+}
+
+// 16. dy (int8_t)
+static bool load_player_dy(int8_t *dy)
+{
+    if (!dy)
+    {
+        FURI_LOG_E(TAG, "Invalid dy pointer");
+        return false;
+    }
+
+    int8_t temp = 0; // Default
+    if (!load_int8("player/dy", &temp))
+    {
+        FURI_LOG_W(TAG, "No data or parse error for dy. Using default: 0");
+        temp = 0;
+    }
+
+    *dy = temp;
     return true;
 }
 
@@ -342,168 +709,117 @@ bool load_player_context(PlayerContext *player_context)
 {
     if (!player_context)
     {
-        FURI_LOG_E(TAG, "Player context is NULL");
+        FURI_LOG_E(TAG, "Invalid player context");
         return false;
     }
 
-    // Load each field and check for success
-
     // 1. Username (String)
-    if (!load_string("player/username", player_context->username, sizeof(player_context->username)))
+    if (!load_player_username(player_context->username, sizeof(player_context->username)))
     {
         FURI_LOG_E(TAG, "Failed to load player username");
         return false;
     }
 
     // 2. Level (uint32_t)
-    if (!load_uint32("player/level", &player_context->level))
+    if (!load_player_level(&player_context->level))
     {
         FURI_LOG_E(TAG, "Failed to load player level");
         return false;
     }
 
     // 3. XP (uint32_t)
-    if (!load_uint32("player/xp", &player_context->xp))
+    if (!load_player_xp(&player_context->xp))
     {
         FURI_LOG_E(TAG, "Failed to load player xp");
         return false;
     }
 
     // 4. Health (uint32_t)
-    if (!load_uint32("player/health", &player_context->health))
+    if (!load_player_health(&player_context->health))
     {
         FURI_LOG_E(TAG, "Failed to load player health");
         return false;
     }
 
     // 5. Strength (uint32_t)
-    if (!load_uint32("player/strength", &player_context->strength))
+    if (!load_player_strength(&player_context->strength))
     {
         FURI_LOG_E(TAG, "Failed to load player strength");
         return false;
     }
 
     // 6. Max Health (uint32_t)
-    if (!load_uint32("player/max_health", &player_context->max_health))
+    if (!load_player_max_health(&player_context->max_health))
     {
         FURI_LOG_E(TAG, "Failed to load player max health");
         return false;
     }
 
     // 7. Health Regen (uint32_t)
-    if (!load_uint32("player/health_regen", &player_context->health_regen))
+    if (!load_player_health_regen(&player_context->health_regen))
     {
         FURI_LOG_E(TAG, "Failed to load player health regen");
         return false;
     }
 
     // 8. Elapsed Health Regen (float)
-    if (!load_float("player/elapsed_health_regen", &player_context->elapsed_health_regen))
+    if (!load_player_elapsed_health_regen(&player_context->elapsed_health_regen))
     {
         FURI_LOG_E(TAG, "Failed to load player elapsed health regen");
         return false;
     }
 
     // 9. Attack Timer (float)
-    if (!load_float("player/attack_timer", &player_context->attack_timer))
+    if (!load_player_attack_timer(&player_context->attack_timer))
     {
         FURI_LOG_E(TAG, "Failed to load player attack timer");
         return false;
     }
 
     // 10. Elapsed Attack Timer (float)
-    if (!load_float("player/elapsed_attack_timer", &player_context->elapsed_attack_timer))
+    if (!load_player_elapsed_attack_timer(&player_context->elapsed_attack_timer))
     {
         FURI_LOG_E(TAG, "Failed to load player elapsed attack timer");
         return false;
     }
 
     // 11. Direction (enum PlayerDirection)
+    if (!load_player_direction(&player_context->direction))
     {
-        int direction_int = 0;
-        if (!load_number("player/direction", &direction_int))
-        {
-            FURI_LOG_E(TAG, "Failed to load player direction");
-            return false;
-        }
-
-        switch (direction_int)
-        {
-        case 0:
-            player_context->direction = PLAYER_UP;
-            break;
-        case 1:
-            player_context->direction = PLAYER_DOWN;
-            break;
-        case 2:
-            player_context->direction = PLAYER_LEFT;
-            break;
-        case 3:
-            player_context->direction = PLAYER_RIGHT;
-            break;
-        default:
-            FURI_LOG_E(TAG, "Invalid direction value: %d", direction_int);
-            player_context->direction = PLAYER_RIGHT; // Default value
-            break;
-        }
+        FURI_LOG_E(TAG, "Failed to load player direction");
+        return false;
     }
 
     // 12. State (enum PlayerState)
+    if (!load_player_state(&player_context->state))
     {
-        int state_int = 0;
-        if (!load_number("player/state", &state_int))
-        {
-            FURI_LOG_E(TAG, "Failed to load player state");
-            return false;
-        }
-
-        switch (state_int)
-        {
-        case 0:
-            player_context->state = PLAYER_IDLE;
-            break;
-        case 1:
-            player_context->state = PLAYER_MOVING;
-            break;
-        case 2:
-            player_context->state = PLAYER_ATTACKING;
-            break;
-        case 3:
-            player_context->state = PLAYER_ATTACKED;
-            break;
-        case 4:
-            player_context->state = PLAYER_DEAD; // Assuming '4' represents 'dead' or similar
-            break;
-        default:
-            FURI_LOG_E(TAG, "Invalid state value: %d", state_int);
-            player_context->state = PLAYER_IDLE; // Default value
-            break;
-        }
+        FURI_LOG_E(TAG, "Failed to load player state");
+        return false;
     }
 
     // 13. Start Position X (float)
-    if (!load_float("player/start_position_x", &player_context->start_position.x))
+    if (!load_player_start_position_x(&player_context->start_position.x))
     {
         FURI_LOG_E(TAG, "Failed to load player start position x");
         return false;
     }
 
     // 14. Start Position Y (float)
-    if (!load_float("player/start_position_y", &player_context->start_position.y))
+    if (!load_player_start_position_y(&player_context->start_position.y))
     {
         FURI_LOG_E(TAG, "Failed to load player start position y");
         return false;
     }
 
     // 15. dx (int8_t)
-    if (!load_int8("player/dx", &player_context->dx))
+    if (!load_player_dx(&player_context->dx))
     {
         FURI_LOG_E(TAG, "Failed to load player dx");
         return false;
     }
 
     // 16. dy (int8_t)
-    if (!load_int8("player/dy", &player_context->dy))
+    if (!load_player_dy(&player_context->dy))
     {
         FURI_LOG_E(TAG, "Failed to load player dy");
         return false;