level.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. #include <game/level.h>
  2. static void level_start(Level *level, GameManager *manager, void *context)
  3. {
  4. UNUSED(manager);
  5. LevelContext *level_context = context;
  6. // check if the world exists
  7. if (!world_exists(level_context->id))
  8. {
  9. FURI_LOG_E("Game", "World does not exist.. downloading now");
  10. if (!level_context->app)
  11. {
  12. level_context->app = (FlipWorldApp *)malloc(sizeof(FlipWorldApp));
  13. if (!level_context->app)
  14. {
  15. FURI_LOG_E("Game", "Failed to allocate FlipWorldApp");
  16. return;
  17. }
  18. }
  19. FuriString *world_data = fetch_world(level_context->id, level_context->app);
  20. if (!world_data)
  21. {
  22. FURI_LOG_E("Game", "Failed to fetch world data");
  23. draw_town_world(level);
  24. free(level_context->app);
  25. level_context->app = NULL;
  26. return;
  27. }
  28. if (!draw_json_world(level, furi_string_get_cstr(world_data)))
  29. {
  30. FURI_LOG_E("Game", "Failed to draw world");
  31. draw_town_world(level);
  32. }
  33. free(level_context->app);
  34. level_context->app = NULL;
  35. furi_string_free(world_data);
  36. return;
  37. }
  38. // get the world data
  39. FuriString *world_data = load_furi_world(level_context->id);
  40. if (!world_data)
  41. {
  42. FURI_LOG_E("Game", "Failed to load world data");
  43. draw_town_world(level);
  44. return;
  45. }
  46. // draw the world
  47. if (!draw_json_world(level, furi_string_get_cstr(world_data)))
  48. {
  49. FURI_LOG_E("Game", "World exists but failed to draw.");
  50. draw_town_world(level);
  51. }
  52. furi_string_free(world_data);
  53. }
  54. static LevelContext *level_context_generic;
  55. static LevelContext *level_generic_alloc(const char *id, int index)
  56. {
  57. if (!level_context_generic)
  58. {
  59. level_context_generic = malloc(sizeof(LevelContext));
  60. }
  61. snprintf(level_context_generic->id, sizeof(level_context_generic->id), "%s", id);
  62. level_context_generic->index = index;
  63. level_context_generic->app = NULL;
  64. return level_context_generic;
  65. }
  66. static void level_generic_free()
  67. {
  68. if (level_context_generic)
  69. {
  70. free(level_context_generic);
  71. level_context_generic = NULL;
  72. }
  73. }
  74. static void level_alloc_generic_world(Level *level, GameManager *manager, void *context)
  75. {
  76. if (!level_context_generic)
  77. {
  78. FURI_LOG_E("Game", "Generic level context not set");
  79. return;
  80. }
  81. LevelContext *level_context = context;
  82. snprintf(level_context->id, sizeof(level_context->id), "%s", level_context_generic->id);
  83. level_context->index = level_context_generic->index;
  84. level_context->app = level_context_generic->app;
  85. player_spawn(level, manager);
  86. }
  87. // Do NOT touch (this is for dynamic level creation)
  88. const LevelBehaviour _generic_level = {
  89. .alloc = level_alloc_generic_world, // called once, when level allocated
  90. .free = NULL, // called once, when level freed
  91. .start = level_start, // called when level is changed to this level
  92. .stop = NULL, // called when level is changed from this level
  93. .context_size = sizeof(LevelContext), // size of level context, will be automatically allocated and freed
  94. };
  95. const LevelBehaviour *generic_level(const char *id, int index)
  96. {
  97. level_generic_free();
  98. level_context_generic = level_generic_alloc(id, index);
  99. return &_generic_level;
  100. }