Sfoglia il codice sorgente

Update json world parsing/loading

jblanked 1 anno fa
parent
commit
2f273c9ae5
6 ha cambiato i file con 166 aggiunte e 107 eliminazioni
  1. 93 1
      flip_storage/storage.c
  2. 7 1
      flip_storage/storage.h
  3. 14 2
      game/game.c
  4. 1 0
      game/game.h
  5. 48 101
      game/world.c
  6. 3 2
      game/world.h

+ 93 - 1
flip_storage/storage.c

@@ -267,4 +267,96 @@ bool load_world(
     furi_record_close(RECORD_STORAGE);
     furi_record_close(RECORD_STORAGE);
 
 
     return true;
     return true;
-}
+}
+
+FuriString *load_furi_world(
+    const char *name)
+{
+    Storage *storage = furi_record_open(RECORD_STORAGE);
+    File *file = storage_file_alloc(storage);
+    char file_path[256];
+    snprintf(file_path, sizeof(file_path), STORAGE_EXT_PATH_PREFIX "/apps_data/flip_world/worlds/%s.json", name);
+    // Open the file for reading
+    if (!storage_file_open(file, file_path, FSAM_READ, FSOM_OPEN_EXISTING))
+    {
+        storage_file_free(file);
+        furi_record_close(RECORD_STORAGE);
+        return NULL; // Return false if the file does not exist
+    }
+
+    // Allocate a FuriString to hold the received data
+    FuriString *str_result = furi_string_alloc();
+    if (!str_result)
+    {
+        FURI_LOG_E(HTTP_TAG, "Failed to allocate FuriString");
+        storage_file_close(file);
+        storage_file_free(file);
+        furi_record_close(RECORD_STORAGE);
+        return NULL;
+    }
+    // Reset the FuriString to ensure it's empty before reading
+    furi_string_reset(str_result);
+
+    // Define a buffer to hold the read data
+    uint8_t *buffer = (uint8_t *)malloc(MAX_FILE_SHOW);
+    if (!buffer)
+    {
+        FURI_LOG_E(HTTP_TAG, "Failed to allocate buffer");
+        furi_string_free(str_result);
+        storage_file_close(file);
+        storage_file_free(file);
+        furi_record_close(RECORD_STORAGE);
+        return NULL;
+    }
+
+    // Read data into the buffer
+    size_t read_count = storage_file_read(file, buffer, MAX_FILE_SHOW);
+    if (storage_file_get_error(file) != FSE_OK)
+    {
+        FURI_LOG_E(HTTP_TAG, "Error reading from file.");
+        furi_string_free(str_result);
+        storage_file_close(file);
+        storage_file_free(file);
+        furi_record_close(RECORD_STORAGE);
+        return NULL;
+    }
+
+    // Append each byte to the FuriString
+    for (size_t i = 0; i < read_count; i++)
+    {
+        furi_string_push_back(str_result, buffer[i]);
+    }
+
+    // Check if there is more data beyond the maximum size
+    char extra_byte;
+    storage_file_read(file, &extra_byte, 1);
+
+    // Clean up
+    storage_file_close(file);
+    storage_file_free(file);
+    furi_record_close(RECORD_STORAGE);
+    free(buffer);
+    return str_result;
+}
+
+bool world_exists(const char *name)
+{
+    if (!name)
+    {
+        FURI_LOG_E(TAG, "Invalid name");
+        return false;
+    }
+    Storage *storage = furi_record_open(RECORD_STORAGE);
+    if (!storage)
+    {
+        FURI_LOG_E(TAG, "Failed to open storage");
+        return false;
+    }
+    char file_path[256];
+    snprintf(file_path, sizeof(file_path), STORAGE_EXT_PATH_PREFIX "/apps_data/flip_world/worlds/%s.json", name);
+    bool does_exist = storage_file_exists(storage, file_path);
+
+    // Clean up
+    furi_record_close(RECORD_STORAGE);
+    return does_exist;
+}

+ 7 - 1
flip_storage/storage.h

@@ -31,4 +31,10 @@ bool save_world(
 bool load_world(
 bool load_world(
     const char *name,
     const char *name,
     char *json_data,
     char *json_data,
-    size_t json_data_size);
+    size_t json_data_size);
+
+FuriString *load_furi_world(
+    const char *name);
+
+bool world_exists(
+    const char *name);

+ 14 - 2
game/game.c

@@ -102,8 +102,20 @@ static void level_alloc(Level *level, GameManager *manager, void *context)
     // Add player entity to the level
     // Add player entity to the level
     player_spawn(level, manager);
     player_spawn(level, manager);
 
 
-    draw_tree_world(level);
-    // draw_example_world(level);
+    // check if tree world exists
+    if (!world_exists("tree_world"))
+    {
+        FURI_LOG_E("Game", "Tree world does not exist");
+        easy_flipper_dialog("[WORLD ERROR]", "No world data installed.\n\n\nSettings -> Game ->\nInstall Official World Pack");
+        draw_example_world(level);
+        return;
+    }
+
+    if (!draw_json_world_furi(level, load_furi_world("tree_world")))
+    {
+        FURI_LOG_E("Game", "Tree World exists but failed to draw.");
+        draw_example_world(level);
+    }
 }
 }
 
 
 static const LevelBehaviour level = {
 static const LevelBehaviour level = {

+ 1 - 0
game/game.h

@@ -2,6 +2,7 @@
 #include "engine/engine.h"
 #include "engine/engine.h"
 #include <game/world.h>
 #include <game/world.h>
 #include "flip_world.h"
 #include "flip_world.h"
+#include "flip_storage/storage.h"
 
 
 typedef struct
 typedef struct
 {
 {

+ 48 - 101
game/world.c

@@ -7,7 +7,53 @@ void draw_bounds(Canvas *canvas)
     canvas_draw_frame(canvas, -camera_x, -camera_y, WORLD_WIDTH, WORLD_HEIGHT);
     canvas_draw_frame(canvas, -camera_x, -camera_y, WORLD_WIDTH, WORLD_HEIGHT);
 }
 }
 
 
-bool draw_json_world(Level *level, FuriString *json_data)
+bool draw_json_world(Level *level, char *json_data)
+{
+    for (int i = 0; i < MAX_WORLD_OBJECTS; i++)
+    {
+        char *data = get_json_array_value("json_data", i, json_data, MAX_WORLD_TOKENS);
+        if (data == NULL)
+        {
+            break;
+        }
+        char *icon = get_json_value("icon", data, 64);
+        char *x = get_json_value("x", data, 64);
+        char *y = get_json_value("y", data, 64);
+        char *width = get_json_value("width", data, 64);
+        char *height = get_json_value("height", data, 64);
+        char *amount = get_json_value("amount", data, 64);
+        char *horizontal = get_json_value("horizontal", data, 64);
+        if (icon == NULL || x == NULL || y == NULL || width == NULL || height == NULL || amount == NULL || horizontal == NULL)
+        {
+            return false;
+        }
+        // if amount is less than 2, we spawn a single icon
+        if (atoi(amount) < 2)
+        {
+            spawn_icon(level, get_icon(icon), atoi(x), atoi(y), atoi(width), atoi(height));
+            free(data);
+            free(icon);
+            free(x);
+            free(y);
+            free(width);
+            free(height);
+            free(amount);
+            free(horizontal);
+            continue;
+        }
+        spawn_icon_line(level, get_icon(icon), atoi(x), atoi(y), atoi(width), atoi(height), atoi(amount), strcmp(horizontal, "true") == 0);
+        free(data);
+        free(icon);
+        free(x);
+        free(y);
+        free(width);
+        free(height);
+        free(amount);
+        free(horizontal);
+    }
+    return true;
+}
+bool draw_json_world_furi(Level *level, FuriString *json_data)
 {
 {
     for (int i = 0; i < MAX_WORLD_OBJECTS; i++)
     for (int i = 0; i < MAX_WORLD_OBJECTS; i++)
     {
     {
@@ -64,70 +110,6 @@ void draw_example_world(Level *level)
     spawn_icon(level, &I_icon_plant, 168, 32, 16, 16);
     spawn_icon(level, &I_icon_plant, 168, 32, 16, 16);
 }
 }
 
 
-/* JSON of the draw_example_world with fields icon, x, y, width, height
-{
-    "name": "Example World",
-    "author": "JBlanked",
-    "json_data": [
-        {
-            "icon": "earth",
-            "x": 112,
-            "y": 56,
-            "width": 15,
-            "height": 16,
-            "amount": 1,
-            "horizontal": true
-        },
-        {
-            "icon": "home",
-            "x": 128,
-            "y": 24,
-            "width": 15,
-            "height": 16,
-            "amount": 1,
-            "horizontal": true
-        },
-        {
-            "icon": "info",
-            "x": 144,
-            "y": 24,
-            "width": 15,
-            "height": 16,
-            "amount": 1,
-            "horizontal": true
-        },
-        {
-            "icon": "man",
-            "x": 160,
-            "y": 56,
-            "width": 7,
-            "height": 16,
-            "amount": 1,
-            "horizontal": true
-        },
-        {
-            "icon": "woman",
-            "x": 168,
-            "y": 56,
-            "width": 9,
-            "height": 16,
-            "amount": 1,
-            "horizontal": true
-        },
-        {
-            "icon": "plant",
-            "x": 168,
-            "y": 32,
-            "width": 16,
-            "height": 16,
-            "amount": 1,
-            "horizontal": true
-        }
-    ]
-}
-
-*/
-
 void draw_tree_world(Level *level)
 void draw_tree_world(Level *level)
 {
 {
     // Spawn two full left/up tree lines
     // Spawn two full left/up tree lines
@@ -185,39 +167,4 @@ void draw_tree_world(Level *level)
     spawn_icon_line(level, &I_icon_tree, 5, 2 + 8 * 17, 16, 16, 3, true);           // 3 left
     spawn_icon_line(level, &I_icon_tree, 5, 2 + 8 * 17, 16, 16, 3, true);           // 3 left
     spawn_icon_line(level, &I_icon_tree, 5 + 5 * 17, 2 + 8 * 17, 16, 16, 1, true);  // 1 middle
     spawn_icon_line(level, &I_icon_tree, 5 + 5 * 17, 2 + 8 * 17, 16, 16, 1, true);  // 1 middle
     spawn_icon_line(level, &I_icon_tree, 5 + 11 * 17, 2 + 8 * 17, 16, 16, 3, true); // 3 right
     spawn_icon_line(level, &I_icon_tree, 5 + 11 * 17, 2 + 8 * 17, 16, 16, 3, true); // 3 right
-}
-
-/* JSON of the draw_tree_world
-{
-    "name" : "tree_world",
-    "author" : "JBlanked",
-    "json_data" : [
-        {"icon" : "tree", "x" : 5, "y" : 2, "width" : 16, "height" : 16, "amount" : 22, "horizontal" : true},
-        {"icon" : "tree", "x" : 5, "y" : 2, "width" : 16, "height" : 16, "amount" : 11, "horizontal" : false},
-        {"icon" : "tree", "x" : 22, "y" : 2, "width" : 16, "height" : 16, "amount" : 22, "horizontal" : true},
-        {"icon" : "tree", "x" : 22, "y" : 2, "width" : 16, "height" : 16, "amount" : 11, "horizontal" : false},
-        {"icon" : "tree", "x" : 5, "y" : 155, "width" : 16, "height" : 16, "amount" : 22, "horizontal" : true},
-        {"icon" : "tree", "x" : 5, "y" : 172, "width" : 16, "height" : 16, "amount" : 22, "horizontal" : true},
-        {"icon" : "tree", "x" : 345, "y" : 50, "width" : 16, "height" : 16, "amount" : 8, "horizontal" : false},
-        {"icon" : "tree", "x" : 362, "y" : 50, "width" : 16, "height" : 16, "amount" : 8, "horizontal" : false},
-        {"icon" : "tree", "x" : 5, "y" : 36, "width" : 16, "height" : 16, "amount" : 14, "horizontal" : true},
-        {"icon" : "tree", "x" : 277, "y" : 36, "width" : 16, "height" : 16, "amount" : 3, "horizontal" : true},
-        {"icon" : "tree", "x" : 5, "y" : 53, "width" : 16, "height" : 16, "amount" : 3, "horizontal" : true},
-        {"icon" : "tree", "x" : 124, "y" : 53, "width" : 16, "height" : 16, "amount" : 6, "horizontal" : true},
-        {"icon" : "tree", "x" : 260, "y" : 53, "width" : 16, "height" : 16, "amount" : 4, "horizontal" : true},
-        {"icon" : "tree", "x" : 5, "y" : 70, "width" : 16, "height" : 16, "amount" : 6, "horizontal" : true},
-        {"icon" : "tree", "x" : 124, "y" : 70, "width" : 16, "height" : 16, "amount" : 7, "horizontal" : true},
-        {"icon" : "tree", "x" : 5, "y" : 87, "width" : 16, "height" : 16, "amount" : 5, "horizontal" : true},
-        {"icon" : "tree", "x" : 124, "y" : 87, "width" : 16, "height" : 16, "amount" : 3, "horizontal" : true},
-        {"icon" : "tree", "x" : 260, "y" : 87, "width" : 16, "height" : 16, "amount" : 7, "horizontal" : true},
-        {"icon" : "tree", "x" : 107, "y" : 104, "width" : 16, "height" : 16, "amount" : 7, "horizontal" : true},
-        {"icon" : "tree", "x" : 243, "y" : 104, "width" : 16, "height" : 16, "amount" : 4, "horizontal" : true},
-        {"icon" : "tree", "x" : 5, "y" : 121, "width" : 16, "height" : 16, "amount" : 4, "horizontal" : true},
-        {"icon" : "tree", "x" : 124, "y" : 121, "width" : 16, "height" : 16, "amount" : 3, "horizontal" : true},
-        {"icon" : "tree", "x" : 260, "y" : 121, "width" : 16, "height" : 16, "amount" : 4, "horizontal" : true},
-        {"icon" : "tree", "x" : 5, "y" : 138, "width" : 16, "height" : 16, "amount" : 3, "horizontal" : true},
-        {"icon" : "tree", "x" : 90, "y" : 138, "width" : 16, "height" : 16, "amount" : 1, "horizontal" : true},
-        {"icon" : "tree", "x" : 192, "y" : 138, "width" : 16, "height" : 16, "amount" : 3, "horizontal" : true}
-    ]
-}
-*/
+}

+ 3 - 2
game/world.h

@@ -12,8 +12,9 @@
 #define MAX_WORLD_OBJECTS 100
 #define MAX_WORLD_OBJECTS 100
 
 
 // Maximum number of world tokens
 // Maximum number of world tokens
-#define MAX_WORLD_TOKENS 512
+#define MAX_WORLD_TOKENS 1024
 void draw_bounds(Canvas *canvas);
 void draw_bounds(Canvas *canvas);
 void draw_example_world(Level *level);
 void draw_example_world(Level *level);
 void draw_tree_world(Level *level);
 void draw_tree_world(Level *level);
-bool draw_json_world(Level *level, FuriString *json_data);
+bool draw_json_world(Level *level, char *json_data);
+bool draw_json_world_furi(Level *level, FuriString *json_data);