level.c 3.5 KB

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