level.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. #include <game/level.h>
  2. #include <flip_storage/storage.h>
  3. static void level_start(Level *level, GameManager *manager, void *context)
  4. {
  5. UNUSED(manager);
  6. if (!level || !context)
  7. {
  8. FURI_LOG_E("Game", "Level or context is NULL");
  9. return;
  10. }
  11. level_clear(level);
  12. player_spawn(level, manager);
  13. LevelContext *level_context = context;
  14. // check if the world exists
  15. if (!world_exists(level_context->id))
  16. {
  17. FURI_LOG_E("Game", "World does not exist.. downloading now");
  18. FuriString *world_data = fetch_world(level_context->id);
  19. if (!world_data)
  20. {
  21. FURI_LOG_E("Game", "Failed to fetch world data");
  22. draw_tree_world(level);
  23. return;
  24. }
  25. if (!draw_json_world(level, furi_string_get_cstr(world_data)))
  26. {
  27. FURI_LOG_E("Game", "Failed to draw world");
  28. draw_tree_world(level);
  29. }
  30. // world_data is guaranteed non-NULL here
  31. furi_string_free(world_data);
  32. return;
  33. }
  34. // get the world data
  35. FuriString *world_data = load_furi_world(level_context->id);
  36. if (!world_data)
  37. {
  38. FURI_LOG_E("Game", "Failed to load world data");
  39. draw_tree_world(level);
  40. return;
  41. }
  42. // draw the world
  43. if (!draw_json_world(level, furi_string_get_cstr(world_data)))
  44. {
  45. FURI_LOG_E("Game", "World exists but failed to draw.");
  46. draw_tree_world(level);
  47. }
  48. // world_data is guaranteed non-NULL here
  49. furi_string_free(world_data);
  50. }
  51. static LevelContext *level_context_generic;
  52. static LevelContext *level_generic_alloc(const char *id, int index)
  53. {
  54. if (level_context_generic == NULL)
  55. {
  56. level_context_generic = malloc(sizeof(LevelContext));
  57. }
  58. snprintf(level_context_generic->id, sizeof(level_context_generic->id), "%s", id);
  59. level_context_generic->index = index;
  60. return level_context_generic;
  61. }
  62. static void level_generic_free()
  63. {
  64. if (level_context_generic != NULL)
  65. {
  66. free(level_context_generic);
  67. level_context_generic = NULL;
  68. }
  69. }
  70. static void level_free(Level *level, GameManager *manager, void *context)
  71. {
  72. UNUSED(level);
  73. UNUSED(manager);
  74. UNUSED(context);
  75. level_generic_free();
  76. }
  77. static void level_alloc_generic_world(Level *level, GameManager *manager, void *context)
  78. {
  79. UNUSED(manager);
  80. UNUSED(level);
  81. if (!level_context_generic)
  82. {
  83. FURI_LOG_E("Game", "Generic level context not set");
  84. return;
  85. }
  86. if (!context)
  87. {
  88. FURI_LOG_E("Game", "Context is NULL");
  89. return;
  90. }
  91. LevelContext *level_context = context;
  92. snprintf(level_context->id, sizeof(level_context->id), "%s", level_context_generic->id);
  93. level_context->index = level_context_generic->index;
  94. }
  95. const LevelBehaviour _generic_level = {
  96. .alloc = level_alloc_generic_world,
  97. .free = level_free,
  98. .start = level_start,
  99. .stop = NULL,
  100. .context_size = sizeof(LevelContext),
  101. };
  102. const LevelBehaviour *generic_level(const char *id, int index)
  103. {
  104. // free any old context before allocating a new one
  105. level_generic_free();
  106. level_context_generic = level_generic_alloc(id, index);
  107. return &_generic_level;
  108. }